diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index 420173781..000000000
--- a/.babelrc
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "presets": ["es2015", "stage-0", "react"],
- "env": {
- "development": {
- "plugins": [
- ["react-transform", {
- "transforms": [{
- "transform": "react-transform-hmr",
- "imports": ["react"],
- "locals": ["module"]
- }, {
- "transform": "react-transform-catch-errors",
- "imports": ["react", "redbox-react"]
- }]
- }]
- ]
- }
- }
-}
diff --git a/.eslintrc b/.eslintrc
deleted file mode 100644
index aeaa0b404..000000000
--- a/.eslintrc
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "parser": "babel-eslint",
- "extends": "airbnb",
- "env": {
- "browser": true,
- "node": true,
- "jest": true,
- "es6": true
- },
- "plugins": ["compat"],
- "rules": {
- "compat/compat": 2,
- "func-names": "off",
- "global-require": "off",
- "no-use-before-define": 0,
- "no-underscore-dangle": 0,
- "react/sort-prop-types": 2,
- "react/jsx-no-bind": 2,
- "react/require-default-props": 0,
- "react/no-find-dom-node": 0,
- "react/jsx-filename-extension": 0,
- "import/prefer-default-export": 0,
- "jsx-a11y/no-static-element-interactions": 0,
- "jsx-a11y/label-has-for": 0,
- "import/no-extraneous-dependencies": [
- "error", {
- "devDependencies": true,
- "optionalDependencies": false,
- "peerDependencies": false
- }
- ]
- }
-}
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 000000000..268379270
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,52 @@
+module.exports = {
+ parser: 'babel-eslint',
+ parserOptions: {
+ ecmaVersion: 6
+ },
+ extends: 'airbnb',
+ env: {
+ browser: true,
+ es6: true,
+ jest: true,
+ node: true
+ },
+ plugins: [
+ 'compat',
+ 'import',
+ 'jest',
+ 'jsx-a11y',
+ 'react'
+ ],
+ rules: {
+ 'compat/compat': 'error',
+ 'func-names': 'off',
+ 'global-require': 'off',
+ 'import/prefer-default-export': 'off',
+ 'import/no-extraneous-dependencies': [
+ 'error',
+ {
+ devDependencies: true,
+ optionalDependencies: false,
+ peerDependencies: false
+ }
+ ],
+ 'jsx-a11y/click-events-have-key-events': 'off',
+ 'jsx-a11y/label-has-for': 'off',
+ 'jsx-a11y/label-has-associated-control': [
+ 'error', {
+ depth: 3,
+ },
+ ],
+ 'jsx-a11y/no-noninteractive-element-interactions': 'off',
+ 'jsx-a11y/no-noninteractive-tabindex': 'off',
+ 'jsx-a11y/no-static-element-interactions': 'off',
+ 'no-underscore-dangle': 'off',
+ 'no-use-before-define': 'off',
+ 'react/destructuring-assignment': 'off',
+ 'react/jsx-filename-extension': 'off',
+ 'react/jsx-no-bind': 'error',
+ 'react/no-find-dom-node': 'off',
+ 'react/require-default-props': 'off',
+ 'react/sort-prop-types': 'error'
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 5aba682b1..6a870dda2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,43 @@
-lib
+# See https://help.github.com/ignore-files/ for more about ignoring files.
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+deploy.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Production
build
-node_modules
-npm-debug.log
-.idea
+dist
+out
+lib
+
+# Dependency directories
+node_modules/
+
+# App directories
+public/styles
+public/js/*
+!public/js/plugins
+
+# OS files
.DS_Store
+._*
+
+# Config files
+.env
+
+# IDE files
+.idea
+.vscode
+
+# Test coverage folder
+.coverage
+/coverage
\ No newline at end of file
diff --git a/.lintstagedrc b/.lintstagedrc
deleted file mode 100644
index 8a2904f4d..000000000
--- a/.lintstagedrc
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "*.js": [
- "eslint --fix",
- "git add"
- ],
- "*.scss": "sass-lint --max-warnings 0 -v"
-}
diff --git a/.nvmrc b/.nvmrc
index 6b9255cf0..758bb9c82 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-6.9.2
+7.10.0
diff --git a/.stylelintrc b/.stylelintrc
deleted file mode 100644
index edc4ab556..000000000
--- a/.stylelintrc
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "extends": "stylelint-config-standard",
- "plugins": [
- "stylelint-order"
- ],
- "rules": {
- "at-rule-no-unknown": [true, {
- ignoreAtRules: ["define-mixin", "mixin", "each"]
- }],
- "property-no-unknown": [ true, {
- "ignoreProperties": [
- "composes",
- "font-smoothing"
- ]
- }],
- "color-hex-case": "lower",
- "order/declaration-block-order": [
- "custom-properties",
- "declarations"
- ],
- "order/declaration-block-properties-alphabetical-order": true,
- "font-family-name-quotes": "always-where-recommended",
- "string-quotes": "single",
- "selector-pseudo-class-no-unknown": [
- true,
- {
- "ignorePseudoClasses": [
- "global"
- ]
- }
- ]
- }
-}
diff --git a/.travis.yml b/.travis.yml
index a2133b959..73da33078 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,4 +8,5 @@ node_js:
script:
- npm run lint
+ - npm run ts
- npm test
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec1afa6c0..8be3d3899 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,114 @@
+
+## 2.0.0-beta.12 (2018-06-02)
+
+* Add `accept` property to `BrowseButton` (#1533) ([934ffd2](https://github.com/react-toolbox/react-toolbox/commit/934ffd2)), closes [#1533](https://github.com/react-toolbox/react-toolbox/issues/1533)
+* Add `multiple` property to `BrowseButton` (#1656) ([071a4d3](https://github.com/react-toolbox/react-toolbox/commit/071a4d3)), closes [#1656](https://github.com/react-toolbox/react-toolbox/issues/1656)
+* Add default export TypeScript type to IconButton (#1577) ([79e031e](https://github.com/react-toolbox/react-toolbox/commit/79e031e)), closes [#1577](https://github.com/react-toolbox/react-toolbox/issues/1577)
+* Add falsy key example to AutocompleteTest ([f24d128](https://github.com/react-toolbox/react-toolbox/commit/f24d128))
+* Add missing Input import ([51a335b](https://github.com/react-toolbox/react-toolbox/commit/51a335b)), closes [#1792](https://github.com/react-toolbox/react-toolbox/issues/1792)
+* Add onEscKeyDown and onOverlayClick fallbacks ([4347125](https://github.com/react-toolbox/react-toolbox/commit/4347125))
+* Add postcss-apply to buid task and to webpack ([82f7118](https://github.com/react-toolbox/react-toolbox/commit/82f7118))
+* Add support for treeshaking (#1423) ([d2eee5a](https://github.com/react-toolbox/react-toolbox/commit/d2eee5a)), closes [#1423](https://github.com/react-toolbox/react-toolbox/issues/1423)
+* Add ThemeProvider Typescript type (#1576) ([7403d5d](https://github.com/react-toolbox/react-toolbox/commit/7403d5d)), closes [#1576](https://github.com/react-toolbox/react-toolbox/issues/1576)
+* Add title to image ([f815fb5](https://github.com/react-toolbox/react-toolbox/commit/f815fb5))
+* Add transition to hover effect in list items ([d9a0d7e](https://github.com/react-toolbox/react-toolbox/commit/d9a0d7e))
+* Add variables for the App Bar's font size and weight. (#1518) ([f93040e](https://github.com/react-toolbox/react-toolbox/commit/f93040e)), closes [#1518](https://github.com/react-toolbox/react-toolbox/issues/1518)
+* Add workaround to `is-component-of-type` for `react-hot-loader@^3` (#1569) ([431abb1](https://github.com/react-toolbox/react-toolbox/commit/431abb1)), closes [#1569](https://github.com/react-toolbox/react-toolbox/issues/1569)
+* Added label to InputTheme interface (#1501) ([6290cf5](https://github.com/react-toolbox/react-toolbox/commit/6290cf5)), closes [#1501](https://github.com/react-toolbox/react-toolbox/issues/1501)
+* Added missing `|` (#1403) ([8df122a](https://github.com/react-toolbox/react-toolbox/commit/8df122a)), closes [#1403](https://github.com/react-toolbox/react-toolbox/issues/1403)
+* Added required?: boolean; (#1491) ([27caadb](https://github.com/react-toolbox/react-toolbox/commit/27caadb)), closes [#1491](https://github.com/react-toolbox/react-toolbox/issues/1491)
+* adds a span wrapper to the component button in case of its disabled and have mouse enter and mouse l ([0286630](https://github.com/react-toolbox/react-toolbox/commit/0286630))
+* Allow autoFocus on Autocomplete component ([a828091](https://github.com/react-toolbox/react-toolbox/commit/a828091))
+* Allow pass inverse to IconMenu (#1490) ([4722904](https://github.com/react-toolbox/react-toolbox/commit/4722904)), closes [#1490](https://github.com/react-toolbox/react-toolbox/issues/1490)
+* Allow to change FontIcon for Tab by passing it into the factory (#1439) ([d6bdf20](https://github.com/react-toolbox/react-toolbox/commit/d6bdf20)), closes [#1439](https://github.com/react-toolbox/react-toolbox/issues/1439)
+* allows the Portal HOC root element to receive a style props. This allows coordinate runtime position ([0e299a6](https://github.com/react-toolbox/react-toolbox/commit/0e299a6)), closes [#1502](https://github.com/react-toolbox/react-toolbox/issues/1502)
+* Apply padding 0 to everything but buttons in ListItemAction (#1571) ([f44833a](https://github.com/react-toolbox/react-toolbox/commit/f44833a)), closes [#1571](https://github.com/react-toolbox/react-toolbox/issues/1571)
+* Avoid undefined className when ProgressBar mode is determinate ([7db3e34](https://github.com/react-toolbox/react-toolbox/commit/7db3e34))
+* Change tab style for ripple to work with Tabs (#1519) ([cd6a130](https://github.com/react-toolbox/react-toolbox/commit/cd6a130)), closes [#1519](https://github.com/react-toolbox/react-toolbox/issues/1519)
+* Check whether the query key has a value rather than whether it's truthy ([f79aaff](https://github.com/react-toolbox/react-toolbox/commit/f79aaff))
+* Disabled input should be dashed not dotted ([a46f095](https://github.com/react-toolbox/react-toolbox/commit/a46f095))
+* Do not show scrollbar on autocomplete component IE11 (#1515) ([f8f528c](https://github.com/react-toolbox/react-toolbox/commit/f8f528c)), closes [#1515](https://github.com/react-toolbox/react-toolbox/issues/1515)
+* Docs/Install: Fix typos, clarify language (#1566) ([2124c8c](https://github.com/react-toolbox/react-toolbox/commit/2124c8c)), closes [#1566](https://github.com/react-toolbox/react-toolbox/issues/1566)
+* Document usage with Create React App (#1482) ([d5b49a2](https://github.com/react-toolbox/react-toolbox/commit/d5b49a2)), closes [#1482](https://github.com/react-toolbox/react-toolbox/issues/1482)
+* Don't handle key events if slider is disabled ([6925570](https://github.com/react-toolbox/react-toolbox/commit/6925570))
+* Enable onKeyDown and onKeyUp props on Autocomplete component ([2c92c37](https://github.com/react-toolbox/react-toolbox/commit/2c92c37))
+* Event passed for Radiogroup (#1544) ([6fd1421](https://github.com/react-toolbox/react-toolbox/commit/6fd1421)), closes [#1544](https://github.com/react-toolbox/react-toolbox/issues/1544)
+* Feature/tabs a11y (#1513) ([94f6493](https://github.com/react-toolbox/react-toolbox/commit/94f6493)), closes [#1513](https://github.com/react-toolbox/react-toolbox/issues/1513)
+* fix #1611 (#1612) ([df175e7](https://github.com/react-toolbox/react-toolbox/commit/df175e7)), closes [#1611](https://github.com/react-toolbox/react-toolbox/issues/1611) [#1612](https://github.com/react-toolbox/react-toolbox/issues/1612)
+* Fix AppBar doc (#1407) ([06cbc41](https://github.com/react-toolbox/react-toolbox/commit/06cbc41)), closes [#1407](https://github.com/react-toolbox/react-toolbox/issues/1407)
+* Fix bug where dropdowns don't close (#1548) ([13520e3](https://github.com/react-toolbox/react-toolbox/commit/13520e3)), closes [#1548](https://github.com/react-toolbox/react-toolbox/issues/1548)
+* Fix compatibility with typescript 2.4+ (#1615) ([b381db4](https://github.com/react-toolbox/react-toolbox/commit/b381db4)), closes [#1615](https://github.com/react-toolbox/react-toolbox/issues/1615)
+* Fix date-picker animation in IE11 (#1586) ([54d0cb5](https://github.com/react-toolbox/react-toolbox/commit/54d0cb5)), closes [#1586](https://github.com/react-toolbox/react-toolbox/issues/1586)
+* Fix eslint errors ([f006708](https://github.com/react-toolbox/react-toolbox/commit/f006708))
+* Fix lint issue (#1624) ([6d43f88](https://github.com/react-toolbox/react-toolbox/commit/6d43f88)), closes [#1624](https://github.com/react-toolbox/react-toolbox/issues/1624)
+* Fix media queries panel height calculations (#1467) ([4a13ff2](https://github.com/react-toolbox/react-toolbox/commit/4a13ff2)), closes [#1467](https://github.com/react-toolbox/react-toolbox/issues/1467)
+* Fix mismatch between NPM published version and package.json version ([ecbdb12](https://github.com/react-toolbox/react-toolbox/commit/ecbdb12))
+* Fix mixed up type definitions for Dropdown ([47d2f18](https://github.com/react-toolbox/react-toolbox/commit/47d2f18))
+* Fix Mobile Safari issues. (#1282) ([e15ee8e](https://github.com/react-toolbox/react-toolbox/commit/e15ee8e)), closes [#1282](https://github.com/react-toolbox/react-toolbox/issues/1282)
+* Fix package.json ([e1f320c](https://github.com/react-toolbox/react-toolbox/commit/e1f320c))
+* Fix README on example project description (#1497) ([eb04045](https://github.com/react-toolbox/react-toolbox/commit/eb04045)), closes [#1497](https://github.com/react-toolbox/react-toolbox/issues/1497) [/github.com/react-toolbox/react-toolbox/pull/1251#issuecomment-302403914](https://github.com//github.com/react-toolbox/react-toolbox/pull/1251/issues/issuecomment-302403914)
+* Fix tests ([9a9396f](https://github.com/react-toolbox/react-toolbox/commit/9a9396f))
+* Fix travis ([32e4096](https://github.com/react-toolbox/react-toolbox/commit/32e4096))
+* Fix travis ([71341d9](https://github.com/react-toolbox/react-toolbox/commit/71341d9))
+* Fix tsc errors ([6357bed](https://github.com/react-toolbox/react-toolbox/commit/6357bed))
+* Fix typescript bindings. (#1564) ([de69a14](https://github.com/react-toolbox/react-toolbox/commit/de69a14)), closes [#1564](https://github.com/react-toolbox/react-toolbox/issues/1564) [#1407](https://github.com/react-toolbox/react-toolbox/issues/1407)
+* fixed browser button fires onChange event twice (#1557) ([c1a2dba](https://github.com/react-toolbox/react-toolbox/commit/c1a2dba)), closes [#1557](https://github.com/react-toolbox/react-toolbox/issues/1557)
+* Fixes #1452 (#1454) ([9619d85](https://github.com/react-toolbox/react-toolbox/commit/9619d85)), closes [#1452](https://github.com/react-toolbox/react-toolbox/issues/1452) [#1454](https://github.com/react-toolbox/react-toolbox/issues/1454) [#1452](https://github.com/react-toolbox/react-toolbox/issues/1452)
+* Handle onChange in errored input in docs ([c6a7b5b](https://github.com/react-toolbox/react-toolbox/commit/c6a7b5b))
+* Importing PropTypes from prop-types rather than react (#1413) ([ae09770](https://github.com/react-toolbox/react-toolbox/commit/ae09770)), closes [#1413](https://github.com/react-toolbox/react-toolbox/issues/1413)
+* Issue 1459: Replace onClick handler in Dropdown component to onMouseDown (#1521) ([736f23e](https://github.com/react-toolbox/react-toolbox/commit/736f23e)), closes [#1521](https://github.com/react-toolbox/react-toolbox/issues/1521)
+* Link text has text-transform: capitalize, contrary to Material specs, is removed. ([470ffae](https://github.com/react-toolbox/react-toolbox/commit/470ffae))
+* ListItem component theme prop extends ListItemTextTheme. ([11c3fb1](https://github.com/react-toolbox/react-toolbox/commit/11c3fb1))
+* ListItem legend may be a node as well (#1496) ([a6eb5c5](https://github.com/react-toolbox/react-toolbox/commit/a6eb5c5)), closes [#1496](https://github.com/react-toolbox/react-toolbox/issues/1496)
+* Made role on input field a property (#1553) ([fc9c180](https://github.com/react-toolbox/react-toolbox/commit/fc9c180)), closes [#1553](https://github.com/react-toolbox/react-toolbox/issues/1553)
+* Make checkbox border color according to spec ([4670098](https://github.com/react-toolbox/react-toolbox/commit/4670098))
+* Make checkbox centered between table edge and next column start ([b660bcc](https://github.com/react-toolbox/react-toolbox/commit/b660bcc))
+* Move Input#validPresent to utils#isValuePresent ([1dafc56](https://github.com/react-toolbox/react-toolbox/commit/1dafc56))
+* Move tsd task to gulpfile ([a9518b6](https://github.com/react-toolbox/react-toolbox/commit/a9518b6))
+* onchange ([4d64c73](https://github.com/react-toolbox/react-toolbox/commit/4d64c73))
+* Pass the theme prop to TableRow child components ([73b2594](https://github.com/react-toolbox/react-toolbox/commit/73b2594)), closes [#1805](https://github.com/react-toolbox/react-toolbox/issues/1805)
+* Remove box-shadow on required inputs ([14eb6ca](https://github.com/react-toolbox/react-toolbox/commit/14eb6ca))
+* Remove discord link in README.md (#1593) ([16ae9bf](https://github.com/react-toolbox/react-toolbox/commit/16ae9bf)), closes [#1593](https://github.com/react-toolbox/react-toolbox/issues/1593) [#107](https://github.com/react-toolbox/react-toolbox/issues/107)
+* Remove max-height from dialog along with hidden overflow ([2eb27c7](https://github.com/react-toolbox/react-toolbox/commit/2eb27c7))
+* Remove unknown prop multilineHint which React reports as passed to textarea ([478c9ae](https://github.com/react-toolbox/react-toolbox/commit/478c9ae))
+* requestAnimationFrame will only trigger if the browser window is visible. If the browser tab is put ([fb5d0e1](https://github.com/react-toolbox/react-toolbox/commit/fb5d0e1)), closes [#1604](https://github.com/react-toolbox/react-toolbox/issues/1604)
+* Revert "Update components to use css-transition-group 2" ([752cdd3](https://github.com/react-toolbox/react-toolbox/commit/752cdd3))
+* small typo error corrected. ([f78c084](https://github.com/react-toolbox/react-toolbox/commit/f78c084))
+* solve #1444 and #1359. (#1587) ([843b88a](https://github.com/react-toolbox/react-toolbox/commit/843b88a)), closes [#1444](https://github.com/react-toolbox/react-toolbox/issues/1444) [#1359](https://github.com/react-toolbox/react-toolbox/issues/1359) [#1587](https://github.com/react-toolbox/react-toolbox/issues/1587)
+* Typescript definitions validation (#1163) ([91cb46d](https://github.com/react-toolbox/react-toolbox/commit/91cb46d)), closes [#1163](https://github.com/react-toolbox/react-toolbox/issues/1163)
+* Update Autocomplete TypeScript declaration file and readme with key callbacks ([b79c3da](https://github.com/react-toolbox/react-toolbox/commit/b79c3da))
+* Update CHANGELOG.md (#1399) ([0d21c02](https://github.com/react-toolbox/react-toolbox/commit/0d21c02)), closes [#1399](https://github.com/react-toolbox/react-toolbox/issues/1399)
+* Update DatePicker.d.ts (#1411) ([e572dd7](https://github.com/react-toolbox/react-toolbox/commit/e572dd7)), closes [#1411](https://github.com/react-toolbox/react-toolbox/issues/1411)
+* update defaults in input component config.css ([25172c5](https://github.com/react-toolbox/react-toolbox/commit/25172c5))
+* Update dependencies ([be80e0b](https://github.com/react-toolbox/react-toolbox/commit/be80e0b))
+* Update enzyme config files ([d313e11](https://github.com/react-toolbox/react-toolbox/commit/d313e11))
+* Update readme for Autocomplete (#1657) ([4ca6747](https://github.com/react-toolbox/react-toolbox/commit/4ca6747)), closes [#1657](https://github.com/react-toolbox/react-toolbox/issues/1657) [/github.com/react-toolbox/react-toolbox/blob/8e2b688954d4b413a602bb59a89254e752f20b0f/components/autocomplete/Autocomplete.d.ts#L54](https://github.com//github.com/react-toolbox/react-toolbox/blob/8e2b688954d4b413a602bb59a89254e752f20b0f/components/autocomplete/Autocomplete.d.ts/issues/L54)
+* Update README.md ([afb6532](https://github.com/react-toolbox/react-toolbox/commit/afb6532))
+* Update README.md ([3d8cd66](https://github.com/react-toolbox/react-toolbox/commit/3d8cd66))
+* Update readme.md (#1478) ([f90958d](https://github.com/react-toolbox/react-toolbox/commit/f90958d)), closes [#1478](https://github.com/react-toolbox/react-toolbox/issues/1478)
+* Update tests to use css-transition-group 2 ([ab2e789](https://github.com/react-toolbox/react-toolbox/commit/ab2e789))
+* Update tests to use Enzyme 3 ([c510029](https://github.com/react-toolbox/react-toolbox/commit/c510029))
+* Update tests to use react-dom/test-utils ([08ca837](https://github.com/react-toolbox/react-toolbox/commit/08ca837))
+* Update URLs to new .io domain ([b0a7533](https://github.com/react-toolbox/react-toolbox/commit/b0a7533))
+* Update versions ([7e4c12e](https://github.com/react-toolbox/react-toolbox/commit/7e4c12e))
+* Updated dependencies (#1448) ([2981da4](https://github.com/react-toolbox/react-toolbox/commit/2981da4)), closes [#1448](https://github.com/react-toolbox/react-toolbox/issues/1448)
+* Upgrade react-transition-group ([ced94a4](https://github.com/react-toolbox/react-toolbox/commit/ced94a4))
+* Upgrade to node 7 ([66a47bb](https://github.com/react-toolbox/react-toolbox/commit/66a47bb))
+* Use code instead of keyCode ([f8a7e88](https://github.com/react-toolbox/react-toolbox/commit/f8a7e88))
+* Use hover effect on selected table row as well ([889e9ca](https://github.com/react-toolbox/react-toolbox/commit/889e9ca))
+* Use innerRef to blur input ([a7d0c5b](https://github.com/react-toolbox/react-toolbox/commit/a7d0c5b))
+* Use proper code values in KEYS constant 🤦🏻♂️ ([6fa13f1](https://github.com/react-toolbox/react-toolbox/commit/6fa13f1))
+* Use window.requestAnimationFrame in Tabs.js ([bc05c69](https://github.com/react-toolbox/react-toolbox/commit/bc05c69))
+* TypeScript: snack-bar label accepts element ([40aa354](https://github.com/react-toolbox/react-toolbox/commit/40aa354))
+* Portal: Fix Invalid "style" PropType (#1664) ([8b7fc07](https://github.com/react-toolbox/react-toolbox/commit/8b7fc07)), closes [#1664](https://github.com/react-toolbox/react-toolbox/issues/1664)
+* IconMenu: active prop (#1662). ([0103d95](https://github.com/react-toolbox/react-toolbox/commit/0103d95)), closes [#1662](https://github.com/react-toolbox/react-toolbox/issues/1662)
+* IconMenu: active prop (#1662). ([74bd2dc](https://github.com/react-toolbox/react-toolbox/commit/74bd2dc)), closes [#1662](https://github.com/react-toolbox/react-toolbox/issues/1662)
+* IconMenu: active prop (#1662). more tests. ([bf790d7](https://github.com/react-toolbox/react-toolbox/commit/bf790d7)), closes [#1662](https://github.com/react-toolbox/react-toolbox/issues/1662)
+* IconMenu: active prop (fixes #1662). ([0f51c06](https://github.com/react-toolbox/react-toolbox/commit/0f51c06)), closes [#1662](https://github.com/react-toolbox/react-toolbox/issues/1662)
+* fix: of -> or in documentation ([31fac7b](https://github.com/react-toolbox/react-toolbox/commit/31fac7b))
+
+
+
# 2.0.0-beta.8 (2017-04-06)
diff --git a/README.md b/README.md
index fa6963195..55d0d8c55 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-#
+#
-[](https://www.npmjs.com/package/react-toolbox) [](https://travis-ci.org/react-toolbox/react-toolbox) [](https://www.npmjs.org/package/react-toolbox) [](https://discord.gg/0ZcbPKXt5bW9FLzM) [](https://paypal.me/javivelasco) [](#backers)
+[](https://www.npmjs.com/package/react-toolbox) [](https://travis-ci.org/react-toolbox/react-toolbox) [](https://www.npmjs.org/package/react-toolbox) [](https://paypal.me/javivelasco) [](#backers)
[](#sponsors)
React Toolbox is a set of [React](http://facebook.github.io/react/) components that implement [Google's Material Design specification](https://material.google.com/). It's powered by [CSS Modules](https://github.com/css-modules/css-modules) and harmoniously integrates with your [webpack](http://webpack.github.io/) workflow, although you can use any other module bundler. You can take a tour through our documentation website and try the components live!
@@ -17,18 +17,23 @@ $ npm install --save react-toolbox
## Prerequisites
-React Toolbox uses [CSS Modules](https://github.com/css-modules/css-modules) by default to import stylesheets written using PostCSS/[cssnext](http://cssnext.io/) features. In case you want to import the components already bundled with CSS, your module bundler should be able to require these PostCSS modules.
+React Toolbox uses [CSS Modules](https://github.com/css-modules/css-modules) by default to import stylesheets written using [PostCSS](https://github.com/postcss/postcss) & [postcss-preset-env](https://preset-env.cssdb.org/) features. In case you want to import the components already bundled with CSS, your module bundler should be able to require these PostCSS modules.
Although we recommend [webpack](https://webpack.github.io/), you are free to use whatever module bundler you want as long as it can compile and require PostCSS files located in your `node_modules`. If you are experiencing require errors, make sure your configuration satisfies this requirement.
Of course this is a set of React components so you should be familiar with [React](https://facebook.github.io/react/). If want to customize your components via themes, you may want to take a look to [react-css-themr](https://github.com/javivelasco/react-css-themr) which is used by React Toolbox to make components easily themeable.
-### Setting up PostCSS+cssnext in Webpack:
+### Usage in Create React App Projects
+
+[Create React App](https://github.com/facebookincubator/create-react-app) does not allow to change the default configuration, so you need an additional build step to configure `react-toolbox` in its project.
+
+Follow [these instructions](https://github.com/react-toolbox/react-toolbox-themr) to add `react-toolbox` to a project created with Create React App.
+
+### Usage in Webpack Projects (*Not* Create React App)
```bash
npm install postcss-loader --save-dev
-npm install postcss --save
-npm install postcss-cssnext --save
+npm install postcss postcss-preset-env postcss-calc --save
```
Configure webpack 1.x loader for .css files to use postcss:
@@ -43,15 +48,46 @@ Configure webpack 1.x loader for .css files to use postcss:
```
Declare plugins to be used by postcss (as part of webpack's config object):
```js
+ // webpack.config.js
postcss: () => {
return [
/* eslint-disable global-require */
- require('postcss-cssnext'),
+ require('postcss-preset-env')({
+ stage: 0, // required to get all features that were from cssnext without enabling them one by one
+ features: {
+ 'custom-properties': {
+ preserve: false, // required to output values instead of variables
+ },
+ 'color-mod-function': true, // required to use color-mod()
+ }
+ }),
+ require('postcss-calc'), // required as postcss-preset-env doesn't have a reduce calc() funtion that cssnext did
/* eslint-enable global-require */
];
},
```
+Configure webpack 2.x or 3.x loader for .css files to use postcss:
+```js
+ // webpack.config.js
+ {
+ test: /\.css$/,
+ use: [
+ "style-loader",
+ {
+ loader: "css-loader",
+ options: {
+ modules: true, // default is false
+ sourceMap: true,
+ importLoaders: 1,
+ localIdentName: "[name]--[local]--[hash:base64:8]"
+ }
+ },
+ "postcss-loader"
+ ]
+ }
+```
+
## Basic usage
In this minimal example, we import a `Button` with styles already bundled:
@@ -67,6 +103,13 @@ ReactDOM.render(
);
```
+>**Note:** if you use it with Create React App, you need to make this additional change:
+>
+>```diff
+>- import {Button} from 'react-toolbox/lib/button';
+>+ import Button from 'react-toolbox/lib/button/Button';
+>```
+
Take into account that any required style will be included in the final CSS so your final CSS would include `Button` styles in this case. It's more efficient to import components this way (`from 'react-toolbox/lib/button'`) (or with raw imports) because if you require from the project root (i.e. `from 'react-toolbox'`), every stylesheet of React Toolbox will be included, even if you don't use it.
## Importing components
@@ -82,7 +125,7 @@ First let's take a look on how the components are structured in the project. The
|---- theme.css
```
-As you can see in the previous block, each folder includes: a Javascript file for each component/subcomponent; a README with documentation, an index Javascript file that imports and injects styles and dependencies for you, a default theme PostCSS/cssnext stylesheet and a config.css with configuration variables (CSS Custom Properties). Depending on whether you want the styles to be directly bundled or not, you can import components in **two** different ways.
+As you can see in the previous block, each folder includes: a Javascript file for each component/subcomponent; a README with documentation, an index Javascript file that imports and injects styles and dependencies for you, a default theme PostCSS/preset-env stylesheet and a config.css with configuration variables (CSS Custom Properties). Depending on whether you want the styles to be directly bundled or not, you can import components in **two** different ways.
### Bundled component
@@ -179,14 +222,13 @@ export default App;
## Theming (configuration variables)
-You can apply theming in multiple ways. First of all, you have to understand that React Toolbox stylesheets are written using PostCSS with cssnext features and use CSS Custom Properties from the **config** files we saw earlier. In addition, there are some global CSS Properties imported by each component: [colors](https://github.com/react-toolbox/react-toolbox/blob/dev/components/colors.css) and [variables](https://github.com/react-toolbox/react-toolbox/blob/dev/components/variables.css). You can override both the global and component-specific **variables** to get the results you want using one of the methods below.
+You can apply theming in multiple ways. First of all, you have to understand that React Toolbox stylesheets are written using PostCSS with postcss-preset-env features and use CSS Custom Properties from the **config** files we saw earlier. In addition, there are some global CSS Properties imported by each component: [colors](https://github.com/react-toolbox/react-toolbox/blob/dev/components/colors.module.css) and [variables](https://github.com/react-toolbox/react-toolbox/blob/dev/components/variables.module.css). You can override both the global and component-specific **variables** to get the results you want using one of the methods below.
### Settings configuration variables in JavaScript
-You can override both the global and component-specific CSS Custom Properties at build-time by supplying an object with these variable names and your desired values to the PostCSS customProperties plugin. i.e. if using postcss-next in webpack:
+You can override both the global and component-specific CSS Custom Properties at build-time by supplying an object with these variable names and your desired values to the PostCSS `custom-properties` plugin. i.e. if using [postcss-preset-env](https://github.com/csstools/postcss-preset-env) in webpack:
```js
-
// This can also be stored in a separate file:
const reactToolboxVariables = {
'color-text': '#444548',
@@ -195,31 +237,34 @@ const reactToolboxVariables = {
'button-height': '30px',
};
-// webpack's config object:
+// webpack's config object: (webpack.config.js)
const config = {
...
postcss: () => {
return [
/* eslint-disable global-require */
- require('postcss-cssnext')({
+ require('postcss-preset-env')({
+ stage: 0, // required to get all features that were from cssnext without enabling them one by one
features: {
- customProperties: {
- variables: reactToolboxVariables,
+ 'custom-properties': {
+ preserve: false, // required to output values instead of variables
+ importFrom: reactToolboxVariables, // see postcss-preset-env for config options
},
- },
+ 'color-mod-function': true, // required to use color-mod()
+ }
}),
+ require('postcss-calc'), // required as postcss-preset-env doesn't have a reduce calc() funtion that cssnext did
/* optional - see next section */
require('postcss-modules-values'),
/* eslint-enable global-require */
];
},
}
-
```
### Settings configuration variables using CSS Module Values
-Instead of using a JavaScript object for variables, you can use [CSS Module Values](https://github.com/css-modules/css-modules/blob/master/docs/values-variables.md) (`npm install postcss-modules-values --save`) and the [modules-values-extract](https://github.com/alexhisen/modules-values-extract) utility to declare these variables in component-specific theme .css files, where you would typically store additional style overrides.
+Instead of using a JavaScript object for variables, you can use [CSS Module Values](https://github.com/css-modules/css-modules/blob/master/docs/values-variables.md) (`npm install postcss-modules-values --save`) and the [modules-values-extract](https://github.com/alexhisen/modules-values-extract) utility to declare these variables in component-specific theme `.css` files, where you would typically store additional style overrides.
CSS Module Values also offer the advantage that importing a css file with @value declarations makes these values properties of the imported style object, i.e.:
@@ -235,7 +280,7 @@ import styleVariables from './css/variables.css';
styleVariables.buttonPrimaryBackgroundColor
```
-In [this demo project](https://github.com/alexhisen/mobx-forms-demo), modules-values-extract utility is used to extract all @values with dashes in their name from all css files in the /css folder and to feed them to customProperties in [webpack](https://github.com/alexhisen/mobx-forms-demo/blob/master/webpack.config.js). In the demo project, variables that are not specific to a particular component are in [variables.css](https://github.com/alexhisen/mobx-forms-demo/blob/master/src/css/variables.css) and button-specific variables are in [button.css](https://github.com/alexhisen/mobx-forms-demo/blob/master/src/css/button.css). Note that button.css also imports certain values from variables.css just to demonstrate this capability \(the import can also be used in a @value declaration\) and it uses CSS overrides instead of color variables that exist in the React-Toolbox Button component to show an alternative method if the variables are not sufficient.
+In [this demo project](https://github.com/alexhisen/mobx-forms-demo), modules-values-extract utility is used to extract all @values with dashes in their name from all css files in the `/css` folder and to feed them to customProperties in [webpack](https://github.com/alexhisen/mobx-forms-demo/blob/master/webpack.config.js). In the demo project, variables that are not specific to a particular component are in [variables.css](https://github.com/alexhisen/mobx-forms-demo/blob/master/src/css/variables.css) and button-specific variables are in [button.css](https://github.com/alexhisen/mobx-forms-demo/blob/master/src/css/button.css). Note that button.css also imports certain values from variables.css just to demonstrate this capability \(the import can also be used in a @value declaration\) and it uses CSS overrides instead of color variables that exist in the React-Toolbox Button component to show an alternative method if the variables are not sufficient.
> **IMPORTANT: Changes to the module values do not take effect immediately with Webpack Hot-Module-Reload - webpack / webpack-dev-server must be restarted!**
@@ -251,9 +296,9 @@ The only requirement for SSR is to be able to require ES6 and CSS Modules in the
## Examples
-For now we have a [1.x repository example](https://github.com/react-toolbox/react-toolbox-example) demonstrating configuration and some basic customization. It hasn't yet been updated for 2.0! For now it's not using SSR rendering but it shouldn't be difficult to implement an example so it will come soon. Feel free to PR your example project or to add some use cases to the repository:
+For now we have a [repository example](https://github.com/react-toolbox/react-toolbox-example) demonstrating configuration and some basic customization. For now it's not using SSR rendering but it shouldn't be difficult to implement an example so it will come soon. Feel free to PR your example project or to add some use cases to the repository:
-2.x demo project - https://github.com/alexhisen/mobx-forms-demo
+Another 2.x demo project is https://github.com/alexhisen/mobx-forms-demo
## TypeScript
diff --git a/ROADMAP.md b/ROADMAP.md
index 8e9821217..2b1ff11af 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,4 +1,4 @@
-This document defines a manifesto and the main Roadmap 🚵 ideas for [React Toolbox](www.react-toolbox.com). It's not a fixed document and of course it's open to change. You can leave your feedback in [this gist](https://gist.github.com/javivelasco/259d2087c2a8c3e8f2c5c720d1fd3f2e) or you can also do it [through an issue](https://github.com/react-toolbox/react-toolbox/issues/new).
+This document defines a manifesto and the main Roadmap 🚵 ideas for [React Toolbox](www.react-toolbox.io). It's not a fixed document and of course it's open to change. You can leave your feedback in [this gist](https://gist.github.com/javivelasco/259d2087c2a8c3e8f2c5c720d1fd3f2e) or you can also do it [through an issue](https://github.com/react-toolbox/react-toolbox/issues/new).
## The Manifesto
@@ -68,7 +68,7 @@ There is no fixed date, sorry. Being an open source project, it depends on contr
### Is there any migration guide to 2.0?
-Not really. At the end we are just providing components and there are no big changes on them apart from huge refactors of some specific components that will be coming. If should be enough by checking changelogs and new documentation. In any case if you feel like a migration guide is needed, feel free to leave for feedback.
+There is a [migration guide](https://github.com/react-toolbox/react-toolbox/wiki/Migrating-from-version-1.3-to-2.0) in the wiki.
### When will be released the new playground?
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 000000000..0b2856212
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,35 @@
+module.exports = function (api) {
+ const env = api.env();
+ api.cache.using(() => env === 'development');
+
+ return {
+ presets: ['@babel/preset-env', '@babel/preset-react'],
+ plugins: [
+ '@babel/plugin-transform-runtime',
+ // Stage 0
+ '@babel/plugin-proposal-function-bind',
+
+ // Stage 1
+ '@babel/plugin-proposal-export-default-from',
+ '@babel/plugin-proposal-logical-assignment-operators',
+ ['@babel/plugin-proposal-optional-chaining', { loose: false }],
+ ['@babel/plugin-proposal-pipeline-operator', { proposal: 'minimal' }],
+ ['@babel/plugin-proposal-nullish-coalescing-operator', { loose: false }],
+ '@babel/plugin-proposal-do-expressions',
+
+ // Stage 2
+ ['@babel/plugin-proposal-decorators', { legacy: true }],
+ '@babel/plugin-proposal-function-sent',
+ '@babel/plugin-proposal-export-namespace-from',
+ '@babel/plugin-proposal-numeric-separator',
+ '@babel/plugin-proposal-throw-expressions',
+
+ // Stage 3
+ '@babel/plugin-syntax-dynamic-import',
+ '@babel/plugin-syntax-import-meta',
+ ['@babel/plugin-proposal-class-properties', { loose: false }],
+ '@babel/plugin-proposal-json-strings',
+ 'react-hot-loader/babel',
+ ],
+ };
+};
diff --git a/components/ThemeProvider.d.ts b/components/ThemeProvider.d.ts
new file mode 100644
index 000000000..f3884c411
--- /dev/null
+++ b/components/ThemeProvider.d.ts
@@ -0,0 +1,3 @@
+import {ThemeProvider} from 'react-css-themr'
+
+export default ThemeProvider
diff --git a/components/__mocks__/react-css-themr.js b/components/__mocks__/react-css-themr.js
index 0db02aaf4..749303b52 100644
--- a/components/__mocks__/react-css-themr.js
+++ b/components/__mocks__/react-css-themr.js
@@ -1,6 +1,6 @@
export function themr() {
return (Component) => {
- Component.defaultProps = Component.defaultProps || {}; // eslint-disable-line no-param-reassign
+ Component.defaultProps = Component.defaultProps || {}; // eslint-disable-line no-param-reassign
Component.defaultProps.theme = {}; // eslint-disable-line no-param-reassign
return Component;
};
diff --git a/components/app_bar/AppBar.d.ts b/components/app_bar/AppBar.d.ts
index 9fc3e680c..3df288673 100644
--- a/components/app_bar/AppBar.d.ts
+++ b/components/app_bar/AppBar.d.ts
@@ -43,7 +43,7 @@ export interface AppBarProps extends ReactToolbox.Props {
*/
fixed?: boolean;
/**
- * If true, the AppBar shows a shadow.
+ * If true, the AppBar doesn't show a shadow.
* @default false
*/
flat?: boolean;
diff --git a/components/app_bar/AppBar.js b/components/app_bar/AppBar.js
index d4421b87d..93627fc07 100644
--- a/components/app_bar/AppBar.js
+++ b/components/app_bar/AppBar.js
@@ -25,9 +25,9 @@ const factory = (IconButton) => {
scrollHide: PropTypes.bool,
theme: PropTypes.shape({
appBar: PropTypes.string,
- inner: PropTypes.string,
fixed: PropTypes.string,
flat: PropTypes.string,
+ inner: PropTypes.string,
leftIcon: PropTypes.string,
rightIcon: PropTypes.string,
scrollHide: PropTypes.string,
@@ -46,7 +46,7 @@ const factory = (IconButton) => {
scrollHide: false,
};
- state = { hidden: false, height: 0 };
+ state = { hidden: false, height: 0 }; // eslint-disable-line react/no-unused-state
componentDidMount() {
if (this.props.scrollHide) {
@@ -70,26 +70,27 @@ const factory = (IconButton) => {
}
}
- initializeScroll() {
+ handleScroll = () => {
+ const scrollDiff = this.curScroll - window.scrollY;
+ this.setState(state => ({
+ hidden: scrollDiff < 0
+ && window.scrollY !== undefined
+ && window.scrollY > state.height,
+ }));
+ this.curScroll = window.scrollY;
+ };
+
+ initializeScroll = () => {
window.addEventListener('scroll', this.handleScroll);
const { height } = this.rootNode.getBoundingClientRect();
this.curScroll = window.scrollY;
- this.setState({ height });
+ this.setState({ height }); // eslint-disable-line react/no-unused-state
}
endScroll() {
window.removeEventListener('scroll', this.handleScroll);
}
- handleScroll = () => {
- const scrollDiff = this.curScroll - window.scrollY;
- const hidden = scrollDiff < 0
- && window.scrollY !== undefined
- && window.scrollY > this.state.height;
- this.setState({ hidden });
- this.curScroll = window.scrollY;
- };
-
render() {
const {
children,
diff --git a/components/app_bar/config.css b/components/app_bar/config.module.css
similarity index 84%
rename from components/app_bar/config.css
rename to components/app_bar/config.module.css
index ca3ba1b48..a3851e20b 100644
--- a/components/app_bar/config.css
+++ b/components/app_bar/config.module.css
@@ -1,6 +1,8 @@
:root {
--appbar-color: var(--color-primary-dark);
--appbar-contrast: var(--color-primary-contrast);
+ --appbar-title-font-size: calc(2 * var(--unit));
+ --appbar-title-font-weight: 500;
--appbar-title-total-distance: calc(8 * var(--unit));
--appbar-height: calc(6.4 * var(--unit));
--appbar-height-m-portrait: calc(5.6 * var(--unit));
diff --git a/components/app_bar/index.js b/components/app_bar/index.js
index ac09b55cc..2fd50cbbd 100644
--- a/components/app_bar/index.js
+++ b/components/app_bar/index.js
@@ -2,7 +2,7 @@ import { themr } from 'react-css-themr';
import { APP_BAR } from '../identifiers';
import { appBarFactory } from './AppBar';
import { IconButton } from '../button';
-import theme from './theme.css';
+import theme from './theme.module.css';
const AppBar = appBarFactory(IconButton);
const ThemedAppBar = themr(APP_BAR, theme)(AppBar);
diff --git a/components/app_bar/theme.css b/components/app_bar/theme.module.css
similarity index 82%
rename from components/app_bar/theme.css
rename to components/app_bar/theme.module.css
index 8b9282b40..fe8986f4e 100644
--- a/components/app_bar/theme.css
+++ b/components/app_bar/theme.module.css
@@ -1,7 +1,7 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/media.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/media.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.appBar {
background: var(--appbar-color);
@@ -54,16 +54,11 @@
.title {
flex-grow: 1;
- font-size: calc(1.8 * var(--unit));
- font-weight: bold;
+ font-size: var(--appbar-title-font-size);
+ font-weight: var(--appbar-title-font-weight);
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
-
- & > small {
- font-size: calc(1.8 * var(--unit));
- font-weight: normal;
- }
}
.leftIcon {
diff --git a/components/autocomplete/Autocomplete.d.ts b/components/autocomplete/Autocomplete.d.ts
index b7d98d82e..9eddafa1c 100644
--- a/components/autocomplete/Autocomplete.d.ts
+++ b/components/autocomplete/Autocomplete.d.ts
@@ -88,6 +88,14 @@ export interface AutocompleteProps extends InputProps {
* Callback function that is fired when component is focused.
*/
onFocus?: Function;
+ /**
+ * Callback function that is fired when a key is pressed down.
+ */
+ onKeyDown?: Function;
+ /**
+ * Callback function that is fired when a key is lifted up.
+ */
+ onKeyUp?: Function;
/**
* Callback function that is fired when the components's query value changes.
*/
diff --git a/components/autocomplete/Autocomplete.js b/components/autocomplete/Autocomplete.js
index 099a03378..ab0ad3096 100644
--- a/components/autocomplete/Autocomplete.js
+++ b/components/autocomplete/Autocomplete.js
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
+import { isValuePresent } from '../utils/utils';
import { AUTOCOMPLETE } from '../identifiers.js';
import InjectChip from '../chip/Chip.js';
import InjectInput from '../input/Input.js';
@@ -35,6 +36,8 @@ const factory = (Chip, Input) => {
onBlur: PropTypes.func,
onChange: PropTypes.func,
onFocus: PropTypes.func,
+ onKeyDown: PropTypes.func,
+ onKeyUp: PropTypes.func,
onQueryChange: PropTypes.func,
query: PropTypes.string,
selectedPosition: PropTypes.oneOf(['above', 'below', 'none']),
@@ -132,7 +135,7 @@ const factory = (Chip, Input) => {
};
handleQueryFocus = (event) => {
- this.suggestionsNode.scrollTop = 0;
+ event.target.scrollTop = 0;
this.setState({ active: '', focus: true });
if (this.props.onFocus) this.props.onFocus(event);
};
@@ -148,6 +151,8 @@ const factory = (Chip, Input) => {
if (event.which === 13) {
this.selectOrCreateActiveItem(event);
}
+
+ if(this.props.onKeyDown) this.props.onKeyDown(event);
};
handleQueryKeyUp = (event) => {
@@ -160,6 +165,8 @@ const factory = (Chip, Input) => {
if (index >= suggestionsKeys.length) index = 0;
this.setState({ active: suggestionsKeys[index] });
}
+
+ if(this.props.onKeyUp) this.props.onKeyUp(event);
};
handleSuggestionHover = (event) => {
@@ -178,7 +185,7 @@ const factory = (Chip, Input) => {
query(key) {
let query_value = '';
- if (!this.props.multiple && key) {
+ if (!this.props.multiple && isValuePresent(key)) {
const source_value = this.source().get(`${key}`);
query_value = source_value || key;
}
@@ -375,7 +382,6 @@ const factory = (Chip, Input) => {
return (
{ this.suggestionsNode = node; }}
>
{suggestions}
diff --git a/components/autocomplete/config.css b/components/autocomplete/config.module.css
similarity index 100%
rename from components/autocomplete/config.css
rename to components/autocomplete/config.module.css
diff --git a/components/autocomplete/index.js b/components/autocomplete/index.js
index 52e3bc568..4acb3accd 100644
--- a/components/autocomplete/index.js
+++ b/components/autocomplete/index.js
@@ -3,7 +3,7 @@ import { AUTOCOMPLETE } from '../identifiers';
import { autocompleteFactory } from './Autocomplete';
import { Chip } from '../chip';
import { Input } from '../input';
-import theme from './theme.css';
+import theme from './theme.module.css';
const Autocomplete = autocompleteFactory(Chip, Input);
const ThemedAutocomplete = themr(AUTOCOMPLETE, theme, { withRef: true })(Autocomplete);
diff --git a/components/autocomplete/readme.md b/components/autocomplete/readme.md
index 5da6b8ba4..0a2abcbe4 100644
--- a/components/autocomplete/readme.md
+++ b/components/autocomplete/readme.md
@@ -45,23 +45,25 @@ If you want to provide a theme via context, the component key is `RTAutocomplete
|:-----|:-----|:-----|:-----|
| `allowCreate` | `Bool` | `false` | Determines if user can create a new option with the current typed value |
| `className` | `String` | `''` | Sets a class to style of the Component.|
-| `direction` | `String` | `auto` | Determines the opening direction. It can be `auto`, `top` or `down`. |
+| `direction` | `String` | `auto` | Determines the opening direction. It can be `auto`, `up` or `down`. |
| `disabled` | `Bool` | `false` | If true, component will be disabled. |
-| `error` | `String` or `Node` | | Sets the error string for the internal input element. |
+| `error` | `String` or `Node` | | Sets the error string for the internal input element. |
| `keepFocusOnChange` | `Bool` | `false` | Whether component should keep focus after value change. |
-| `label` | `String` or `Node` | | The text string to use for the floating label element. |
+| `label` | `String` or `Node` | | The text string to use for the floating label element. |
| `multiple` | `Bool` | `true` | If true, component can hold multiple values. |
-| `onBlur` | `Function` | | Callback function that is fired when component is blurred. |
-| `onChange` | `Function` | | Callback function that is fired when the components's value changes. |
-| `onQueryChange` | `Function` | | Callback function that is fired when the components's query input value changes. |
-| `onFocus` | `Function` | | Callback function that is fired when component is focused. |
-| `query` | `String` | | This property has to be used in case the `source` is not static and will be changing during search for `multiple={false}` autocomplete, content of the `query` has to be managed by the `onQueryChange` callback. |
-| `source` | `Object` or `Array` | | Object of key/values or array representing all items suggested. |
+| `onBlur` | `Function` | | Callback function that is fired when component is blurred. |
+| `onChange` | `Function` | | Callback function that is fired when the components's value changes. |
+| `onFocus` | `Function` | | Callback function that is fired when component is focused. |
+| `onKeyDown` | `Function` | | Callback function that is fired when a key is pressed down. |
+| `onKeyUp` | `Function` | | Callback function that is fired when a key is lifted up. |
+| `onQueryChange` | `Function` | | Callback function that is fired when the components's query input value changes. |
+| `query` | `String` | | This property has to be used in case the `source` is not static and will be changing during search for `multiple={false}` autocomplete, content of the `query` has to be managed by the `onQueryChange` callback. |
+| `source` | `Object` or `Array` | | Object of key/values or array representing all items suggested. |
| `selectedPosition` | `String` | `above` | Determines if the selected list is shown above or below input. It can be `above`, `below` or `none`. |
| `showSelectedWhenNotInSource` | `Bool` | `false` | Determines if the selected list is shown if the `value` keys don't exist in the source. Only works if passing the `value` prop as an Object. |
| `showSuggestionsWhenValueIsSet` | `Bool` | `false` | If true, the list of suggestions will not be filtered when a value is selected, until the query is modified. |
| `suggestionMatch` | `String` | `start` | Determines how suggestions are supplied. It can be `start` (query matches the start of a suggestion), `anywhere` (query matches anywhere inside the suggestion), `word` (query matches the start of a word in the suggestion) or `disabled` (disable filtering of provided source, all items are shown). |
-| `value` | `String`, `Array` or `Object` | | Value or array of values currently selected component. |
+| `value` | `String`, `Array` or `Object` | | Value or array of values currently selected component. |
Additional properties will be passed to the Input Component so you can use `hint`, `name` ... etc.
diff --git a/components/autocomplete/theme.css b/components/autocomplete/theme.module.css
similarity index 91%
rename from components/autocomplete/theme.css
rename to components/autocomplete/theme.module.css
index f6c943cd6..069e1e4f1 100644
--- a/components/autocomplete/theme.css
+++ b/components/autocomplete/theme.module.css
@@ -1,7 +1,36 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/input/config.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/input/config.module.css';
+@import 'http://github.com/config.module.css';
+
+.suggestions {
+ background-color: var(--autocomplete-suggestions-background);
+ list-style: none;
+ max-height: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 0;
+ position: absolute;
+ transition-duration: var(--animation-duration);
+ transition-property: max-height, box-shadow;
+ transition-timing-function: var(--animation-curve-default);
+ visibility: hidden;
+ width: 100%;
+ z-index: var(--z-index-high);
+
+ &::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+ }
+
+ &:not(.up) {
+ margin-top: calc(-1 * var(--input-padding));
+ }
+
+ &.up {
+ bottom: 0;
+ }
+}
.autocomplete {
padding: var(--unit) 0;
@@ -13,6 +42,7 @@
& .suggestions {
box-shadow: var(--zdepth-shadow-1);
max-height: var(--autocomplete-overflow-max-height);
+ -ms-overflow-style: none;
visibility: visible;
}
}
@@ -30,35 +60,6 @@
margin: var(--autocomplete-value-margin);
}
-.suggestions {
- background-color: var(--autocomplete-suggestions-background);
- list-style: none;
- max-height: 0;
- overflow-x: hidden;
- overflow-y: auto;
- padding: 0;
- position: absolute;
- transition-duration: var(--animation-duration);
- transition-property: max-height, box-shadow;
- transition-timing-function: var(--animation-curve-default);
- visibility: hidden;
- width: 100%;
- z-index: var(--z-index-high);
-
- &:not(.up) {
- margin-top: calc(-1 * var(--input-padding));
- }
-
- &.up {
- bottom: 0;
- }
-
- &::-webkit-scrollbar {
- height: 0;
- width: 0;
- }
-}
-
.suggestion {
cursor: pointer;
font-size: var(--input-field-font-size);
diff --git a/components/avatar/Avatar.js b/components/avatar/Avatar.js
index 9d9dd9448..7dfbfc0fb 100644
--- a/components/avatar/Avatar.js
+++ b/components/avatar/Avatar.js
@@ -6,11 +6,13 @@ import { AVATAR } from '../identifiers';
import InjectFontIcon from '../font_icon/FontIcon';
const factory = (FontIcon) => {
- const Avatar = ({ alt, children, className, cover, icon, image, theme, title, ...other }) => (
+ const Avatar = ({
+ alt, children, className, cover, icon, image, theme, title, ...other
+ }) => (
diff --git a/components/date_picker/__test__/index.spec.js b/components/date_picker/__test__/index.spec.js
index 7ef335f86..fa952c7fb 100644
--- a/components/date_picker/__test__/index.spec.js
+++ b/components/date_picker/__test__/index.spec.js
@@ -1,6 +1,6 @@
import React from 'react';
import { shallow } from 'enzyme';
-import theme from '../theme.css';
+import theme from '../theme.module.css';
import { DatePickerDialog, Calendar } from '../DatePicker';
describe('DatePickerDialog', () => {
diff --git a/components/date_picker/config.css b/components/date_picker/config.module.css
similarity index 90%
rename from components/date_picker/config.css
rename to components/date_picker/config.module.css
index 92480b399..52f65426f 100644
--- a/components/date_picker/config.css
+++ b/components/date_picker/config.module.css
@@ -3,7 +3,7 @@
--datepicker-primary-contrast: var(--color-primary-contrast);
--datepicker-primary-dark: var(--color-primary-dark);
--datepicker-primary-color: var(--datepicker-primary);
- --datepicker-primary-hover-color: color(var(--datepicker-primary) a(0.2));
+ --datepicker-primary-hover-color: color-mod(var(--datepicker-primary) a(0.2));
--datepicker-primary-contrast-color: var(--datepicker-primary-contrast);
--datepicker-primary-dark-color: var(--datepicker-primary-dark);
--datepicker-dialog-width: calc(33 * var(--unit));
@@ -18,7 +18,7 @@
--calendar-primary-contrast: var(--color-primary-contrast);
--calendar-primary-color: var(--calendar-primary);
--calendar-primary-contrast-color: var(--calendar-primary-contrast);
- --calendar-primary-hover-color: color(var(--calendar-primary) a(0.21));
+ --calendar-primary-hover-color: color-mod(var(--calendar-primary) a(0.21));
--calendar-arrows-color: var(--palette-grey-600);
--calendar-arrows-font-size: calc(2 * var(--unit));
--calendar-year-font-size: 2.4;
diff --git a/components/date_picker/index.js b/components/date_picker/index.js
index 2a7f36b60..5e72c5988 100644
--- a/components/date_picker/index.js
+++ b/components/date_picker/index.js
@@ -7,7 +7,7 @@ import calendarFactory from './Calendar';
import { IconButton } from '../button';
import { Input } from '../input';
import { Dialog } from '../dialog';
-import theme from './theme.css';
+import theme from './theme.module.css';
const Calendar = calendarFactory(IconButton);
const DatePickerDialog = datePickerDialogFactory(Dialog, Calendar);
diff --git a/components/date_picker/readme.md b/components/date_picker/readme.md
index a62da27e0..2e4943ba6 100644
--- a/components/date_picker/readme.md
+++ b/components/date_picker/readme.md
@@ -49,25 +49,25 @@ If you want to provide a theme via context, the component key is `RTDatePicker`.
| `active` | `Boolean` | `false` | Allows to control if the picker should be shown from outside. Beware you should update the prop when the Dialog is closed. |
| `autoOk` | `Boolean` | `false` | Automatically selects a date upon clicking on a day. |
| `cancelLabel` | `String` | `'Cancel'` | Label used for cancel button on date picker dialog. |
-| `className` | `String` | | This class will be placed at the top of the `DatePickerDialog` component so you can provide custom styles.|
-| `disabledDates` | `Array` | | An array of date objects which will be disabled in the calendar. All other dates will be enabled.|
-| `enabledDates` | `Array` | | An array of date objects which will be enabled in the calendar. All other dates will be disabled.|
-| `error` | `String` | | Give an error message to display under the field.|
-| `inputClassName`| `String` | | This class will be applied to `Input` component of `DatePicker`. |
-| `inputFormat` | `Function` | | Function to format the date displayed on the input. |
-| `label` | `String` | | The text string to use for the floating label element in the input component.|
+| `className` | `String` | | This class will be placed at the top of the `DatePickerDialog` component so you can provide custom styles.|
+| `disabledDates` | `Array` | | An array of date objects which will be disabled in the calendar. All other dates will be enabled.|
+| `enabledDates` | `Array` | | An array of date objects which will be enabled in the calendar. All other dates will be disabled.|
+| `error` | `String` | | Give an error message to display under the field.|
+| `inputClassName`| `String` | | This class will be applied to `Input` component of `DatePicker`. |
+| `inputFormat` | `Function` | | Function to format the date displayed on the input. |
+| `label` | `String` | | The text string to use for the floating label element in the input component.|
| `locale` | `String` or `Object` | `'en'` | Set the locale for the date picker dialog ('de','no','en','es','af','ar','be','bg','bn','bo','br','bs','ca','gl','eu','pt','it','fr','ru','ua'). Object is supported too (see example above). |
-| `maxDate` | `Date` | | Date object with the maximum selectable date. |
-| `minDate` | `Date` | | Date object with the minimum selectable date. |
-| `onChange` | `Function` | | Callback called when the picker value is changed.|
-| `onClick` | `Function` | | Callback fired on Input click.|
-| `onDismiss` | `Function` | | Callback fired after dismissing the Dialog.|
-| `onEscKeyDown` | `Function` | | Callback called when the ESC key is pressed with the overlay active. |
-| `onKeyPress` | `Function` | | Callback invoked on Input key press.
-| `onOverlayClick`| `Function` | | Callback to be invoked when the dialog overlay is clicked.|
-| `readonly` | `Boolean` | | The input element will be readonly and look like disabled.|
+| `maxDate` | `Date` | | Date object with the maximum selectable date. |
+| `minDate` | `Date` | | Date object with the minimum selectable date. |
+| `onChange` | `Function` | | Callback called when the picker value is changed.|
+| `onClick` | `Function` | | Callback fired on Input click.|
+| `onDismiss` | `Function` | | Callback fired after dismissing the Dialog.|
+| `onEscKeyDown` | `Function` | | Callback called when the ESC key is pressed with the overlay active. |
+| `onKeyPress` | `Function` | | Callback invoked on Input key press.
+| `onOverlayClick`| `Function` | | Callback to be invoked when the dialog overlay is clicked.|
+| `readonly` | `Boolean` | | The input element will be readonly and look like disabled.|
| `sundayFirstDayOfWeek` | `Boolean`| `false` | Set week's first day to Sunday. Default week's first day is Monday ([ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Week_dates)). |
-| `value` | `Date` | | Date object with the currently selected date. |
+| `value` | `Date` | | Date object with the currently selected date. |
## Theme
diff --git a/components/date_picker/theme.css b/components/date_picker/theme.module.css
similarity index 91%
rename from components/date_picker/theme.css
rename to components/date_picker/theme.module.css
index ded096874..28920559e 100644
--- a/components/date_picker/theme.css
+++ b/components/date_picker/theme.module.css
@@ -1,6 +1,6 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.input:not(.disabled) > .inputElement {
cursor: pointer;
@@ -70,6 +70,19 @@
}
}
+.week {
+ display: flex;
+ flex-wrap: wrap;
+ font-size: var(--calendar-day-font-size);
+ height: var(--calendar-row-height);
+ line-height: var(--calendar-row-height);
+ opacity: 0.5;
+
+ & > span {
+ flex: 0 0 calc(100% / 7);
+ }
+}
+
.calendar {
background: var(--calendar-primary-contrast-color);
font-size: var(--font-size-small);
@@ -102,6 +115,39 @@
}
}
+.day {
+ flex: 0 0 calc(100% / 7);
+ padding: var(--calendar-day-padding-topbottom) var(--calendar-day-padding-leftright);
+
+ /* stylelint-disable */
+ & > span {
+ border-radius: 50%;
+ display: inline-block;
+ height: var(--calendar-row-height);
+ line-height: var(--calendar-row-height);
+ width: var(--calendar-row-height);
+ }
+ /* stylelint-enable */
+
+ &.active > span {
+ background: var(--calendar-primary-color);
+ color: var(--calendar-primary-contrast-color);
+ }
+
+ &:hover:not(.disabled) > span {
+ cursor: pointer;
+ }
+
+ &:hover:not(.active):not(.disabled) > span {
+ background: var(--calendar-primary-hover-color);
+ color: var(--calendar-primary-contrast-color);
+ }
+
+ &.disabled {
+ opacity: var(--calendar-day-disable-opacity);
+ }
+}
+
.title {
display: inline-block;
font-weight: 500;
@@ -128,67 +174,24 @@
}
}
-.week {
- display: flex;
- flex-wrap: wrap;
- font-size: var(--calendar-day-font-size);
- height: var(--calendar-row-height);
- line-height: var(--calendar-row-height);
- opacity: 0.5;
-
- & > span {
- flex: 0 0 calc(100% / 7);
- }
-}
-
.days {
display: flex;
flex-wrap: wrap;
font-size: var(--calendar-day-font-size);
}
-.day {
- flex: 0 0 calc(100% / 7);
- padding: var(--calendar-day-padding-topbottom) var(--calendar-day-padding-leftright);
-
- & > span {
- border-radius: 50%;
- display: inline-block;
- height: var(--calendar-row-height);
- line-height: var(--calendar-row-height);
- width: var(--calendar-row-height);
- }
-
- &:hover:not(.active):not(.disabled) > span {
- background: var(--calendar-primary-hover-color);
- color: var(--calendar-primary-contrast-color);
- }
-
- &.active > span {
- background: var(--calendar-primary-color);
- color: var(--calendar-primary-contrast-color);
- }
-
- &:hover:not(.disabled) > span {
- cursor: pointer;
- }
-
- &.disabled {
- opacity: var(--calendar-day-disable-opacity);
- }
-}
-
.month {
background-color: var(--calendar-primary-contrast-color);
+ width: 100%;
}
.slideRightEnter,
-.slideRightLeave {
+.slideRightExit {
position: absolute;
}
.slideRightEnterActive,
-.slideRightLeaveActive {
+.slideRightExitActive {
transition-duration: 350ms;
transition-property: transform, opacity;
transition-timing-function: ease-in-out;
@@ -204,20 +207,24 @@
}
}
-.slideRightLeave {
+.slideRightExit {
opacity: 1;
transform: translateX(0);
- &.slideRightLeaveActive {
+ &.slideRightExitActive {
opacity: 0;
transform: translateX(-100%);
}
}
.slideLeftEnter,
-.slideLeftLeave {
+.slideLeftExit {
position: absolute;
- transition-duration: 0.35s;
+}
+
+.slideLeftEnterActive,
+.slideLeftExitActive {
+ transition-duration: 350ms;
transition-property: transform, opacity;
transition-timing-function: ease-in-out;
}
@@ -232,11 +239,11 @@
}
}
-.slideLeftLeave {
+.slideLeftExit {
opacity: 1;
transform: translate3d(0, 0, 0);
- &.slideLeftLeaveActive {
+ &.slideLeftExitActive {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
diff --git a/components/dialog/Dialog.js b/components/dialog/Dialog.js
index 5f9e2d406..4167b18cf 100644
--- a/components/dialog/Dialog.js
+++ b/components/dialog/Dialog.js
@@ -39,9 +39,11 @@ const factory = (Overlay, Button) => {
{props.children}
{actions.length
- ?
+ ? (
+
+ )
: null
}
@@ -51,9 +53,9 @@ const factory = (Overlay, Button) => {
Dialog.propTypes = {
actions: PropTypes.arrayOf(PropTypes.shape({
+ children: PropTypes.node,
className: PropTypes.string,
label: PropTypes.string,
- children: PropTypes.node,
})),
active: PropTypes.bool,
children: PropTypes.node,
diff --git a/components/dialog/config.css b/components/dialog/config.module.css
similarity index 92%
rename from components/dialog/config.css
rename to components/dialog/config.module.css
index e3c1ccb98..01542e589 100644
--- a/components/dialog/config.css
+++ b/components/dialog/config.module.css
@@ -5,5 +5,5 @@
--dialog-content-padding: calc(2.4 * var(--unit));
--dialog-navigation-padding: calc(0.8 * var(--unit));
--dialog-translate-y: calc(4 * var(--unit));
- --overflow: hidden;
+ --overflow: inherit;
}
diff --git a/components/dialog/index.js b/components/dialog/index.js
index 132144562..66fce6919 100644
--- a/components/dialog/index.js
+++ b/components/dialog/index.js
@@ -3,7 +3,7 @@ import { DIALOG } from '../identifiers';
import { dialogFactory } from './Dialog';
import { Overlay } from '../overlay';
import { Button } from '../button';
-import theme from './theme.css';
+import theme from './theme.module.css';
const Dialog = dialogFactory(Overlay, Button);
const ThemedDialog = themr(DIALOG, theme)(Dialog);
diff --git a/components/dialog/readme.md b/components/dialog/readme.md
index a1a7ab72f..b00f2f118 100644
--- a/components/dialog/readme.md
+++ b/components/dialog/readme.md
@@ -48,12 +48,12 @@ If you want to provide a theme via context, the component key is `RTDialog`.
| `actions` | `Array` | `[]` | A array of objects representing the buttons for the dialog navigation area. The properties will be transferred to the buttons.|
| `active` | `Boolean` | `false` | If true, the dialog will be active.|
| `className` | `String` | `''` | Sets a class to give customized styles to the dialog.|
-| `onEscKeyDown` | `Function` | | Callback called when the ESC key is pressed with the overlay active. |
-| `onOverlayClick` | `Function` | | Callback to be invoked when the dialog overlay is clicked.|
-| `onOverlayMouseDown` | `Function` | | Callback called when the mouse button is pressed on the overlay. |
-| `onOverlayMouseMove` | `Function` | | Callback called when the mouse is moving over the overlay. |
-| `onOverlayMouseUp` | `Function` | | Callback called when the mouse button is released over the overlay. |
-| `title` | `String` | | The text string to use as standar title of the dialog.|
+| `onEscKeyDown` | `Function` | | Callback called when the ESC key is pressed with the overlay active. |
+| `onOverlayClick` | `Function` | | Callback to be invoked when the dialog overlay is clicked.|
+| `onOverlayMouseDown` | `Function` | | Callback called when the mouse button is pressed on the overlay. |
+| `onOverlayMouseMove` | `Function` | | Callback called when the mouse is moving over the overlay. |
+| `onOverlayMouseUp` | `Function` | | Callback called when the mouse button is released over the overlay. |
+| `title` | `String` | | The text string to use as standar title of the dialog.|
| `type` | `String` | `normal` | Used to determine the size of the dialog. It can be `small`, `normal`, `large` or `fullscreen`. |
Notice that the `fullscreen` option only applies on mobile devices with small screens (i.e. cellphones), and on other devices it behaves as a `large` dialog.
diff --git a/components/dialog/theme.css b/components/dialog/theme.module.css
similarity index 93%
rename from components/dialog/theme.css
rename to components/dialog/theme.module.css
index 294255ce1..84aa589f0 100644
--- a/components/dialog/theme.css
+++ b/components/dialog/theme.module.css
@@ -1,7 +1,7 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/media.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/media.module.css';
+@import 'http://github.com/config.module.css';
.wrapper {
align-items: center;
@@ -22,7 +22,6 @@
box-shadow: var(--zdepth-shadow-5);
display: flex;
flex-direction: column;
- max-height: 96vh;
max-width: 96vw;
opacity: 0;
overflow: var(--overflow);
diff --git a/components/drawer/Drawer.d.ts b/components/drawer/Drawer.d.ts
index 37cd30d11..6ae297e42 100644
--- a/components/drawer/Drawer.d.ts
+++ b/components/drawer/Drawer.d.ts
@@ -28,7 +28,7 @@ export interface DrawerTheme {
wrapper?: string;
}
-export interface DrawerProps extends ReactToolbox.Props {
+export interface DrawerCommonProps {
/**
* If true, the drawer will be visible.
* @default false
@@ -47,10 +47,6 @@ export interface DrawerProps extends ReactToolbox.Props {
* Callback function to be invoked when the overlay is clicked.
*/
onOverlayClick?: Function;
- /**
- * Classnames object defining the component style.
- */
- theme?: DrawerTheme;
/**
* Type of drawer. It can be left or right to display the drawer on the left or right side of the screen.
* @default left
@@ -63,6 +59,13 @@ export interface DrawerProps extends ReactToolbox.Props {
withOverlay?: boolean;
}
+export interface DrawerProps extends ReactToolbox.Props, DrawerCommonProps {
+ /**
+ * Classnames object defining the component style.
+ */
+ theme?: DrawerTheme;
+}
+
export class Drawer extends React.Component { }
export default Drawer;
diff --git a/components/drawer/config.css b/components/drawer/config.module.css
similarity index 81%
rename from components/drawer/config.css
rename to components/drawer/config.module.css
index afbdcfbf0..dd12d7a37 100644
--- a/components/drawer/config.css
+++ b/components/drawer/config.module.css
@@ -3,6 +3,6 @@
--drawer-border-color: var(--palette-grey-300);
--drawer-text-color: var(--palette-grey-800);
--drawer-width: calc(24 * var(--unit));
- --drawer-desktop-width: calc(4 * var(--standard-increment-desktop));
+ --drawer-desktop-width: calc(5 * var(--standard-increment-desktop));
--drawer-mobile-width: calc(5 * var(--standard-increment-mobile));
}
diff --git a/components/drawer/index.js b/components/drawer/index.js
index 7c8909317..71d03180a 100644
--- a/components/drawer/index.js
+++ b/components/drawer/index.js
@@ -2,7 +2,7 @@ import { themr } from 'react-css-themr';
import { DRAWER } from '../identifiers';
import { Overlay } from '../overlay';
import { drawerFactory } from './Drawer';
-import theme from './theme.css';
+import theme from './theme.module.css';
const Drawer = drawerFactory(Overlay);
const ThemedDrawer = themr(DRAWER, theme)(Drawer);
diff --git a/components/drawer/readme.md b/components/drawer/readme.md
index 159fc80a4..5a05628ce 100644
--- a/components/drawer/readme.md
+++ b/components/drawer/readme.md
@@ -38,7 +38,7 @@ If you want to provide a theme via context, the component key is `RTDrawer`.
| `active` | `Boolean` | `false` | If true, the drawer will be visible.|
| `className` | `String` | `''` | Sets a class to give customized styles to the drawer.|
| `insideTree` | `Boolean` | `false` | If true the Drawer is rendered inside the normal tree.|
-| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked.|
+| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked.|
| `type` | `String` | `left` | Type of drawer. It can be `left` or `right` to display the drawer on the left or right side of the screen.|
| `withOverlay` | `String` | `true` | If true display an Overlay that locks the scroll when the Drawer is active.|
diff --git a/components/drawer/theme.css b/components/drawer/theme.module.css
similarity index 89%
rename from components/drawer/theme.css
rename to components/drawer/theme.module.css
index fc8152f79..a0a3e3c62 100644
--- a/components/drawer/theme.css
+++ b/components/drawer/theme.module.css
@@ -1,7 +1,7 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/media.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/media.module.css';
+@import 'http://github.com/config.module.css';
.wrapper {
position: relative;
diff --git a/components/dropdown/Dropdown.d.ts b/components/dropdown/Dropdown.d.ts
index 4d14eeb79..3ed678170 100644
--- a/components/dropdown/Dropdown.d.ts
+++ b/components/dropdown/Dropdown.d.ts
@@ -30,10 +30,6 @@ export interface DropdownTheme {
* Used for the the label element.
*/
label?: string;
- /**
- * Used for setting the label from source
- */
- labelKey?: string;
/**
* Used when dropdown has required attribute.
*/
@@ -58,10 +54,6 @@ export interface DropdownTheme {
* Used for the list of values.
*/
values?: string;
- /**
- * Used for setting the value from source
- */
- valueKey: string;
}
export interface DropdownProps extends ReactToolbox.Props {
@@ -88,6 +80,10 @@ export interface DropdownProps extends ReactToolbox.Props {
* The text string to use for the floating label element.
*/
label?: string;
+ /**
+ * Used for setting the label from source
+ */
+ labelKey?: string;
/**
* Name for the input field.
*/
@@ -104,6 +100,11 @@ export interface DropdownProps extends ReactToolbox.Props {
* Callback function that is fired when the component is focused.
*/
onFocus?: Function;
+ /**
+ * If true, the dropdown has a required attribute.
+ * @default false
+ */
+ required?: boolean;
/**
* Array of data objects with the data to represent in the dropdown.
*/
@@ -121,10 +122,9 @@ export interface DropdownProps extends ReactToolbox.Props {
*/
value?: string | number;
/**
- * If true, the dropdown has a required attribute.
- * @default false
+ * Used for setting the value from source
*/
- required?: boolean;
+ valueKey?: string;
}
export class Dropdown extends React.Component { }
diff --git a/components/dropdown/Dropdown.js b/components/dropdown/Dropdown.js
index d31e7e4d7..5cdad85dc 100644
--- a/components/dropdown/Dropdown.js
+++ b/components/dropdown/Dropdown.js
@@ -130,7 +130,6 @@ const factory = (Input) => {
const client = event.target.getBoundingClientRect();
const screenHeight = window.innerHeight || document.documentElement.offsetHeight;
const up = this.props.auto ? client.top > ((screenHeight / 2) + client.height) : false;
- if (this.inputNode) this.inputNode.blur();
this.setState({ active: true, up });
};
@@ -207,6 +206,7 @@ const factory = (Input) => {
data-react-toolbox="dropdown"
onBlur={this.handleBlur}
onFocus={this.handleFocus}
+ tabIndex="-1"
>
{
onClick={this.handleClick}
required={this.props.required}
readOnly
- ref={(node) => { this.inputNode = node && node.getWrappedInstance(); }}
type={template && selected ? 'hidden' : null}
theme={theme}
themeNamespace="input"
diff --git a/components/dropdown/config.css b/components/dropdown/config.module.css
similarity index 85%
rename from components/dropdown/config.css
rename to components/dropdown/config.module.css
index fa0a790e0..3a80db2fb 100644
--- a/components/dropdown/config.css
+++ b/components/dropdown/config.module.css
@@ -3,7 +3,7 @@
--dropdown-color-white: var(--color-white);
--dropdown-color-primary: var(--color-primary);
--dropdown-color-primary-contrast: var(--color-primary-contrast);
- --dropdown-color-disabled: color(var(--color-black) a(26%));
+ --dropdown-color-disabled: color-mod(var(--color-black) a(26%));
--dropdown-value-hover-background: var(--palette-grey-200);
--dropdown-overflow-max-height: 45vh;
--dropdown-value-border-radius: calc(0.2 * var(--unit));
diff --git a/components/dropdown/index.js b/components/dropdown/index.js
index 419b264af..0c8349a81 100644
--- a/components/dropdown/index.js
+++ b/components/dropdown/index.js
@@ -2,7 +2,7 @@ import { themr } from 'react-css-themr';
import { DROPDOWN } from '../identifiers';
import { dropdownFactory } from './Dropdown';
import { Input } from '../input';
-import theme from './theme.css';
+import theme from './theme.module.css';
const Dropdown = dropdownFactory(Input);
const ThemedDropdown = themr(DROPDOWN, theme)(Dropdown);
diff --git a/components/dropdown/readme.md b/components/dropdown/readme.md
index 7d7870a4c..14be8dfac 100644
--- a/components/dropdown/readme.md
+++ b/components/dropdown/readme.md
@@ -43,14 +43,14 @@ If you want to provide a theme via context, the component key is `RTDropdown`.
| `auto` | `Boolean` | `true` | If true, the dropdown will open up or down depending on the position in the screen.|
| `className` | `String` | `''` | Set the class to give custom styles to the dropdown.|
| `disabled` | `Boolean` | `false` | Set the component as disabled.|
-| `error` | `String` | | Give an error string to display under the field.|
-| `label` | `String` | | The text string to use for the floating label element.|
-| `onBlur` | `Function` | | Callback function that is fired when the component is blurred.|
-| `onChange` | `Function` | | Callback function that is fired when the component's value changes.|
-| `onFocus` | `Function` | | Callback function that is fired when the component is focused.|
-| `source` | `Array` | | Array of data objects with the data to represent in the dropdown.|
-| `template` | `Function` | | Callback function that returns a JSX template to represent the element.|
-| `value` | `String` | | Default value using JSON data.|
+| `error` | `String` | | Give an error string to display under the field.|
+| `label` | `String` | | The text string to use for the floating label element.|
+| `onBlur` | `Function` | | Callback function that is fired when the component is blurred.|
+| `onChange` | `Function` | | Callback function that is fired when the component's value changes.|
+| `onFocus` | `Function` | | Callback function that is fired when the component is focused.|
+| `source` | `Array` | | Array of data objects with the data to represent in the dropdown.|
+| `template` | `Function` | | Callback function that returns a JSX template to represent the element.|
+| `value` | `String` | | Default value using JSON data.|
| `required` | `Boolean` | `false` | If true, the dropdown has a required attribute.|
## Theming
diff --git a/components/dropdown/theme.css b/components/dropdown/theme.module.css
similarity index 95%
rename from components/dropdown/theme.css
rename to components/dropdown/theme.module.css
index 02f068e68..fe45f05a2 100644
--- a/components/dropdown/theme.css
+++ b/components/dropdown/theme.module.css
@@ -1,7 +1,80 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/input/config.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/input/config.module.css';
+@import 'http://github.com/config.module.css';
+
+.value {
+ & > input {
+ cursor: pointer;
+ }
+
+ &::after {
+ border-left: var(--dropdown-value-border-size) solid transparent;
+ border-right: var(--dropdown-value-border-size) solid transparent;
+ border-top: var(--dropdown-value-border-size) solid var(--input-text-bottom-border-color);
+ content: '';
+ height: 0;
+ pointer-events: none;
+ position: absolute;
+ right: var(--input-chevron-offset);
+ top: 50%;
+ transition: transform var(--animation-duration) var(--animation-curve-default);
+ width: 0;
+ }
+}
+
+.label {
+ color: var(--input-text-label-color);
+ font-size: var(--input-label-font-size);
+ left: 0;
+ line-height: var(--input-field-font-size);
+ position: absolute;
+ top: var(--input-focus-label-top);
+
+ & .required {
+ color: var(--input-text-error-color);
+ }
+}
+
+.values {
+ background-color: var(--dropdown-color-white);
+ border-radius: var(--dropdown-value-border-radius);
+ list-style: none;
+ margin: 0;
+ overflow-y: auto;
+ padding: 0;
+ position: absolute;
+ transition-duration: var(--animation-duration);
+ transition-property: max-height, box-shadow;
+ transition-timing-function: var(--animation-curve-default);
+ width: 100%;
+ z-index: var(--z-index-high);
+
+ & > * {
+ cursor: pointer;
+ overflow: hidden;
+ padding: var(--unit);
+ position: relative;
+
+ &:hover:not(.disabled) {
+ background-color: var(--dropdown-value-hover-background);
+ }
+
+ &.selected {
+ color: var(--dropdown-color-primary);
+ }
+
+ &.disabled {
+ color: var(--dropdown-color-disabled);
+ cursor: not-allowed;
+ }
+ }
+
+ &::-webkit-scrollbar {
+ height: 0;
+ width: 0;
+ }
+}
.dropdown {
position: relative;
@@ -44,24 +117,13 @@
}
}
-.value {
- & > input {
- cursor: pointer;
- }
-
- &::after {
- border-left: var(--dropdown-value-border-size) solid transparent;
- border-right: var(--dropdown-value-border-size) solid transparent;
- border-top: var(--dropdown-value-border-size) solid var(--input-text-bottom-border-color);
- content: '';
- height: 0;
- pointer-events: none;
- position: absolute;
- right: var(--input-chevron-offset);
- top: 50%;
- transition: transform var(--animation-duration) var(--animation-curve-default);
- width: 0;
- }
+.templateValue {
+ background-color: var(--input-text-background-color);
+ border-bottom: 1px solid var(--input-text-bottom-border-color);
+ color: var(--color-text);
+ min-height: var(--input-field-height);
+ padding: var(--input-field-padding) 0;
+ position: relative;
}
.field {
@@ -96,71 +158,9 @@
}
}
-.templateValue {
- background-color: var(--input-text-background-color);
- border-bottom: 1px solid var(--input-text-bottom-border-color);
- color: var(--color-text);
- min-height: var(--input-field-height);
- padding: var(--input-field-padding) 0;
- position: relative;
-}
-
-.label {
- color: var(--input-text-label-color);
- font-size: var(--input-label-font-size);
- left: 0;
- line-height: var(--input-field-font-size);
- position: absolute;
- top: var(--input-focus-label-top);
-
- & .required {
- color: var(--input-text-error-color);
- }
-}
-
.error {
color: var(--input-text-error-color);
font-size: var(--input-label-font-size);
line-height: var(--input-underline-height);
margin-bottom: calc(-1 * var(--input-underline-height));
}
-
-.values {
- background-color: var(--dropdown-color-white);
- border-radius: var(--dropdown-value-border-radius);
- list-style: none;
- margin: 0;
- overflow-y: auto;
- padding: 0;
- position: absolute;
- transition-duration: var(--animation-duration);
- transition-property: max-height, box-shadow;
- transition-timing-function: var(--animation-curve-default);
- width: 100%;
- z-index: var(--z-index-high);
-
- & > * {
- cursor: pointer;
- overflow: hidden;
- padding: var(--unit);
- position: relative;
-
- &:hover:not(.disabled) {
- background-color: var(--dropdown-value-hover-background);
- }
-
- &.selected {
- color: var(--dropdown-color-primary);
- }
-
- &.disabled {
- color: var(--dropdown-color-disabled);
- cursor: not-allowed;
- }
- }
-
- &::-webkit-scrollbar {
- height: 0;
- width: 0;
- }
-}
diff --git a/components/font_icon/readme.md b/components/font_icon/readme.md
index 4b0fee55d..cab39c81d 100644
--- a/components/font_icon/readme.md
+++ b/components/font_icon/readme.md
@@ -22,4 +22,4 @@ const FontIcons = () => (
|:-----|:-----|:-----|:-----|
| `alt` | `String` | `''` | The text used to set the `aria-label` attribute.
| `className` | `String` | `''` | The class name to give custom styles such as sizing.|
-| `value` | `String` or `Element` | | The key string for the icon you want be displayed.|
+| `value` | `String` or `Element` | | The key string for the icon you want be displayed.|
diff --git a/components/hoc/ActivableRenderer.js b/components/hoc/ActivableRenderer.js
index edb6455c8..fd116c39b 100644
--- a/components/hoc/ActivableRenderer.js
+++ b/components/hoc/ActivableRenderer.js
@@ -1,8 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-const ActivableRendererFactory = (options = { delay: 500 }) =>
- ActivableComponent => class ActivableRenderer extends Component {
+const ActivableRendererFactory = (options = { delay: 500 }) => ActivableComponent => class ActivableRenderer extends Component { // eslint-disable-line max-len
static propTypes = {
active: PropTypes.bool.isRequired,
children: PropTypes.node,
@@ -28,13 +27,6 @@ const ActivableRendererFactory = (options = { delay: 500 }) =>
clearTimeout(this.unrenderTimeout);
}
- renderAndActivate() {
- if (this.unrenderTimeout) clearTimeout(this.unrenderTimeout);
- this.setState({ rendered: true, active: false }, () => {
- this.activateTimeout = setTimeout(() => this.setState({ active: true }), 20);
- });
- }
-
deactivateAndUnrender() {
this.setState({ rendered: true, active: false }, () => {
this.unrenderTimeout = setTimeout(() => {
@@ -44,6 +36,13 @@ const ActivableRendererFactory = (options = { delay: 500 }) =>
});
}
+ renderAndActivate() {
+ if (this.unrenderTimeout) clearTimeout(this.unrenderTimeout);
+ this.setState({ rendered: true, active: false }, () => {
+ this.activateTimeout = setTimeout(() => this.setState({ active: true }), 20);
+ });
+ }
+
render() {
const { delay, ...others } = this.props; // eslint-disable-line no-unused-vars
const { active, rendered } = this.state;
@@ -51,6 +50,6 @@ const ActivableRendererFactory = (options = { delay: 500 }) =>
?
: null;
}
- };
+};
export default ActivableRendererFactory;
diff --git a/components/hoc/Portal.js b/components/hoc/Portal.js
index 99769747e..cdd55036f 100644
--- a/components/hoc/Portal.js
+++ b/components/hoc/Portal.js
@@ -1,12 +1,14 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
+import styleShape from 'react-style-proptype';
class Portal extends Component {
static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
container: PropTypes.node,
+ style: styleShape,
}
static defaultProps = {
@@ -55,7 +57,11 @@ class Portal extends Component {
_getOverlay() {
if (!this.props.children) return null;
- return
{this.props.children}
;
+ return (
+
+ {this.props.children}
+
+ );
}
_renderOverlay() {
@@ -97,7 +103,6 @@ class Portal extends Component {
render() {
return null;
}
-
}
function getContainer(container) {
diff --git a/components/index.d.ts b/components/index.d.ts
index 9b0f4da49..4d7246877 100644
--- a/components/index.d.ts
+++ b/components/index.d.ts
@@ -1,4 +1,5 @@
import * as React from "react";
+import { ThemeProviderProps } from "react-css-themr";
export declare namespace ReactToolbox {
interface Props extends React.Attributes {
/**
@@ -46,6 +47,7 @@ export declare namespace ReactToolbox {
* Set inline style for the root component.
*/
style?: React.CSSProperties;
+ innerRef?: ThemeProviderProps["innerRef"];
}
}
diff --git a/components/index.js b/components/index.js
index f753885bb..6dbe5f4bb 100644
--- a/components/index.js
+++ b/components/index.js
@@ -21,11 +21,11 @@ export * from './menu';
export { default as Navigation } from './navigation';
export { default as ProgressBar } from './progress_bar';
export * from './radio';
-export Ripple from './ripple';
+export { default as Ripple } from './ripple';
export { default as Slider } from './slider';
export { default as Snackbar } from './snackbar';
export { default as Switch } from './switch';
export * from './table';
export * from './tabs';
-export Tooltip from './tooltip';
+export { default as Tooltip } from './tooltip';
export { default as TimePicker } from './time_picker';
diff --git a/components/input/Input.d.ts b/components/input/Input.d.ts
index f3c9dc9f4..dc12e0fcf 100644
--- a/components/input/Input.d.ts
+++ b/components/input/Input.d.ts
@@ -42,6 +42,10 @@ export interface InputTheme {
* Used for the HTML input element.
*/
inputElement?: string;
+ /**
+ * Used for the label when the input has a label.
+ */
+ label?: string;
/**
* Used in case the input is required.
*/
@@ -128,7 +132,7 @@ export interface InputProps extends ReactToolbox.Props {
/**
* The number of rows the multiline input field has.
*/
- rows?:number;
+ rows?: number;
/**
* Classnames object defining the component style.
*/
diff --git a/components/input/Input.js b/components/input/Input.js
index 545fe8d39..6d642916c 100644
--- a/components/input/Input.js
+++ b/components/input/Input.js
@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
+import { isValuePresent } from '../utils/utils';
import { INPUT } from '../identifiers';
import InjectedFontIcon from '../font_icon/FontIcon';
@@ -37,6 +38,7 @@ const factory = (FontIcon) => {
onFocus: PropTypes.func,
onKeyPress: PropTypes.func,
required: PropTypes.bool,
+ role: PropTypes.string,
rows: PropTypes.number,
theme: PropTypes.shape({
bar: PropTypes.string,
@@ -67,6 +69,7 @@ const factory = (FontIcon) => {
floating: true,
multiline: false,
required: false,
+ role: 'input',
type: 'text',
};
@@ -110,9 +113,9 @@ const factory = (FontIcon) => {
handleAutoresize = () => {
const element = this.inputNode;
- const rows = this.props.rows;
+ const { rows } = this.props;
- if (typeof rows === 'number' && !isNaN(rows)) {
+ if (typeof rows === 'number' && !Number.isNaN(rows)) {
element.style.height = null;
} else {
// compute the height difference between inner height and outer height
@@ -136,7 +139,7 @@ const factory = (FontIcon) => {
// replace the selected characters, so the length of value doesn't actually
// increase.
const isReplacing = event.target.selectionEnd - event.target.selectionStart;
- const value = event.target.value;
+ const { value } = event.target;
if (!isReplacing && value.length === maxLength) {
event.preventDefault();
@@ -157,17 +160,12 @@ const factory = (FontIcon) => {
this.inputNode.focus();
}
- valuePresent = value => (
- value !== null
- && value !== undefined
- && value !== ''
- && !(typeof value === 'number' && isNaN(value))
- )
-
render() {
- const { children, defaultValue, disabled, error, floating, hint, icon,
- name, label: labelText, maxLength, multiline, required,
- theme, type, value, onKeyPress, rows = 1, ...others } = this.props;
+ const {
+ children, defaultValue, disabled, error, floating, hint, icon,
+ name, label: labelText, maxLength, multiline, required, role,
+ theme, type, value, onKeyPress, rows = 1, ...others
+ } = this.props;
const length = maxLength && value ? value.length : 0;
const labelClassName = classnames(theme.label, { [theme.fixed]: !floating });
@@ -178,14 +176,14 @@ const factory = (FontIcon) => {
[theme.withIcon]: icon,
}, this.props.className);
- const valuePresent = this.valuePresent(value) || this.valuePresent(defaultValue);
+ const valuePresent = isValuePresent(value) || isValuePresent(defaultValue);
const inputElementProps = {
...others,
className: classnames(theme.inputElement, { [theme.filled]: valuePresent }),
onChange: this.handleChange,
ref: (node) => { this.inputNode = node; },
- role: 'input',
+ role,
name,
defaultValue,
disabled,
@@ -207,14 +205,20 @@ const factory = (FontIcon) => {
{icon ? : null}
{labelText
- ?
+ ? (
+
+ )
: null}
{hint ? {hint} : null}
{error ? {error} : null}
- {maxLength ? {length}/{maxLength} : null}
+ {maxLength ? (
+
+ {`${length}/${maxLength}`}
+
+ ) : null}
{children}
);
@@ -225,6 +229,6 @@ const factory = (FontIcon) => {
};
const Input = factory(InjectedFontIcon);
-export default themr(INPUT, null, { withRef: true })(Input);
+export default themr(INPUT)(Input);
export { factory as inputFactory };
export { Input };
diff --git a/components/input/config.css b/components/input/config.module.css
similarity index 84%
rename from components/input/config.css
rename to components/input/config.module.css
index 58e389e5e..25b263fd8 100644
--- a/components/input/config.css
+++ b/components/input/config.module.css
@@ -6,8 +6,9 @@
--input-label-font-size: calc(1.2 * var(--unit));
--input-focus-label-top: calc(0.6 * var(--unit));
--input-text-background-color: transparent;
- --input-text-label-color: color(var(--color-black) a(26%));
- --input-text-bottom-border-color: color(var(--color-black) a(12%));
+ --input-text-label-color: color-mod(var(--color-text) a(26%));
+ --input-text-input-element-color: var(--color-text);
+ --input-text-bottom-border-color: color-mod(var(--color-text) a(12%));
--input-text-highlight-color: var(--color-primary);
--input-text-disabled-color: var(--input-text-bottom-border-color);
--input-text-disabled-text-color: var(--input-text-label-color);
diff --git a/components/input/index.js b/components/input/index.js
index 062dbebb5..aeb5bfe25 100644
--- a/components/input/index.js
+++ b/components/input/index.js
@@ -2,7 +2,7 @@ import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers';
import { inputFactory } from './Input';
import { FontIcon } from '../font_icon/FontIcon';
-import theme from './theme.css';
+import theme from './theme.module.css';
const Input = inputFactory(FontIcon);
const ThemedInput = themr(INPUT, theme, { withRef: true })(Input);
diff --git a/components/input/readme.md b/components/input/readme.md
index 97b9ea9b5..a0c99afec 100644
--- a/components/input/readme.md
+++ b/components/input/readme.md
@@ -9,18 +9,18 @@ import Input from 'react-toolbox/lib/input';
class InputTest extends React.Component {
state = { name: '', phone: '', email: '', hint: '' };
- handleChange = (name, value) => {
- this.setState({ [name]: value });
+ handleChange = (value, ev) => {
+ this.setState({ [ev.target.name]: value });
};
render () {
return (
-
+
-
-
- J} />
+
+
+ J} />
);
}
@@ -35,21 +35,21 @@ If you want to provide a theme via context, the component key is `RTInput`.
|:-----|:-----|:-----|:-----|
| `className` | `String` | `''` | Sets a class name to give custom styles.|
| `disabled` | `Boolean` | `false` | If true, component will be disabled.|
-| `error` | `String` or `Node` | | Give an error node to display under the field.|
+| `error` | `String` or `Node` | | Give an error node to display under the field.|
| `floating` | `Boolean` | `true` | Indicates if the label is floating in the input field or not.|
| `hint` | `String` or `Node` | `''` | The text string to use for hint text element.|
-| `icon` | `String` or `Element` | | Name of an icon to use as a label for the input.|
-| `label` | `String` or `Node` | | The text string to use for the floating label element.|
-| `maxLength` | `Number` | | Specifies the maximum number of characters allowed in the component.|
+| `icon` | `String` or `Element` | | Name of an icon to use as a label for the input.|
+| `label` | `String` or `Node` | | The text string to use for the floating label element.|
+| `maxLength` | `Number` | | Specifies the maximum number of characters allowed in the component.|
| `multiline` | `Boolean` | `false` | If true, a textarea element will be rendered. The textarea also grows and shrinks according to the number of lines.|
-| `rows` | `Number` | | The number of rows the multiline input field has.|
-| `onBlur` | `Function` | | Callback function that is fired when component is blurred.|
-| `onChange` | `Function` | | Callback function that is fired when the component's value changes.|
-| `onFocus` | `Function` | | Callback function that is fired when component is focused.|
-| `onKeyPress` | `Function` | | Callback function that is fired when a key is pressed.|
+| `rows` | `Number` | | The number of rows the multiline input field has.|
+| `onBlur` | `Function` | | Callback function that is fired when component is blurred.|
+| `onChange` | `Function` | | Callback function that is fired when the component's value changes.|
+| `onFocus` | `Function` | | Callback function that is fired when component is focused.|
+| `onKeyPress` | `Function` | | Callback function that is fired when a key is pressed.|
| `required` | `Boolean` | `false` | If true, the html input has a required attribute.|
| `type` | `String` | `text` | Type of the input element. It can be a valid HTML5 input type|
-| `value` | `Any` | | Current value of the input element.|
+| `value` | `Any` | | Current value of the input element.|
## Theming
@@ -71,7 +71,7 @@ If you want to provide a theme via context, the component key is `RTInput`.
## Methods
-The `Input` component has some imperative methods that are used as a bypass to the native rendered DOM element. To call this methods you will need to retrieve the instance of the component. Check the [Install](http://react-toolbox.com/#/install) section for details on how to do this. The methods included for the `Input` are:
+The `Input` component has some imperative methods that are used as a bypass to the native rendered DOM element. To call this methods you will need to retrieve the instance of the component. Check the [Install](http://react-toolbox.io/#/install) section for details on how to do this. The methods included for the `Input` are:
- `blur` used to blur the `input` element.
- `focus` used to focus the `input` element.
diff --git a/components/input/theme.css b/components/input/theme.module.css
similarity index 90%
rename from components/input/theme.css
rename to components/input/theme.module.css
index 512e25e9e..fc60c1841 100644
--- a/components/input/theme.css
+++ b/components/input/theme.module.css
@@ -1,6 +1,6 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.input {
padding: var(--input-padding) 0;
@@ -27,92 +27,49 @@
width: var(--input-icon-size);
}
-.inputElement {
- background-color: var(--input-text-background-color);
- border-bottom: 1px solid var(--input-text-bottom-border-color);
- border-left: 0;
- border-right: 0;
- border-top: 0;
- color: var(--color-text);
- display: block;
- font-size: var(--input-field-font-size);
- outline: none;
- padding: var(--input-field-padding) 0;
- width: 100%;
-
- &:focus:not([disabled]):not([readonly]) {
- & ~ .bar::before,
- & ~ .bar::after {
- width: 50%;
- }
-
- & ~ .label:not(.fixed) {
- color: var(--input-text-highlight-color);
- }
-
- & ~ .label > .required {
- color: var(--input-text-required-color);
- }
-
- & ~ .hint {
- display: block;
- opacity: var(--input-hint-opacity);
- }
-
- & ~ .icon {
- color: var(--input-text-highlight-color);
- }
-
- &.filled ~ .hint {
- opacity: 0;
- }
- }
-
- &:focus:not([disabled]):not([readonly]),
- &.filled,
- &[type='date'],
- &[type='time'] {
- & ~ .label:not(.fixed) {
- font-size: var(--input-label-font-size);
- top: var(--input-focus-label-top);
- }
- }
+.counter {
+ color: var(--input-text-label-color);
+ position: absolute;
+ right: 0;
+}
- &.filled ~ .label.fixed,
- &.filled ~ .hint {
- display: none;
- }
+.counter,
+.error {
+ color: var(--input-text-error-color);
+ font-size: var(--input-label-font-size);
+ line-height: var(--input-underline-height);
+ margin-bottom: calc(-1 * var(--input-underline-height));
}
-.label {
+.hint {
color: var(--input-text-label-color);
font-size: var(--input-field-font-size);
left: 0;
line-height: var(--input-field-font-size);
+ opacity: var(--input-hint-opacity);
pointer-events: none;
position: absolute;
top: calc(var(--input-padding) + 1.5 * var(--input-field-padding));
transition-duration: var(--animation-duration);
- transition-property: top, font-size, color;
+ transition-property: opacity;
transition-timing-function: var(--animation-curve-default);
-
- &.fixed ~ .hint {
- display: none;
- }
}
-.hint {
+.label {
color: var(--input-text-label-color);
font-size: var(--input-field-font-size);
left: 0;
line-height: var(--input-field-font-size);
- opacity: var(--input-hint-opacity);
pointer-events: none;
position: absolute;
top: calc(var(--input-padding) + 1.5 * var(--input-field-padding));
transition-duration: var(--animation-duration);
- transition-property: opacity;
+ transition-property: top, font-size, color;
transition-timing-function: var(--animation-curve-default);
+
+ &.fixed ~ .hint {
+ display: none;
+ }
}
.bar {
@@ -142,23 +99,8 @@
}
}
-.error,
-.counter {
- color: var(--input-text-error-color);
- font-size: var(--input-label-font-size);
- line-height: var(--input-underline-height);
- margin-bottom: calc(-1 * var(--input-underline-height));
-}
-
-.counter {
- color: var(--input-text-label-color);
- position: absolute;
- right: 0;
-}
-
-.disabled > .inputElement {
- border-bottom-style: dotted;
- color: var(--input-text-disabled-text-color);
+.hidden {
+ display: none;
}
.errored {
@@ -179,6 +121,70 @@
}
}
-.hidden {
- display: none;
+.disabled > .inputElement {
+ border-bottom-style: dashed;
+ color: var(--input-text-disabled-text-color);
+}
+
+/* stylelint-disable */
+.inputElement {
+ background-color: var(--input-text-background-color);
+ border-bottom: 1px solid var(--input-text-bottom-border-color);
+ border-left: 0;
+ border-radius: 0;
+ border-right: 0;
+ border-top: 0;
+ color: var(--input-text-input-element-color);
+ display: block;
+ font-size: var(--input-field-font-size);
+ outline: none;
+ padding: var(--input-field-padding) 0;
+ width: 100%;
+
+ &:required {
+ box-shadow: none;
+ }
+
+ &.filled ~ .hint,
+ &.filled ~ .label.fixed {
+ display: none;
+ }
+
+ &.filled,
+ &[type='date'],
+ &[type='time'],
+ &:focus:not([disabled]):not([readonly]) {
+ & ~ .label:not(.fixed) {
+ font-size: var(--input-label-font-size);
+ top: var(--input-focus-label-top);
+ }
+ }
+
+ &:focus:not([disabled]):not([readonly]) {
+ & ~ .bar::before,
+ & ~ .bar::after {
+ width: 50%;
+ }
+
+ & ~ .label:not(.fixed) {
+ color: var(--input-text-highlight-color);
+ }
+
+ & ~ .label > .required {
+ color: var(--input-text-required-color);
+ }
+
+ & ~ .hint {
+ display: block;
+ opacity: var(--input-hint-opacity);
+ }
+
+ & ~ .icon {
+ color: var(--input-text-highlight-color);
+ }
+
+ &.filled ~ .hint {
+ opacity: 0;
+ }
+ }
}
diff --git a/components/layout/Layout.d.ts b/components/layout/Layout.d.ts
index 477b57b9f..afc943e7c 100644
--- a/components/layout/Layout.d.ts
+++ b/components/layout/Layout.d.ts
@@ -1,8 +1,5 @@
import * as React from "react";
import ReactToolbox from "../index";
-import { NavDrawer } from './NavDrawer';
-import { Panel } from './Panel';
-import { Sidebar } from './Sidebar';
export interface LayoutTheme {
appbarFixed?: string;
@@ -54,7 +51,7 @@ export interface LayoutProps extends ReactToolbox.Props {
/**
* Children to pass through the component.
*/
- children?: [NavDrawer | Panel | Sidebar];
+ children?: JSX.Element | JSX.Element[];
/**
* Classnames object defining the component style.
*/
diff --git a/components/layout/Layout.js b/components/layout/Layout.js
index 8c540436c..4806c6759 100644
--- a/components/layout/Layout.js
+++ b/components/layout/Layout.js
@@ -63,7 +63,9 @@ const factory = (AppBar, NavDrawer, Sidebar) => {
}
render() {
- const { children, className, theme, ...rest } = this.props;
+ const {
+ children, className, theme, ...rest
+ } = this.props;
const appBar = filterReactChildren(children, isAppBar)[0];
const navDrawer = filterReactChildren(children, isNavDrawer)[0];
const sidebar = filterReactChildren(children, isSidebar)[0];
diff --git a/components/layout/NavDrawer.d.ts b/components/layout/NavDrawer.d.ts
index c6cb56504..16e78173e 100644
--- a/components/layout/NavDrawer.d.ts
+++ b/components/layout/NavDrawer.d.ts
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DrawerProps } from '../drawer/Drawer';
+import { DrawerCommonProps } from '../drawer/Drawer';
export interface NavDrawerTheme {
/**
@@ -12,7 +12,7 @@ export interface NavDrawerTheme {
clipped?: string;
}
-export interface NavDrawerProps extends DrawerProps {
+export interface NavDrawerProps extends DrawerCommonProps {
/**
* If true, the drawer will be shown as an overlay.
* @default false
diff --git a/components/layout/Panel.js b/components/layout/Panel.js
index 244104054..432d554c3 100644
--- a/components/layout/Panel.js
+++ b/components/layout/Panel.js
@@ -4,7 +4,9 @@ import cn from 'classnames';
import { themr } from 'react-css-themr';
import { LAYOUT } from '../identifiers';
-const Panel = ({ bodyScroll, children, className, theme, ...other }) => {
+const Panel = ({
+ bodyScroll, children, className, theme, ...other
+}) => {
const _className = cn(theme.panel, { [theme.bodyScroll]: bodyScroll }, className);
return (
diff --git a/components/layout/Sidebar.d.ts b/components/layout/Sidebar.d.ts
index 56d2075c7..e8c2a5b6b 100644
--- a/components/layout/Sidebar.d.ts
+++ b/components/layout/Sidebar.d.ts
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DrawerProps } from '../drawer/Drawer';
+import { DrawerCommonProps } from '../drawer/Drawer';
export interface SidebarTheme {
/**
@@ -12,7 +12,7 @@ export interface SidebarTheme {
pinned?: string;
}
-export interface SidebarProps extends DrawerProps {
+export interface SidebarProps extends DrawerCommonProps {
/**
* If true, when the `AppBar` gets pinned, it will stand over the `Drawer`.
* @default false
diff --git a/components/layout/Sidebar.js b/components/layout/Sidebar.js
index 562dde224..8a161e3d6 100644
--- a/components/layout/Sidebar.js
+++ b/components/layout/Sidebar.js
@@ -41,6 +41,7 @@ const factory = (Drawer) => {
clipped: PropTypes.bool,
permanentAt: PropTypes.oneOf(['sm', 'smTablet', 'md', 'lg', 'lgTablet', 'xl', 'xxl', 'xxxl']),
pinned: PropTypes.bool,
+ right: PropTypes.bool,
theme: PropTypes.shape({
clipped: PropTypes.string,
pinned: PropTypes.string,
diff --git a/components/layout/index.js b/components/layout/index.js
index 18b9ad55c..c2921bff8 100644
--- a/components/layout/index.js
+++ b/components/layout/index.js
@@ -6,7 +6,7 @@ import { navDrawerFactory } from './NavDrawer';
import { Panel } from './Panel';
import { AppBar } from '../app_bar';
import { Drawer } from '../drawer';
-import theme from './theme.css';
+import theme from './theme.module.css';
const injectTheme = component => themr(LAYOUT, theme)(component);
const ThemedNavDrawer = injectTheme(navDrawerFactory(Drawer));
diff --git a/components/layout/readme.md b/components/layout/readme.md
index 3ad0e6681..97359613d 100644
--- a/components/layout/readme.md
+++ b/components/layout/readme.md
@@ -137,8 +137,8 @@ If the column layout does not suit your needs, simply fill the content area with
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
-| `children` | `Nodes` | | Can hold a `Panel`, along with a `NavDrawer`, a `Sidebar` and an `AppBar` |
-| `className` | `string` | | Additional class(es) for custom styling. |
+| `children` | `Nodes` | | Can hold a `Panel`, along with a `NavDrawer`, a `Sidebar` and an `AppBar` |
+| `className` | `string` | | Additional class(es) for custom styling. |
### Theme
The themed key the `Layout` in general is `ToolboxLayout`. We add classes to the root element depending on the parsed children:
@@ -162,7 +162,7 @@ The [navigation drawer](https://material.google.com/patterns/navigation-drawer.h
| Breakpoint | Drawer Width | Notes |
|:-----|:-----|:-----|
| < `xs` | 280px or (Screen width - 85px) | whichever is smaller |
-| > `xs` | 320px | |
+| > `xs` | 320px | |
| > `xs` | 400px | If property `width` is set to `wide` |
The drawer can be docked to the left side of the screen or can float temporarily as an overlay. You can control the drawer's display manually `active` and `pinned` properties, and can also specify a breakpoint at which the drawer automatically becomes permanently docked. You can also use a `clipped` property when it's pinned so the `AppBar` would stick over the Drawer.
@@ -171,11 +171,11 @@ The drawer can be docked to the left side of the screen or can float temporarily
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
| `active` | `bool` | `false` | If true, the drawer will be shown as an overlay. |
-| `className` | `string` | | Additional class(es) for custom styling. |
+| `className` | `string` | | Additional class(es) for custom styling. |
| `clipped` | `bool` | `false` | If true, when the `AppBar` gets pinned, it will stand over the `Drawer`. |
-| `permanentAt` | `enum`(`'sm'`,`'smTablet'`,`'md'`,`'lg'`,`'lgTablet'`,`'xl'`,`'xxl'`,`'xxxl'`) | | The breakpoint at which the drawer is automatically pinned. |
+| `permanentAt` | `enum`(`'sm'`,`'smTablet'`,`'md'`,`'lg'`,`'lgTablet'`,`'xl'`,`'xxl'`,`'xxxl'`) | | The breakpoint at which the drawer is automatically pinned. |
| `pinned` | `bool` | `false` | If true, the drawer will be pinned open. `pinned` takes precedence over `active`. |
-| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked. It only works if the `Drawer` is actually displaying and Overlay|
+| `onOverlayClick` | `Function` | | Callback function to be invoked when the overlay is clicked. It only works if the `Drawer` is actually displaying and Overlay|
### Theme
@@ -193,8 +193,8 @@ The `Panel` is the main content area within a `Layout`. By default we assume it
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
-| `bodyScroll` | `Boolean` | | You can set it to true in case you are using a pinned Sidebar so it takes an scrolled `div` instead of using the document scroll. |
-| `className` | `string` | | Additional class(es) for custom styling. |
+| `bodyScroll` | `Boolean` | | You can set it to true in case you are using a pinned Sidebar so it takes an scrolled `div` instead of using the document scroll. |
+| `className` | `string` | | Additional class(es) for custom styling. |
### Theme
| Name | Description|
@@ -212,7 +212,7 @@ The `Sidebar` is an extra drawer that docks to the right side of the `Layout`. T
| `width` | `enum`(`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`10`,`11`,`12`,`25`,`33`,`50`,`66`,`75`,`100`) | `5` | Width in standard increments (1-12) or percentage (25, 33, 50, 66, 75, 100) |
| `pinned` | `bool` | `false` | If true, the sidebar will be pinned open. |
| `scrollY` | `bool` | `false` | If true, the sidebar will vertically scroll all content. |
-| `className` | `string` | | Additional class(es) for custom styling. |
+| `className` | `string` | | Additional class(es) for custom styling. |
### Theme
diff --git a/components/layout/theme.css b/components/layout/theme.module.css
similarity index 89%
rename from components/layout/theme.css
rename to components/layout/theme.module.css
index 33a36b0ce..054a61263 100644
--- a/components/layout/theme.css
+++ b/components/layout/theme.module.css
@@ -1,24 +1,16 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/media.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/app_bar/config.css';
-@import 'http://github.com/drawer/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/media.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/app_bar/config.module.css';
+@import 'http://github.com/drawer/config.module.css';
:root {
--layout-side-transition: all var(--animation-duration) var(--animation-curve-default);
}
-.layout {
- align-items: stretch;
- display: flex;
- flex: 1;
- flex-direction: column;
- justify-content: space-between;
- min-height: 100vh;
- min-width: 100%;
- position: relative;
-
- @apply --reset;
+.panel,
+.appbarInner {
+ transition: var(--layout-side-transition);
}
.panel {
@@ -34,6 +26,19 @@
}
}
+.layout {
+ align-items: stretch;
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ justify-content: space-between;
+ min-height: 100vh;
+ min-width: 100%;
+ position: relative;
+
+ @apply --reset;
+}
+
.sidebarDrawer,
.navDrawerDrawer {
z-index: var(--z-index-high);
@@ -59,35 +64,6 @@
}
}
-.appbarInner,
-.panel {
- transition: var(--layout-side-transition);
-}
-
-.appbarFixed {
- &.appbarAppBar {
- z-index: var(--z-index-high);
- }
-
- & .panel {
- top: var(--appbar-height);
-
- &:not(.bodyScroll) {
- height: calc(100vh - var(--appbar-height));
- max-height: calc(100vh - var(--appbar-height));
- overflow-y: scroll;
- }
-
- @media screen and (--xxs-viewport) and (--portrait) {
- top: var(--appbar-height-m-portrait);
- }
-
- @media screen and (--xs-viewport) and (--landscape) {
- top: var(--appbar-height-m-landscape);
- }
- }
-}
-
.navDrawerPinned {
& .appbarLeftIcon {
display: none;
@@ -116,13 +92,6 @@
}
}
-.navDrawerClipped {
- & .navDrawerWrapper {
- position: relative;
- z-index: var(--z-index-normal);
- }
-}
-
.sidebarPinned {
& .appbarLeftIcon {
display: none;
@@ -151,6 +120,41 @@
}
}
+.appbarFixed {
+ &.appbarAppBar {
+ z-index: var(--z-index-high);
+ }
+
+ & .panel {
+ height: calc(100vh - var(--appbar-height));
+ max-height: calc(100vh - var(--appbar-height));
+ top: var(--appbar-height);
+
+ &:not(.bodyScroll) {
+ overflow-y: scroll;
+ }
+
+ @media screen and (--xxs-viewport) and (--portrait) {
+ height: calc(100vh - var(--appbar-height-m-portrait));
+ max-height: calc(100vh - var(--appbar-height-m-portrait));
+ top: var(--appbar-height-m-portrait);
+ }
+
+ @media screen and (--xs-viewport) and (--landscape) {
+ height: calc(100vh - var(--appbar-height-m-landscape));
+ max-height: calc(100vh - var(--appbar-height-m-landscape));
+ top: var(--appbar-height-m-landscape);
+ }
+ }
+}
+
+.navDrawerClipped {
+ & .navDrawerWrapper {
+ position: relative;
+ z-index: var(--z-index-normal);
+ }
+}
+
.sidebarClipped {
& .sidebarWrapper {
position: relative;
diff --git a/components/link/Link.js b/components/link/Link.js
index 7097759b9..3ca251621 100644
--- a/components/link/Link.js
+++ b/components/link/Link.js
@@ -5,7 +5,9 @@ import { themr } from 'react-css-themr';
import { LINK } from '../identifiers';
import { FontIcon } from '../font_icon/FontIcon';
-const Link = ({ active, children, className, count, icon, label, theme, ...others }) => {
+const Link = ({
+ active, children, className, count, icon, label, theme, ...others
+}) => {
const _className = classnames(theme.link, {
[theme.active]: active,
}, className);
diff --git a/components/link/index.js b/components/link/index.js
index 73c91ba15..df8a571e1 100644
--- a/components/link/index.js
+++ b/components/link/index.js
@@ -1,7 +1,7 @@
import { themr } from 'react-css-themr';
import { LINK } from '../identifiers';
import { Link } from './Link';
-import theme from './theme.css';
+import theme from './theme.module.css';
const ThemedLink = themr(LINK, theme)(Link);
diff --git a/components/link/readme.md b/components/link/readme.md
index 1de725eb1..38861960f 100644
--- a/components/link/readme.md
+++ b/components/link/readme.md
@@ -25,9 +25,9 @@ You can add as many properties as you want to be directly transferred to the out
|:-----|:-----|:-----|:-----|
| `active` | `Boolean` | `false` | If true, adds active style to link.|
| `className` | `String` | `''` | Sets a custom class name to add styles to the link.|
-| `count` | `Number` | | Sets a count number.|
-| `icon` | `String` or `Element` | | An icon key string to include a `FontIcon` component in front of the text.|
-| `label` | `String` | | The text string used for the text content of the link.|
+| `count` | `Number` | | Sets a count number.|
+| `icon` | `String` or `Element` | | An icon key string to include a `FontIcon` component in front of the text.|
+| `label` | `String` | | The text string used for the text content of the link.|
## Theme
diff --git a/components/link/theme.css b/components/link/theme.module.css
similarity index 85%
rename from components/link/theme.css
rename to components/link/theme.module.css
index b7af696fb..ba016e1c8 100644
--- a/components/link/theme.css
+++ b/components/link/theme.module.css
@@ -1,5 +1,5 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
.icon {
font-size: calc(1.8 * var(--unit));
@@ -32,10 +32,6 @@
vertical-align: middle;
}
- & > abbr {
- text-transform: capitalize;
- }
-
& > small {
font-size: var(--font-size-tiny);
margin-left: calc(0.8 * var(--unit));
diff --git a/components/list/List.js b/components/list/List.js
index a9a14f69c..8609fc2a8 100644
--- a/components/list/List.js
+++ b/components/list/List.js
@@ -7,8 +7,8 @@ import InjectListItem from './ListItem';
const mergeProp = (propName, child, parent) => (
child[propName] !== undefined
- ? child[propName]
- : parent[propName]
+ ? child[propName]
+ : parent[propName]
);
const factory = (ListItem) => {
@@ -16,6 +16,8 @@ const factory = (ListItem) => {
static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
+ ripple: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types
+ selectable: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types
theme: PropTypes.shape({
list: PropTypes.string,
}),
@@ -31,7 +33,7 @@ const factory = (ListItem) => {
return React.Children.map(this.props.children, (item) => {
if (item === null || item === undefined) {
return item;
- } else if (item.type === ListItem) {
+ } if (item.type === ListItem) {
const selectable = mergeProp('selectable', item.props, this.props);
const ripple = mergeProp('ripple', item.props, this.props);
return React.cloneElement(item, { selectable, ripple });
diff --git a/components/list/ListItem.d.ts b/components/list/ListItem.d.ts
index eb8cf0669..c1e7739f0 100644
--- a/components/list/ListItem.d.ts
+++ b/components/list/ListItem.d.ts
@@ -3,6 +3,7 @@ import ReactToolbox from '../index';
import { ListItemContentTheme } from './ListItemContent';
import { ListItemActionsTheme } from './ListItemActions';
import { ListItemLayoutProps, ListItemLayoutTheme } from './ListItemLayout';
+import { ListItemTextTheme } from './ListItemText';
export interface ListItemTheme {
/**
@@ -29,7 +30,7 @@ export interface ListItemProps extends ReactToolbox.Props {
* Classnames object defining the component style.
* @default false
*/
- theme?: ListItemTheme & ListItemActionsTheme & ListItemContentTheme & ListItemLayoutTheme;
+ theme?: ListItemTheme & ListItemActionsTheme & ListItemContentTheme & ListItemLayoutTheme & ListItemTextTheme;
/**
* In case you want to provide the item as a link, you can pass this property to specify the href.
*/
diff --git a/components/list/ListItem.js b/components/list/ListItem.js
index f2e836b03..be1a161e3 100644
--- a/components/list/ListItem.js
+++ b/components/list/ListItem.js
@@ -69,9 +69,9 @@ const factory = (ripple, ListItemLayout, ListItemContent) => {
render() {
const {
className,
- ripple: hasRipple, // eslint-disable-line no-unused-vars
- onClick, // eslint-disable-line no-unused-vars
- onMouseDown, // eslint-disable-line no-unused-vars
+ ripple: hasRipple, // eslint-disable-line no-unused-vars
+ onClick, // eslint-disable-line no-unused-vars
+ onMouseDown, // eslint-disable-line no-unused-vars
onTouchStart, // eslint-disable-line no-unused-vars
theme,
to,
diff --git a/components/list/ListItemAction.js b/components/list/ListItemAction.js
index c74bc44c5..ccfa261cc 100644
--- a/components/list/ListItemAction.js
+++ b/components/list/ListItemAction.js
@@ -8,7 +8,11 @@ const ListItemAction = ({ action, theme }) => {
const stopRipple = onClick && !onMouseDown;
const stop = e => e.stopPropagation();
return (
-
+
{action}
);
diff --git a/components/list/ListItemContent.js b/components/list/ListItemContent.js
index 561be3266..e24652c75 100644
--- a/components/list/ListItemContent.js
+++ b/components/list/ListItemContent.js
@@ -15,7 +15,10 @@ const factory = (ListItemText) => {
PropTypes.node,
]),
children: PropTypes.node,
- legend: PropTypes.string,
+ legend: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.node,
+ ]),
theme: PropTypes.shape({
auto: PropTypes.string,
itemContentRoot: PropTypes.string,
@@ -26,7 +29,9 @@ const factory = (ListItemText) => {
};
getType() {
- const { type, children, caption, legend } = this.props;
+ const {
+ type, children, caption, legend,
+ } = this.props;
let count = React.Children.count(children);
[caption, legend].forEach((s) => { count += s ? 1 : 0; });
@@ -36,7 +41,9 @@ const factory = (ListItemText) => {
}
render() {
- const { children, caption, legend, theme } = this.props;
+ const {
+ children, caption, legend, theme,
+ } = this.props;
const contentType = this.getType();
const className = classnames(theme.itemContentRoot, {
[theme[contentType]]: theme[contentType],
diff --git a/components/list/ListItemLayout.js b/components/list/ListItemLayout.js
index 0ee7f1996..932231624 100644
--- a/components/list/ListItemLayout.js
+++ b/components/list/ListItemLayout.js
@@ -43,7 +43,10 @@ const factory = (Avatar, ListItemContent, ListItemActions) => {
PropTypes.string,
PropTypes.element,
]),
- caption: PropTypes.string,
+ caption: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.node,
+ ]),
className: PropTypes.string,
disabled: PropTypes.bool,
itemContent: PropTypes.element,
@@ -52,7 +55,10 @@ const factory = (Avatar, ListItemContent, ListItemActions) => {
PropTypes.string,
PropTypes.element,
]),
- legend: PropTypes.string,
+ legend: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.node,
+ ]),
rightActions: PropTypes.arrayOf(PropTypes.node),
rightIcon: PropTypes.oneOfType([
PropTypes.string,
diff --git a/components/list/ListItemText.js b/components/list/ListItemText.js
index 20bfb6110..f015c1e25 100644
--- a/components/list/ListItemText.js
+++ b/components/list/ListItemText.js
@@ -4,7 +4,9 @@ import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { LIST } from '../identifiers';
-const ListItemText = ({ className, primary, children, theme, ...other }) => {
+const ListItemText = ({
+ className, primary, children, theme, ...other
+}) => {
const _className = classnames(theme.itemText, { [theme.primary]: primary }, className);
return (
diff --git a/components/list/config.css b/components/list/config.module.css
similarity index 100%
rename from components/list/config.css
rename to components/list/config.module.css
diff --git a/components/list/index.js b/components/list/index.js
index f13c94ec3..de147707f 100644
--- a/components/list/index.js
+++ b/components/list/index.js
@@ -13,7 +13,7 @@ import { listItemActionsFactory } from './ListItemActions';
import { listItemContentFactory } from './ListItemContent';
import { listItemLayoutFactory } from './ListItemLayout';
import themedRippleFactory from '../ripple';
-import theme from './theme.css';
+import theme from './theme.module.css';
const applyTheme = Component => themr(LIST, theme)(Component);
const ripple = themedRippleFactory({ centered: false, listItemIgnore: true });
diff --git a/components/list/readme.md b/components/list/readme.md
index afcc16e6e..34954cddd 100644
--- a/components/list/readme.md
+++ b/components/list/readme.md
@@ -63,20 +63,20 @@ Represents a list item that can have avatar, icons, title, subtitle, etc. Note:
### Properties
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
-| `avatar` | `String` or `Element` | | A string URL to specify an avatar in the left side of the item.|
-| `caption` | `String` | | Main text of the item.|
+| `avatar` | `String` or `Element` | | A string URL to specify an avatar in the left side of the item.|
+| `caption` | `String` or `Element` | | Main text of the item.|
| `className` | `String` | `''` | Set a class to give custom styles to the list item.|
| `disabled` | `String` | `false` | If true, the item is displayed as disabled and is not clickable.|
-| `itemContent` | `Element` | | An element that will be displayed as the item. If set, this will override `caption` and `legend`.|
-| `leftActions` | `Array of Elements` | | A list of elements that are placed on the left side of the item and after the avatar attribute.|
-| `leftIcon` | `String` or `Element` | | A string key of a font icon or element to display an icon in the left side of the item. |
-| `legend` | `String` | | Secondary text to display under the caption.|
-| `onClick` | `Function` | | Callback the is invoked when the item is clicked if it's not disabled. |
-| `rightIcon` | `String` or `Element` | | The same as the `leftIcon` but in this case the icon is displayed in the right side.|
-| `rightActions` | `Array of Elements` | | A list of elements that are placed on the right side of the item and after the rightIcon attribute.|
+| `itemContent` | `Element` | | An element that will be displayed as the item. If set, this will override `caption` and `legend`.|
+| `leftActions` | `Array of Elements` | | A list of elements that are placed on the left side of the item and after the avatar attribute.|
+| `leftIcon` | `String` or `Element` | | A string key of a font icon or element to display an icon in the left side of the item. |
+| `legend` | `String` or `Element` | | Secondary text to display under the caption.|
+| `onClick` | `Function` | | Callback that is invoked when the item is clicked if it's not disabled. |
+| `rightIcon` | `String` or `Element` | | The same as the `leftIcon` but in this case the icon is displayed in the right side.|
+| `rightActions` | `Array of Elements` | | A list of elements that are placed on the right side of the item and after the rightIcon attribute.|
| `ripple` | `Boolean` | `false` | If true, the item displays a ripple effect on click. By default it's inherited from the parent element.|
| `selectable` | `Boolean` | `false` | If true, the elements in the list will display a hover effect and a pointer cursor. Inherited from the parent.|
-| `to` | `String` | | In case you want to provide the item as a link, you can pass this property to specify the href. |
+| `to` | `String` | | In case you want to provide the item as a link, you can pass this property to specify the href. |
### Theme
| Name | Description|
@@ -101,15 +101,15 @@ A special type of item that has a checkbox control on the left side. It implemen
### Properties
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
-| `caption` | `String` | | Main text of the item. Required.|
-| `className` | `String` | | Set a class to give custom styles to Component.|
+| `caption` | `String` | | Main text of the item. Required.|
+| `className` | `String` | | Set a class to give custom styles to Component.|
| `checked` | `Boolean` | `false` | If true the checkbox appears checked by default.|
| `disabled` | `String` | `false` | If true, the item is displayed as disabled and it's not clickable.|
-| `legend` | `String` | | Secondary text to display under the caption.|
-| `name` | `String` | | Name for the checkbox input item.|
-| `onBlur` | `Function` | | Callback called when the input element is blurred.|
-| `onChange` | `Function` | | Callback called when the input element is changed.|
-| `onFocus` | `Function` | | Callback called when the input element is focused.|
+| `legend` | `String` | | Secondary text to display under the caption.|
+| `name` | `String` | | Name for the checkbox input item.|
+| `onBlur` | `Function` | | Callback called when the input element is blurred.|
+| `onChange` | `Function` | | Callback called when the input element is changed.|
+| `onFocus` | `Function` | | Callback called when the input element is focused.|
### Theme
| Name | Description|
@@ -131,7 +131,7 @@ Simple subcomponent used to give a title to a list area.
### Properties
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
-| `caption` | `String` | | Text that will be displayed.|
+| `caption` | `String` | | Text that will be displayed.|
| `className` | `String` | `''` | Set a class to give custom styles to the list subheader.|
### Theme
diff --git a/components/list/theme.css b/components/list/theme.module.css
similarity index 92%
rename from components/list/theme.css
rename to components/list/theme.module.css
index 281181847..b8fc2af8b 100644
--- a/components/list/theme.css
+++ b/components/list/theme.module.css
@@ -1,6 +1,18 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
+
+.divider {
+ background-color: var(--color-divider);
+ border: 0;
+ height: var(--list-divider-height);
+ margin: calc(-1 * var(--list-divider-height)) 0 0;
+
+ &.inset {
+ margin-left: var(--list-content-left-spacing);
+ margin-right: var(--list-horizontal-padding);
+ }
+}
.list {
display: inline-block;
@@ -28,18 +40,6 @@
padding-left: var(--list-horizontal-padding);
}
-.divider {
- background-color: var(--color-divider);
- border: 0;
- height: var(--list-divider-height);
- margin: calc(-1 * var(--list-divider-height)) 0 0;
-
- &.inset {
- margin-left: var(--list-content-left-spacing);
- margin-right: var(--list-horizontal-padding);
- }
-}
-
.listItem {
position: relative;
@@ -57,6 +57,24 @@
}
}
+.checkbox {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ height: 100%;
+ margin: 0;
+ min-height: var(--list-item-min-height);
+ width: 100%;
+
+ & > [data-react-toolbox='check'] {
+ margin-right: var(--list-item-right-checkbox-margin);
+ }
+
+ & > [data-react-toolbox='label'] {
+ padding-left: 0;
+ }
+}
+
.item {
align-items: center;
color: var(--color-text);
@@ -64,6 +82,9 @@
min-height: var(--list-item-min-height);
padding: 0 var(--list-horizontal-padding);
position: relative;
+ transition-duration: 0.28s;
+ transition-property: background-color;
+ transition-timing-function: var(--animation-curve-default);
&.selectable:not(.disabled):hover {
background-color: var(--list-item-hover-color);
@@ -83,6 +104,20 @@
}
}
+.itemAction {
+ display: flex;
+ margin: var(--list-item-child-margin) var(--list-horizontal-padding) var(--list-item-child-margin) 0;
+
+ & > :not(button) {
+ padding: 0;
+ }
+
+ & > [data-react-toolbox='font-icon'] {
+ color: var(--color-text-secondary);
+ font-size: var(--list-item-icon-font-size);
+ }
+}
+
.left {
& [data-react-toolbox='font-icon'] {
width: var(--list-item-icon-size);
@@ -112,20 +147,6 @@
flex: 0 0 auto;
}
-.itemAction {
- display: flex;
- margin: var(--list-item-child-margin) var(--list-horizontal-padding) var(--list-item-child-margin) 0;
-
- & > * {
- padding: 0;
- }
-
- & > [data-react-toolbox='font-icon'] {
- color: var(--color-text-secondary);
- font-size: var(--list-item-icon-font-size);
- }
-}
-
.itemContentRoot {
display: block;
flex-grow: 1;
@@ -138,24 +159,6 @@
}
}
-.checkbox {
- align-items: center;
- cursor: pointer;
- display: flex;
- height: 100%;
- margin: 0;
- min-height: var(--list-item-min-height);
- width: 100%;
-
- & > [data-react-toolbox='check'] {
- margin-right: var(--list-item-right-checkbox-margin);
- }
-
- & > [data-react-toolbox='label'] {
- padding-left: 0;
- }
-}
-
.itemText {
display: block;
diff --git a/components/media.css b/components/media.module.css
similarity index 100%
rename from components/media.css
rename to components/media.module.css
diff --git a/components/menu/IconMenu.d.ts b/components/menu/IconMenu.d.ts
index 6fbab80fe..f7140965d 100644
--- a/components/menu/IconMenu.d.ts
+++ b/components/menu/IconMenu.d.ts
@@ -13,6 +13,11 @@ export interface IconMenuTheme {
}
export interface IconMenuProps extends ReactToolbox.Props {
+ /**
+ * If true, the inner Menu component will be active.
+ * @default false
+ */
+ active?: boolean;
/**
* Children to pass through the component.
*/
@@ -27,6 +32,11 @@ export interface IconMenuProps extends ReactToolbox.Props {
* @default true
*/
iconRipple?: boolean;
+ /**
+ * If true, the neutral colors are inverted. Useful if the icon is over a dark background.
+ * @default false
+ */
+ inverse?: boolean;
/**
* Transferred to the Menu component.
* @default true
diff --git a/components/menu/IconMenu.js b/components/menu/IconMenu.js
index 3fd7341ce..865b7457c 100644
--- a/components/menu/IconMenu.js
+++ b/components/menu/IconMenu.js
@@ -9,6 +9,7 @@ import InjectMenu from './Menu';
const factory = (IconButton, Menu) => {
class IconMenu extends Component {
static propTypes = {
+ active: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
icon: PropTypes.oneOfType([
@@ -16,6 +17,7 @@ const factory = (IconButton, Menu) => {
PropTypes.element,
]),
iconRipple: PropTypes.bool,
+ inverse: PropTypes.bool,
menuRipple: PropTypes.bool,
onClick: PropTypes.func,
onHide: PropTypes.func,
@@ -31,6 +33,7 @@ const factory = (IconButton, Menu) => {
};
static defaultProps = {
+ active: false,
className: '',
icon: 'more_vert',
iconRipple: true,
@@ -40,11 +43,17 @@ const factory = (IconButton, Menu) => {
};
state = {
- active: false,
+ active: this.props.active,
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (this.state.active !== nextProps.active) {
+ this.setState({ active: nextProps.active });
+ }
}
handleButtonClick = (event) => {
- this.setState({ active: !this.state.active });
+ this.setState(state => ({ active: !state.active }));
if (this.props.onClick) this.props.onClick(event);
};
@@ -55,7 +64,7 @@ const factory = (IconButton, Menu) => {
render() {
const {
- children, className, icon, iconRipple, inverse, menuRipple, onHide, // eslint-disable-line
+ active, children, className, icon, iconRipple, inverse, menuRipple, onHide, // eslint-disable-line
onSelect, onShow, position, selectable, selected, theme, ...other
} = this.props;
return (
diff --git a/components/menu/Menu.js b/components/menu/Menu.js
index 77333ac3b..c3cdaa5f6 100644
--- a/components/menu/Menu.js
+++ b/components/menu/Menu.js
@@ -142,13 +142,21 @@ const factory = (MenuItem) => {
if (position !== POSITION.STATIC) {
if (this.state.active) {
return { clip: `rect(0 ${width}px ${height}px 0)` };
- } else if (position === POSITION.TOP_RIGHT) {
+ }
+
+ if (position === POSITION.TOP_RIGHT) {
return { clip: `rect(0 ${width}px 0 ${width}px)` };
- } else if (position === POSITION.BOTTOM_RIGHT) {
+ }
+
+ if (position === POSITION.BOTTOM_RIGHT) {
return { clip: `rect(${height}px ${width}px ${height}px ${width}px)` };
- } else if (position === POSITION.BOTTOM_LEFT) {
+ }
+
+ if (position === POSITION.BOTTOM_LEFT) {
return { clip: `rect(${height}px 0 ${height}px 0)` };
- } else if (position === POSITION.TOP_LEFT) {
+ }
+
+ if (position === POSITION.TOP_LEFT) {
return { clip: 'rect(0 0 0 0)' };
}
}
@@ -162,16 +170,6 @@ const factory = (MenuItem) => {
: undefined;
}
- calculatePosition() {
- const parentNode = ReactDOM.findDOMNode(this).parentNode;
- if (!parentNode) return undefined;
- const { top, left, height, width } = parentNode.getBoundingClientRect();
- const { height: wh, width: ww } = getViewport();
- const toTop = top < ((wh / 2) - (height / 2));
- const toLeft = left < ((ww / 2) - (width / 2));
- return `${toTop ? 'top' : 'bottom'}${toLeft ? 'Left' : 'Right'}`;
- }
-
handleDocumentClick = (event) => {
if (this.state.active && !events.targetIsDescendant(event, ReactDOM.findDOMNode(this))) {
this.setState({ active: false, rippled: false });
@@ -187,6 +185,18 @@ const factory = (MenuItem) => {
});
};
+ calculatePosition() {
+ const { parentNode } = ReactDOM.findDOMNode(this);
+ if (!parentNode) return undefined;
+ const {
+ top, left, height, width,
+ } = parentNode.getBoundingClientRect();
+ const { height: wh, width: ww } = getViewport();
+ const toTop = top < ((wh / 2) - (height / 2));
+ const toLeft = left < ((ww / 2) - (width / 2));
+ return `${toTop ? 'top' : 'bottom'}${toLeft ? 'Left' : 'Right'}`;
+ }
+
show() {
const { width, height } = this.menuNode.getBoundingClientRect();
this.setState({ active: true, width, height });
diff --git a/components/menu/MenuItem.d.ts b/components/menu/MenuItem.d.ts
index 265f05766..325e85057 100644
--- a/components/menu/MenuItem.d.ts
+++ b/components/menu/MenuItem.d.ts
@@ -59,6 +59,10 @@ export interface MenuItemProps extends ReactToolbox.Props {
* Classnames object defining the component style.
*/
theme?: MenuItemTheme;
+ /**
+ * Passed down to the root element
+ */
+ value?: any;
}
export class MenuItem extends React.Component { }
diff --git a/components/menu/__test__/index.spec.js b/components/menu/__test__/index.spec.js
index be98b9437..59624fcf7 100644
--- a/components/menu/__test__/index.spec.js
+++ b/components/menu/__test__/index.spec.js
@@ -1,8 +1,60 @@
import React from 'react';
-import { shallow } from 'enzyme';
+import { mount, shallow } from 'enzyme';
+import { IconMenu } from '../IconMenu';
import { Menu } from '../Menu';
import { MenuItem } from '../MenuItem';
+describe('IconMenu', () => {
+ describe('#on mount', () => {
+ describe('when \'active\' prop is not set', () => {
+ it('sets \'active\' Menu prop correctly', () => {
+ const wrapper = shallow();
+ expect(wrapper.find('Menu').props().active).toBe(false);
+ });
+ });
+
+ describe('when \'active\' prop is set to false', () => {
+ it('sets \'active\' Menu prop correctly', () => {
+ const wrapper = shallow();
+ expect(wrapper.find('Menu').props().active).toBe(false);
+ });
+
+ it('sets \'active\' Menu prop correctly after IconButton click', () => {
+ const wrapper = mount();
+ wrapper.find('IconButton').simulate('click');
+ expect(wrapper.find('Menu').props().active).toBe(true);
+ });
+
+ it('sets \'active\' Menu prop correctly when prop is set after IconButton click', () => {
+ const wrapper = mount();
+ wrapper.find('IconButton').simulate('click');
+ wrapper.setProps({ active: false });
+ expect(wrapper.find('Menu').props().active).toBe(false);
+ });
+ });
+
+ describe('when \'active\' prop is set to true', () => {
+ it('sets \'active\' Menu prop correctly', () => {
+ const wrapper = shallow();
+ expect(wrapper.find('Menu').props().active).toBe(true);
+ });
+
+ it('sets \'active\' Menu prop correctly after IconButton click', () => {
+ const wrapper = mount();
+ wrapper.find('IconButton').simulate('click');
+ expect(wrapper.find('Menu').props().active).toBe(false);
+ });
+
+ it('sets \'active\' Menu prop correctly when prop is set after IconButton click', () => {
+ const wrapper = mount();
+ wrapper.find('IconButton').simulate('click');
+ wrapper.setProps({ active: true });
+ expect(wrapper.find('Menu').props().active).toBe(true);
+ });
+ });
+ });
+});
+
describe('MenuItem', () => {
describe('#onClick', () => {
it('passes to listener the event', () => {
diff --git a/components/menu/config.css b/components/menu/config.module.css
similarity index 100%
rename from components/menu/config.css
rename to components/menu/config.module.css
diff --git a/components/menu/index.js b/components/menu/index.js
index a62675ab7..13b37347c 100644
--- a/components/menu/index.js
+++ b/components/menu/index.js
@@ -6,7 +6,7 @@ import { menuItemFactory } from './MenuItem';
import { menuFactory } from './Menu';
import { iconMenuFactory } from './IconMenu';
import themedRippleFactory from '../ripple';
-import theme from './theme.css';
+import theme from './theme.module.css';
const applyTheme = Component => themr(MENU, theme)(Component);
const ThemedMenuDivider = applyTheme(MenuDivider);
diff --git a/components/menu/readme.md b/components/menu/readme.md
index 8bf58b993..69561f2a6 100644
--- a/components/menu/readme.md
+++ b/components/menu/readme.md
@@ -29,14 +29,14 @@ This subcomponent is the default wrapper for a menu and is responsible for the o
|:-----|:-----|:-----|:-----|
| `active` | `Boolean` | `false` | If true, the menu will be displayed as opened by default.|
| `className` | `String` | `''` | Set a class to give custom styles to the menu wrapper.|
-| `onHide` | `Function` | | Callback that will be called when the menu is being hidden. |
-| `onSelect` | `Function` | | Callback that will be invoked when a menu item is selected. |
-| `onShow` | `Function` | | Callback that will be invoked when the menu is being shown. |
+| `onHide` | `Function` | | Callback that will be called when the menu is being hidden. |
+| `onSelect` | `Function` | | Callback that will be invoked when a menu item is selected. |
+| `onShow` | `Function` | | Callback that will be invoked when the menu is being shown. |
| `outline` | `Boolean` | `true` | If true the menu wrapper will show an outline with a soft shadow. |
| `position` | `String` | `static` | Determine the position of the menu. With `static` value the menu will be always shown, `auto` means that the it will decide the opening direction based on the current position. To force a position use `topLeft`, `topRight`, `bottomLeft`, `bottomRight`. |
| `ripple` | `Boolean` | `true` | If true, the menu items will show a ripple effect on click. |
| `selectable` | `Boolean` | `false` | If true, the menu will keep a value to highlight the active child item. |
-| `selected` | `Any` | | Used for selectable menus. Indicates the current selected value so the child item with this value can be highlighted. |
+| `selected` | `Any` | | Used for selectable menus. Indicates the current selected value so the child item with this value can be highlighted. |
### Theming
@@ -61,18 +61,19 @@ As the most usual scenario will be to open the menu from a click in an Icon, we
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
+| `active` | `Boolean` | `false` | If true, the inner `Menu` component will be active. |
| `className` | `String` | `''` | Set a class to give custom styles to the icon wrapper.|
| `icon` | `String` or `Element` | `more_vert` | Icon font key string or Element to display the opener icon. |
| `iconRipple` | `Boolean` | `true` | If true, the icon will show a ripple when is clicked. |
| `inverse` | `Boolean` | `false` | If true, the neutral colors are inverted. Useful if the icon is over a dark background. |
| `menuRipple` | `Boolean` | `true` | Transferred to the `Menu` component. |
-| `onClick` | `Function` | | Callback that will be called when the icon is clicked. |
-| `onHide` | `Function` | | Callback that will be called when the menu is being hidden. |
-| `onSelect` | `Function` | | Callback that will be invoked when a menu item is selected. |
-| `onShow` | `Function` | | Callback that will be invoked when the menu is being shown. |
+| `onClick` | `Function` | | Callback that will be called when the icon is clicked. |
+| `onHide` | `Function` | | Callback that will be called when the menu is being hidden. |
+| `onSelect` | `Function` | | Callback that will be invoked when a menu item is selected. |
+| `onShow` | `Function` | | Callback that will be invoked when the menu is being shown. |
| `position` | `String` | `auto` | Determines the position of the menu. This property is transferred to the inner `Menu` component. |
| `selectable` | `Boolean` | `false` | If true, the menu will keep a value to highlight the active child item. |
-| `selected` | `Any` | | Used for selectable menus. Indicates the current selected value so the child item with this value can be highlighted. |
+| `selected` | `Any` | | Used for selectable menus. Indicates the current selected value so the child item with this value can be highlighted. |
### Theming
@@ -89,11 +90,11 @@ The inner component for menus and describes the content of each option. It behav
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
-| `caption` | `String` | | The text to include in the menu item. Required.|
+| `caption` | `String` | | The text to include in the menu item. Required.|
| `className` | `String` | `''` | Set a class to give custom styles to the item.|
| `disabled` | `Boolean` | `false` | If true, the item will be displayed as disabled and is not selectable.|
-| `icon` | `String` or `Element` | | Icon font key string or Element to display in the right side of the option. |
-| `onClick` | `Function` | | Callback that will be called when Component is clicked. |
+| `icon` | `String` or `Element` | | Icon font key string or Element to display in the right side of the option. |
+| `onClick` | `Function` | | Callback that will be called when Component is clicked. |
| `selected` | `Boolean` | `false` | Transferred from the `Menu` component for selectable menus. Indicates if it's the current active option. |
| `shortcut` | `String` | `''` | Displays shortcut text on the right side of the `caption` attribute. |
diff --git a/components/menu/theme.css b/components/menu/theme.module.css
similarity index 96%
rename from components/menu/theme.css
rename to components/menu/theme.module.css
index 13e1e7276..57e410a89 100644
--- a/components/menu/theme.css
+++ b/components/menu/theme.module.css
@@ -1,6 +1,6 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.iconMenu {
display: inline-block;
@@ -14,6 +14,25 @@
}
}
+.outline {
+ background-color: var(--menu-background-color);
+ border-radius: var(--menu-outline-border-radius);
+ box-shadow: var(--shadow-2p);
+ display: block;
+ left: 0;
+ position: absolute;
+ top: 0;
+}
+
+.menuInner {
+ display: block;
+ list-style: none;
+ padding: var(--menu-padding);
+ position: relative;
+ text-align: left;
+ white-space: nowrap;
+}
+
.menu {
display: inline-block;
position: relative;
@@ -79,16 +98,6 @@
top: 0;
}
- &.rippled:not(.active) {
- & > .outline {
- transition-delay: var(--menu-ripple-delay);
- }
-
- & > .menuInner {
- transition-delay: var(--menu-ripple-delay);
- }
- }
-
&.active {
pointer-events: all;
@@ -104,26 +113,17 @@
clip var(--menu-expand-duration) var(--animation-curve-default);
}
}
- }
-}
-.outline {
- background-color: var(--menu-background-color);
- border-radius: var(--menu-outline-border-radius);
- box-shadow: var(--shadow-2p);
- display: block;
- left: 0;
- position: absolute;
- top: 0;
-}
+ &.rippled:not(.active) {
+ & > .outline {
+ transition-delay: var(--menu-ripple-delay);
+ }
-.menuInner {
- display: block;
- list-style: none;
- padding: var(--menu-padding);
- position: relative;
- text-align: left;
- white-space: nowrap;
+ & > .menuInner {
+ transition-delay: var(--menu-ripple-delay);
+ }
+ }
+ }
}
.menuItem {
diff --git a/components/navigation/Navigation.js b/components/navigation/Navigation.js
index 8a364c98f..d752b997c 100644
--- a/components/navigation/Navigation.js
+++ b/components/navigation/Navigation.js
@@ -7,7 +7,9 @@ import InjectButton from '../button/Button';
import InjectLink from '../link/Link';
const factory = (Button, Link) => {
- const Navigation = ({ actions, children, className, routes, theme, type }) => {
+ const Navigation = ({
+ actions, children, className, routes, theme, type,
+ }) => {
const _className = classnames(theme[type], className);
const buttons = actions.map((action, index) => (
// eslint-disable-line
diff --git a/components/navigation/config.css b/components/navigation/config.module.css
similarity index 100%
rename from components/navigation/config.css
rename to components/navigation/config.module.css
diff --git a/components/navigation/index.js b/components/navigation/index.js
index 5b98443b0..2de55561a 100644
--- a/components/navigation/index.js
+++ b/components/navigation/index.js
@@ -3,7 +3,7 @@ import { NAVIGATION } from '../identifiers';
import { navigationFactory } from './Navigation';
import { Button } from '../button';
import { Link } from '../link';
-import theme from './theme.css';
+import theme from './theme.module.css';
const ThemedNavigation = themr(NAVIGATION, theme)(navigationFactory(Button, Link));
export default ThemedNavigation;
diff --git a/components/navigation/readme.md b/components/navigation/readme.md
index 3d143e704..7d03d6e14 100644
--- a/components/navigation/readme.md
+++ b/components/navigation/readme.md
@@ -29,9 +29,9 @@ The theming for this component can be provided using the key `RTNavigation`.
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
-| `actions` | `Array` | | Array of objects that will be represented as `` so the keys will be transferred as properties the Button Component.|
-| `className` | `String` | | Set a custom class styles to style the navigation.|
-| `routes` | `Array` | | Array of objects similar to actions but that will be rendered as `` component definition. |
+| `actions` | `Array` | | Array of objects that will be represented as `` so the keys will be transferred as properties the Button Component.|
+| `className` | `String` | | Set a custom class styles to style the navigation.|
+| `routes` | `Array` | | Array of objects similar to actions but that will be rendered as `` component definition. |
| `type` | `String` | `horizontal` | Type of the navigation, it can be `vertical` or `horizontal`.|
## Theming
diff --git a/components/navigation/theme.css b/components/navigation/theme.module.css
similarity index 83%
rename from components/navigation/theme.css
rename to components/navigation/theme.module.css
index e0c4a3cc3..452065bba 100644
--- a/components/navigation/theme.css
+++ b/components/navigation/theme.module.css
@@ -1,6 +1,6 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.horizontal {
& > [data-react-toolbox='button'],
diff --git a/components/overlay/config.css b/components/overlay/config.module.css
similarity index 100%
rename from components/overlay/config.css
rename to components/overlay/config.module.css
diff --git a/components/overlay/index.js b/components/overlay/index.js
index d210af170..d4085a739 100644
--- a/components/overlay/index.js
+++ b/components/overlay/index.js
@@ -1,7 +1,7 @@
import { themr } from 'react-css-themr';
import { OVERLAY } from '../identifiers';
import { Overlay } from './Overlay';
-import theme from './theme.css';
+import theme from './theme.module.css';
const ThemedOverlay = themr(OVERLAY, theme)(Overlay);
export default ThemedOverlay;
diff --git a/components/overlay/theme.css b/components/overlay/theme.module.css
similarity index 77%
rename from components/overlay/theme.css
rename to components/overlay/theme.module.css
index e8b1328f5..5d4a0647c 100644
--- a/components/overlay/theme.css
+++ b/components/overlay/theme.module.css
@@ -1,6 +1,6 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.overlay {
background-color: var(--overlay-color);
diff --git a/components/progress_bar/ProgressBar.js b/components/progress_bar/ProgressBar.js
index b8957fc6f..a619189c7 100644
--- a/components/progress_bar/ProgressBar.js
+++ b/components/progress_bar/ProgressBar.js
@@ -80,9 +80,11 @@ class ProgressBar extends Component {
}
render() {
- const { className, disabled, max, min, mode, multicolor, type, theme, value } = this.props;
+ const {
+ className, disabled, max, min, mode, multicolor, type, theme, value,
+ } = this.props;
const _className = classnames(theme[type], {
- [theme[mode]]: mode,
+ [theme.indeterminate]: mode === 'indeterminate',
[theme.multicolor]: multicolor,
}, className);
diff --git a/components/progress_bar/__test__/index.spec.js b/components/progress_bar/__test__/index.spec.js
index 36be9b7ea..f3d7e29ca 100644
--- a/components/progress_bar/__test__/index.spec.js
+++ b/components/progress_bar/__test__/index.spec.js
@@ -1,7 +1,7 @@
import React from 'react';
import { mount, shallow } from 'enzyme';
import { ProgressBar } from '../ProgressBar';
-import theme from '../theme.css';
+import theme from '../theme.module.css';
describe('ProgressBar', () => {
describe('#calculateRatio', () => {
@@ -27,25 +27,25 @@ describe('ProgressBar', () => {
describe('#render', () => {
it('renders the value and buffer bars when it is linear', () => {
const wrapper = mount();
- expect(wrapper.childAt(0).props().children.length).toEqual(2);
+ expect(wrapper.childAt(0).childAt(0).props().children.length).toEqual(2);
});
it('renders the value and buffer bars when it is linear', () => {
const wrapper = mount();
- const buffer = wrapper.childAt(0).childAt(0);
- const value = wrapper.childAt(0).childAt(1);
+ const buffer = wrapper.childAt(0).childAt(0).childAt(0);
+ const value = wrapper.childAt(0).childAt(0).childAt(1);
expect(buffer.props().style.transform).toEqual(`scaleX(${0.6})`);
expect(value.props().style.transform).toEqual(`scaleX(${0.3})`);
});
it('renders the svg circle when it is circular', () => {
const wrapper = mount();
- expect(wrapper.childAt(0).props().children.type).toEqual('circle');
+ expect(wrapper.childAt(0).childAt(0).props().children.type).toEqual('circle');
});
it('renders the proper circle length style when it is circular and determinate', () => {
const wrapper = mount();
- const circle = wrapper.childAt(0).props().children;
+ const circle = wrapper.childAt(0).childAt(0).props().children;
const strokeLength = 2 * Math.PI * circle.props.r * 0.3;
expect(circle.props.style.strokeDasharray).toEqual(`${strokeLength}, 400`);
});
diff --git a/components/progress_bar/config.css b/components/progress_bar/config.module.css
similarity index 58%
rename from components/progress_bar/config.css
rename to components/progress_bar/config.module.css
index c9ecfd78e..568d7c22d 100644
--- a/components/progress_bar/config.css
+++ b/components/progress_bar/config.module.css
@@ -1,8 +1,8 @@
:root {
--progress-height: calc(0.4 * var(--unit));
--progress-main-color: var(--color-primary);
- --progress-secondary-color: color(var(--color-primary-contrast) a(70%));
- --progress-disabled-color: color(var(--color-black) a(26%));
+ --progress-secondary-color: color-mod(var(--color-primary-contrast) a(70%));
+ --progress-disabled-color: color-mod(var(--color-black) a(26%));
--circle-wrapper-width: 60;
--circle-radius: 25;
--scale-ratio: calc(var(--circle-radius) / 20);
diff --git a/components/progress_bar/index.js b/components/progress_bar/index.js
index a6b5a9fa3..92eb89651 100644
--- a/components/progress_bar/index.js
+++ b/components/progress_bar/index.js
@@ -1,7 +1,7 @@
import { themr } from 'react-css-themr';
import { PROGRESS_BAR } from '../identifiers';
import { ProgressBar } from './ProgressBar';
-import theme from './theme.css';
+import theme from './theme.module.css';
const ThemedProgressBar = themr(PROGRESS_BAR, theme)(ProgressBar);
diff --git a/components/progress_bar/theme.css b/components/progress_bar/theme.module.css
similarity index 91%
rename from components/progress_bar/theme.css
rename to components/progress_bar/theme.module.css
index 305897cad..41a6c83ef 100644
--- a/components/progress_bar/theme.css
+++ b/components/progress_bar/theme.module.css
@@ -1,19 +1,9 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
-.linear {
- background: var(--color-divider);
- display: inline-block;
- height: var(--progress-height);
- overflow: hidden;
- position: relative;
- width: 100%;
-
- &.indeterminate .value {
- animation: linear-indeterminate-bar 1s linear infinite;
- transform-origin: center center;
- }
+.value {
+ background-color: var(--progress-main-color);
}
.value,
@@ -29,8 +19,18 @@
transition-timing-function: var(--animation-curve-default);
}
-.value {
- background-color: var(--progress-main-color);
+.linear {
+ background: var(--color-divider);
+ display: inline-block;
+ height: var(--progress-height);
+ overflow: hidden;
+ position: relative;
+ width: 100%;
+
+ &.indeterminate .value {
+ animation: linear-indeterminate-bar 1s linear infinite;
+ transform-origin: center center;
+ }
}
.buffer {
@@ -39,6 +39,22 @@
linear-gradient(to right, var(--progress-main-color), var(--progress-main-color));
}
+.circle {
+ height: 100%;
+ width: 100%;
+}
+
+.path {
+ fill: none;
+ stroke: var(--progress-main-color);
+ stroke-dasharray: 0, calc(var(--scale-ratio) * 200);
+ stroke-dashoffset: 0;
+ stroke-linecap: round;
+ stroke-miterlimit: 20;
+ stroke-width: 4;
+ transition: stroke-dasharray var(--animation-duration) var(--animation-curve-default);
+}
+
.circular {
display: inline-block;
height: calc(var(--circle-wrapper-width) * 1px);
@@ -57,10 +73,12 @@
stroke-dashoffset: 0;
}
- &.multicolor .path {
- animation:
- circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
- colors calc(1.5s * 4) ease-in-out infinite;
+ &.multicolor {
+ & .path {
+ animation:
+ circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
+ colors calc(1.5s * 4) ease-in-out infinite;
+ }
}
}
}
@@ -78,22 +96,6 @@
}
}
-.circle {
- height: 100%;
- width: 100%;
-}
-
-.path {
- fill: none;
- stroke: var(--progress-main-color);
- stroke-dasharray: 0, calc(var(--scale-ratio) * 200);
- stroke-dashoffset: 0;
- stroke-linecap: round;
- stroke-miterlimit: 20;
- stroke-width: 4;
- transition: stroke-dasharray var(--animation-duration) var(--animation-curve-default);
-}
-
@keyframes linear-indeterminate-bar {
0% {
transform: translate(-50%) scaleX(0);
diff --git a/components/radio/Radio.js b/components/radio/Radio.js
index 1d18cfd38..11f4f84e6 100644
--- a/components/radio/Radio.js
+++ b/components/radio/Radio.js
@@ -2,7 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
const factory = (ripple) => {
- const Radio = ({ checked, onMouseDown, theme, ...other }) => (
+ const Radio = ({
+ checked, onMouseDown, theme, ...other
+ }) => (
{
disabled: false,
};
- handleChange = (value) => {
- if (this.props.onChange) this.props.onChange(value);
+ handleChange = (value, event) => {
+ if (this.props.onChange) this.props.onChange(value, event);
};
renderRadioButtons() {
diff --git a/components/radio/config.css b/components/radio/config.module.css
similarity index 61%
rename from components/radio/config.css
rename to components/radio/config.module.css
index 5c35d83d9..dbd5c9363 100644
--- a/components/radio/config.css
+++ b/components/radio/config.module.css
@@ -3,9 +3,9 @@
--radio-button-size: calc(2 * var(--unit));
--radio-inner-margin: calc(var(--radio-button-size) / 4);
--radio-inner-color: var(--color-primary);
- --radio-focus-color: color(var(--color-black) a(10%));
- --radio-checked-focus-color: color(var(--color-primary) a(26%));
+ --radio-focus-color: color-mod(var(--color-black) a(10%));
+ --radio-checked-focus-color: color-mod(var(--color-primary) a(26%));
--radio-text-color: var(--color-black);
- --radio-disabled-color: color(var(--color-black) a(26%));
+ --radio-disabled-color: color-mod(var(--color-black) a(26%));
--radio-text-font-size: calc(1.4 * var(--unit));
}
diff --git a/components/radio/index.js b/components/radio/index.js
index 143a29af0..e98bf0673 100644
--- a/components/radio/index.js
+++ b/components/radio/index.js
@@ -4,7 +4,7 @@ import themedRippleFactory from '../ripple';
import radioFactory from './Radio';
import { radioButtonFactory } from './RadioButton';
import { radioGroupFactory } from './RadioGroup';
-import theme from './theme.css';
+import theme from './theme.module.css';
const ThemedRadio = radioFactory(themedRippleFactory({ centered: true, spread: 2.6 }));
const ThemedRadioButton = themr(RADIO, theme)(radioButtonFactory(ThemedRadio));
diff --git a/components/radio/readme.md b/components/radio/readme.md
index 78f8df4f5..c7889ebe1 100644
--- a/components/radio/readme.md
+++ b/components/radio/readme.md
@@ -40,9 +40,9 @@ A radio selector is mean to get a value from a set of choices, that's why a radi
|:-----|:-----|:-----|:-----|
| `className` | `String` | `''` | Set a class to give custom styles to the group.|
| `disabled` | `Boolean` | `false` | If true, the group will be displayed as disabled.|
-| `name` | `String` | | Name for the input element group. |
-| `onChange` | `Function` | | Callback function that will be invoked when the value changes. |
-| `value` | `Any` | | Default value selected in the radio group. |
+| `name` | `String` | | Name for the input element group. |
+| `onChange` | `Function` | | Callback function that will be invoked when the value changes. |
+| `value` | `Any` | | Default value selected in the radio group. |
## Radio Button
@@ -56,12 +56,12 @@ The inner component to compose radio selectors. They will be rendered as radio i
| `checked` | `Boolean` | `false` | If true, the input element will be selected by default. Transferred from the parent. |
| `className` | `String` | `''` | Set a class to give custom styles to the radio button.|
| `disabled` | `Boolean` | `false` | If true, the item will be displayed as disabled.|
-| `label` | `String` of `node` | `''` | Label for the radio button.|
-| `name` | `String` | | Name for the input element. |
-| `onBlur` | `Function` | | Callback function that will be invoked when the input is blurred. |
-| `onChange` | `Function` | | Callback function that will be invoked when the value changes. |
-| `onFocus` | `Function` | | Callback function that will be invoked when the input is focused. |
-| `value` | `Any` | | Value for the radio button. |
+| `label` | `String` or `node` | `''` | Label for the radio button.|
+| `name` | `String` | | Name for the input element. |
+| `onBlur` | `Function` | | Callback function that will be invoked when the input is blurred. |
+| `onChange` | `Function` | | Callback function that will be invoked when the value changes. |
+| `onFocus` | `Function` | | Callback function that will be invoked when the input is focused. |
+| `value` | `Any` | | Value for the radio button. |
### Theming
diff --git a/components/radio/theme.css b/components/radio/theme.module.css
similarity index 95%
rename from components/radio/theme.css
rename to components/radio/theme.module.css
index 17263ce50..528ddcadc 100644
--- a/components/radio/theme.css
+++ b/components/radio/theme.module.css
@@ -1,6 +1,6 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.radio {
border: calc(0.2 * var(--unit)) solid var(--radio-text-color);
@@ -61,25 +61,6 @@
white-space: nowrap;
}
-.input {
- appearance: none;
- border: 0;
- height: 0;
- margin: 0;
- opacity: 0;
- padding: 0;
- position: absolute;
- width: 0;
-
- &:focus ~ .radio {
- box-shadow: 0 0 0 var(--unit) var(--radio-focus-color);
- }
-
- &:focus ~ .radioChecked {
- box-shadow: 0 0 0 var(--unit) var(--radio-checked-focus-color);
- }
-}
-
.disabled {
composes: field;
@@ -101,3 +82,22 @@
}
}
}
+
+.input {
+ appearance: none;
+ border: 0;
+ height: 0;
+ margin: 0;
+ opacity: 0;
+ padding: 0;
+ position: absolute;
+ width: 0;
+
+ &:focus ~ .radio {
+ box-shadow: 0 0 0 var(--unit) var(--radio-focus-color);
+ }
+
+ &:focus ~ .radioChecked {
+ box-shadow: 0 0 0 var(--unit) var(--radio-checked-focus-color);
+ }
+}
diff --git a/components/ripple/Ripple.js b/components/ripple/Ripple.js
index 2709b6501..06c1e2209 100644
--- a/components/ripple/Ripple.js
+++ b/components/ripple/Ripple.js
@@ -62,6 +62,11 @@ const rippleFactory = (options = {}) => {
ripples: {},
};
+ /**
+ * Variable to store the ripple references
+ */
+ rippleNodes = {};
+
componentDidUpdate(prevProps, prevState) {
// If a new ripple was just added, add a remove event listener to its animation
if (Object.keys(prevState.ripples).length < Object.keys(this.state.ripples).length) {
@@ -85,7 +90,9 @@ const rippleFactory = (options = {}) => {
* @return {Object} Descriptor element including position and size of the element
*/
getDescriptor(x, y) {
- const { left, top, height, width } = ReactDOM.findDOMNode(this).getBoundingClientRect();
+ const {
+ left, top, height, width,
+ } = ReactDOM.findDOMNode(this).getBoundingClientRect();
const { rippleCentered: centered, rippleSpread: spread } = this.props;
return {
left: centered ? 0 : x - left - (width / 2),
@@ -115,10 +122,23 @@ const rippleFactory = (options = {}) => {
return `ripple${this.currentCount}`;
}
- /**
- * Variable to store the ripple references
- */
- rippleNodes = {};
+ doRipple = () => (!this.props.disabled && this.props.ripple)
+
+ handleMouseDown = (event) => {
+ if (this.props.onMouseDown) this.props.onMouseDown(event);
+ if (this.doRipple()) {
+ const { x, y } = events.getMousePosition(event);
+ this.animateRipple(x, y, false);
+ }
+ };
+
+ handleTouchStart = (event) => {
+ if (this.props.onTouchStart) this.props.onTouchStart(event);
+ if (this.doRipple()) {
+ const { x, y } = events.getTouchPosition(event);
+ this.animateRipple(x, y, true);
+ }
+ };
/**
* Determine if a ripple should start depending if its a touch event. For mobile both
@@ -153,15 +173,22 @@ const rippleFactory = (options = {}) => {
? this.getNextKey()
: this.getLastKey();
const endRipple = this.addRippleDeactivateEventListener(isTouch, key);
- const initialState = { active: false, restarting: true, top, left, width, endRipple };
+ const initialState = {
+ active: false, restarting: true, top, left, width, endRipple,
+ };
const runningState = { active: true, restarting: false };
- const ripples = { ...this.state.ripples, [key]: initialState };
- this.setState({ ripples }, () => {
+
+ this.setState(state => ({
+ ripples: { ...state.ripples, [key]: initialState },
+ }), () => {
if (this.rippleNodes[key]) this.rippleNodes[key].offsetWidth; // eslint-disable-line
- this.setState({ ripples: {
- ...this.state.ripples,
- [key]: Object.assign({}, this.state.ripples[key], runningState),
- } });
+
+ this.setState(state => ({
+ ripples: {
+ ...state.ripples,
+ [key]: Object.assign({}, state.ripples[key], runningState),
+ },
+ }));
});
}
}
@@ -216,32 +243,18 @@ const rippleFactory = (options = {}) => {
const self = this;
return function endRipple() {
document.removeEventListener(eventType, endRipple);
- self.setState({ ripples: {
- ...self.state.ripples,
- [rippleKey]: Object.assign({}, self.state.ripples[rippleKey], { active: false }),
- } });
+ self.setState({
+ ripples: {
+ ...self.state.ripples,
+ [rippleKey]: Object.assign({}, self.state.ripples[rippleKey], { active: false }),
+ },
+ });
};
}
- doRipple = () => (!this.props.disabled && this.props.ripple)
-
- handleMouseDown = (event) => {
- if (this.props.onMouseDown) this.props.onMouseDown(event);
- if (this.doRipple()) {
- const { x, y } = events.getMousePosition(event);
- this.animateRipple(x, y, false);
- }
- };
-
- handleTouchStart = (event) => {
- if (this.props.onTouchStart) this.props.onTouchStart(event);
- if (this.doRipple()) {
- const { x, y } = events.getTouchPosition(event);
- this.animateRipple(x, y, true);
- }
- };
-
- renderRipple(key, className, { active, left, restarting, top, width }) {
+ renderRipple(key, className, {
+ active, left, restarting, top, width,
+ }) {
const scale = restarting ? 0 : 1;
const transform = `translate3d(${(-width / 2) + left}px, ${(-width / 2) + top}px, 0) scale(${scale})`;
const _className = classnames(this.props.theme.ripple, {
@@ -273,9 +286,7 @@ const rippleFactory = (options = {}) => {
...other
} = this.props;
const { ripples } = this.state;
- const childRipples = Object.keys(ripples).map(key =>
- this.renderRipple(key, rippleClassName, ripples[key]),
- );
+ const childRipples = Object.keys(ripples).map(key => this.renderRipple(key, rippleClassName, ripples[key])); // eslint-disable-line max-len
const childProps = {
onMouseDown: this.handleMouseDown,
onTouchStart: this.handleTouchStart,
diff --git a/components/ripple/config.css b/components/ripple/config.module.css
similarity index 100%
rename from components/ripple/config.css
rename to components/ripple/config.module.css
diff --git a/components/ripple/index.js b/components/ripple/index.js
index 3933c4cfa..4d2f945b1 100644
--- a/components/ripple/index.js
+++ b/components/ripple/index.js
@@ -1,4 +1,4 @@
import rippleFactory from './Ripple';
-import theme from './theme.css';
+import theme from './theme.module.css';
export default options => rippleFactory({ ...options, theme });
diff --git a/components/ripple/readme.md b/components/ripple/readme.md
index 8eb484d0e..68c84261b 100644
--- a/components/ripple/readme.md
+++ b/components/ripple/readme.md
@@ -36,7 +36,7 @@ In any component you decorate with the Ripple you'd get some additional props na
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
-| `onRippleEnded` | `Function` | | Function that will be called when the ripple animation ends. Beware if your animation supports multiple waves this function will be called for each ended ripple. |
+| `onRippleEnded` | `Function` | | Function that will be called when the ripple animation ends. Beware if your animation supports multiple waves this function will be called for each ended ripple. |
| `ripple` | `Boolean` | `true` | False in case you want to deactivate the ripple.|
| `rippleCentered` | `Boolean` | `options.centered` | True in case you want a centered ripple.|
| `rippleClassName` | `String` | `options.className` | String to customize appearance (color and opacity for example).|
diff --git a/components/ripple/theme.css b/components/ripple/theme.module.css
similarity index 91%
rename from components/ripple/theme.css
rename to components/ripple/theme.module.css
index 4b4153c6c..1e0fdcaf9 100644
--- a/components/ripple/theme.css
+++ b/components/ripple/theme.module.css
@@ -1,5 +1,5 @@
-@import 'http://github.com/variables.css';
-@import 'http://github.com/config.css';
+@import 'http://github.com/variables.module.css';
+@import 'http://github.com/config.module.css';
.rippleWrapper {
bottom: 0;
diff --git a/components/slider/Slider.js b/components/slider/Slider.js
index 01edef5c2..bcc5f80b9 100644
--- a/components/slider/Slider.js
+++ b/components/slider/Slider.js
@@ -10,6 +10,13 @@ import events from '../utils/events';
import InjectProgressBar from '../progress_bar/ProgressBar';
import InjectInput from '../input/Input';
+const KEYS = {
+ ENTER: 'Enter',
+ ESC: 'Escape',
+ ARROW_UP: 'ArrowUp',
+ ARROW_DOWN: 'ArrowDown',
+};
+
const factory = (ProgressBar, Input) => {
class Slider extends Component {
static propTypes = {
@@ -97,12 +104,6 @@ const factory = (ProgressBar, Input) => {
events.removeEventsFromDocument(this.getKeyboardEvents());
}
- getInput() {
- return this.inputNode && this.inputNode.getWrappedInstance
- ? this.inputNode.getWrappedInstance()
- : this.inputNode;
- }
-
getKeyboardEvents() {
return {
keydown: this.handleKeyDown,
@@ -123,12 +124,6 @@ const factory = (ProgressBar, Input) => {
};
}
- addToValue(increment) {
- let value = this.state.inputFocused ? parseFloat(this.state.inputValue) : this.props.value;
- value = this.trimValue(value + increment);
- if (value !== this.props.value) this.props.onChange(value);
- }
-
handleInputFocus = () => {
this.setState({
inputFocused: true,
@@ -148,13 +143,19 @@ const factory = (ProgressBar, Input) => {
};
handleKeyDown = (event) => {
- if ([13, 27].indexOf(event.keyCode) !== -1) this.getInput().blur();
- if (event.keyCode === 38) this.addToValue(this.props.step);
- if (event.keyCode === 40) this.addToValue(-this.props.step);
+ const { disabled, step } = this.props;
+ const {
+ ARROW_DOWN, ARROW_UP, ENTER, ESC,
+ } = KEYS;
+
+ if (disabled) return;
+ if ([ENTER, ESC].includes(event.code)) this.inputNode.blur();
+ if (event.code === ARROW_UP) this.addToValue(step);
+ if (event.code === ARROW_DOWN) this.addToValue(-step);
};
handleMouseDown = (event) => {
- if (this.state.inputFocused) this.getInput().blur();
+ if (this.state.inputFocused) this.inputNode.blur();
events.addEventsToDocument(this.getMouseEventMap());
this.start(events.getMousePosition(event));
events.pauseEvent(event);
@@ -192,12 +193,18 @@ const factory = (ProgressBar, Input) => {
};
handleTouchStart = (event) => {
- if (this.state.inputFocused) this.getInput().blur();
+ if (this.state.inputFocused) this.inputNode.blur();
this.start(events.getTouchPosition(event));
events.addEventsToDocument(this.getTouchEventMap());
events.pauseEvent(event);
};
+ addToValue(increment) {
+ let value = this.state.inputFocused ? parseFloat(this.state.inputValue) : this.props.value;
+ value = this.trimValue(value + increment);
+ if (value !== this.props.value) this.props.onChange(value);
+ }
+
end(revents) {
events.removeEventsFromDocument(revents);
this.setState({ pressed: false });
@@ -246,9 +253,7 @@ const factory = (ProgressBar, Input) => {
if (!this.props.snaps) return undefined;
return (
- {selectable &&
-
- }
+ {selectable && (
+
+
+
+ )}
{React.Children.map(children, (child, index) => {
if (!child) return null;
return cloneElement(child, {
diff --git a/components/table/index.js b/components/table/index.js
index ff2500d60..ae1fa1abb 100644
--- a/components/table/index.js
+++ b/components/table/index.js
@@ -7,7 +7,7 @@ import { tableFactory } from './Table';
import { tableHeadFactory } from './TableHead';
import { tableRowFactory } from './TableRow';
import { tableCellFactory } from './TableCell';
-import theme from './theme.css';
+import theme from './theme.module.css';
const applyTheme = Component => themr(TABLE, theme)(Component);
const ThemedTableCell = applyTheme(tableCellFactory(FontIcon));
diff --git a/components/table/readme.md b/components/table/readme.md
index 3d99021bc..780de0009 100644
--- a/components/table/readme.md
+++ b/components/table/readme.md
@@ -99,10 +99,10 @@ This is the `Table` main wrapper component. It parses children to generate an ap
Name | Type | Default | Description
:---------------- | :--------- | :------ | :-------------------------------------------------------------
-`children` | `Node` | | Pass `TableHead` and `TableRow` components as children always.
+`children` | `Node` | | Pass `TableHead` and `TableRow` components as children always.
`className` | `String` | `''` | Sets a custom class to style the component.
`multiSelectable` | `Boolean` | `false` | If true, the header and each row will display a checkbox to allow the user to select multiple rows at the same time.
-`onRowSelect` | `Function` | | Will be called when the row selection changes. It passes an array of selected indexes as first parameter so you can figure out changes in your local state.
+`onRowSelect` | `Function` | | Will be called when the row selection changes. It passes an array of selected indexes as first parameter so you can figure out changes in your local state.
`selectable` | `Boolean` | `true` | If true, each row will display a checkbox to allow the user to select that one row.
## TableHead
@@ -113,7 +113,7 @@ Header element that should be place as a direct descendant of `Table` and whose
Name | Type | Default | Description
:---------------- | :--------- | :------ | :----------------------------------------------
-`children` | `Node` | | Pass `TableCell` components always either decorated or not.
+`children` | `Node` | | Pass `TableCell` components always either decorated or not.
`className` | `String` | `''` | Sets a custom class to style the header row.
`displaySelect` | `Boolean` | `true` | If true, a checkbox will be displayed to select every row. In case the table is not multi-selectable, it will be disabled though.
@@ -125,7 +125,7 @@ An element that represents a row in the Table. It should be place as a direct de
Name | Type | Default | Description
:---------------- | :--------- | :------ | :----------------------------------------------
-`children` | `Node` | | Pass `TableCell` components always either decorated or not.
+`children` | `Node` | | Pass `TableCell` components always either decorated or not.
`className` | `String` | `''` | Sets a custom class to style the row.
`selected` | `Boolean` | `false` | If true, the row will be considered as selected so the row will display a selected style with the selection control activated. This property is used by `Table` to figure out the selection when you interact with the Table.
@@ -135,10 +135,10 @@ Displays a cell of the `Table`. It renders a tag `td` or `th` depending on if it
Name | Type | Default | Description
:---------------- | :--------- | :------ | :----------------------------------------------
-`children` | `Any` | | Any content you want to render inside the cell.
+`children` | `Any` | | Any content you want to render inside the cell.
`className` | `String` | `''` | Sets a custom class to style that particular cell.
`numeric` | `Boolean` | `false` | If true the cell is considered as numeric and the content will be displayed aligned to right.
-`onClick` | `Function` | | Called when the cell is clicked with the click event, column number and row number.
+`onClick` | `Function` | | Called when the cell is clicked with the click event, column number and row number.
`sorted` | `Bool` | `asc` or `desc` | Optional. If you provide a value the cell will show an arrow pointing down or up depending on the value to indicate it is a sorted element. Useful only for columns.
## Theme
diff --git a/components/table/theme.css b/components/table/theme.module.css
similarity index 83%
rename from components/table/theme.css
rename to components/table/theme.module.css
index 985380d6f..efa4d0d9f 100644
--- a/components/table/theme.css
+++ b/components/table/theme.module.css
@@ -1,15 +1,15 @@
-@import 'http://github.com/colors.css';
-@import 'http://github.com/variables.css';
+@import 'http://github.com/colors.module.css';
+@import 'http://github.com/variables.module.css';
:root {
--table-font-size: calc(1.3 * var(--unit));
--table-header-font-size: calc(1.2 * var(--unit));
--table-header-sort-icon-size: calc(1.6 * var(--unit));
- --table-header-color: color(#000 a(54%));
- --table-header-sorted-color: color(#000 a(87%));
- --table-header-sorted-icon-hover-color: color(#000 a(26%));
+ --table-header-color: color-mod(#000 a(54%));
+ --table-header-sorted-color: color-mod(#000 a(87%));
+ --table-header-sorted-icon-hover-color: color-mod(#000 a(26%));
--table-dividers: 1px solid #e6e6e6;
- --table-row-color: color(#000 a(87%));
+ --table-row-color: color-mod(#000 a(87%));
--table-hover-color: #eee;
--table-selection-color: #f5f5f5;
--table-row-height: calc(4.8 * var(--unit));
@@ -40,18 +40,10 @@
transition-property: background-color;
transition-timing-function: var(--animation-curve-default);
- &:hover { background-color: var(--table-hover-color); }
&.selected { background-color: var(--table-selection-color); }
-}
-
-.rowCell,
-.headCell {
- padding: 0 var(--table-column-padding) 12px var(--table-column-padding);
- text-align: left;
- &:first-of-type { padding-left: 24px; }
- &:last-of-type { padding-right: 24px; }
- &.numeric { text-align: right; }
+ &:hover,
+ &.selected:hover { background-color: var(--table-hover-color); }
}
.rowCell {
@@ -62,6 +54,7 @@
vertical-align: middle;
&.checkboxCell {
+ padding-right: 5px;
width: calc(1.8 * var(--unit));
& > * {
@@ -70,6 +63,18 @@
}
}
+.sortIcon {
+ display: inline-block;
+ font-size: calc(1.6 * var(--unit));
+ margin-right: 3px;
+ transition: 0.28s transform var(--animation-curve-default);
+ vertical-align: sub;
+
+ &.asc {
+ transform: rotate(180deg);
+ }
+}
+
.headCell {
color: var(--table-header-color);
font-size: var(--table-header-font-size);
@@ -81,6 +86,7 @@
vertical-align: bottom;
&.checkboxCell {
+ padding-right: 5px;
width: calc(1.8 * var(--unit));
& > * {
@@ -98,14 +104,12 @@
}
}
-.sortIcon {
- display: inline-block;
- font-size: calc(1.6 * var(--unit));
- margin-right: 3px;
- transition: 0.28s transform var(--animation-curve-default);
- vertical-align: sub;
+.rowCell,
+.headCell {
+ padding: 12px var(--table-column-padding);
+ text-align: left;
- &.asc {
- transform: rotate(180deg);
- }
+ &:first-of-type { padding-left: 24px; }
+ &:last-of-type { padding-right: 24px; }
+ &.numeric { text-align: right; }
}
diff --git a/components/tabs/Tab.d.ts b/components/tabs/Tab.d.ts
index c7cf99b23..59c1e0274 100644
--- a/components/tabs/Tab.d.ts
+++ b/components/tabs/Tab.d.ts
@@ -52,9 +52,9 @@ export interface TabProps extends ReactToolbox.Props {
*/
icon?: React.ReactNode;
/**
- * Label text for navigation header. Required.
+ * Label text for navigation header.
*/
- label: string;
+ label?: string;
/**
* Callback function that is fired when the tab is activated.
*/
diff --git a/components/tabs/Tab.js b/components/tabs/Tab.js
index eb35c2228..381539c87 100644
--- a/components/tabs/Tab.js
+++ b/components/tabs/Tab.js
@@ -2,11 +2,11 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
-import { FontIcon } from '../font_icon';
import { TABS } from '../identifiers';
import rippleFactory from '../ripple/Ripple';
+import InjectFontIcon from '../font_icon/FontIcon';
-const factory = (ripple) => {
+const factory = (ripple, FontIcon) => {
class Tab extends Component {
static propTypes = {
active: PropTypes.bool,
@@ -65,7 +65,7 @@ const factory = (ripple) => {
}, className);
return (
-
Provide an image source or object, a font icon, children or a title to use its first letter.
-
- } />
-
-
-
+ } />
+
+
+
-
-
+
+
);
diff --git a/spec/components/button.js b/spec/components/button.js
index 6c0a2e651..6398f9612 100644
--- a/spec/components/button.js
+++ b/spec/components/button.js
@@ -30,7 +30,7 @@ const ButtonTest = () => (
Icon Buttons should align in the vertical center, to see this we need to
put them next to text or highlight thier background color.
-
+ MenuMenu
diff --git a/spec/components/card.js b/spec/components/card.js
index 1f53e8d4e..355d9e7ac 100644
--- a/spec/components/card.js
+++ b/spec/components/card.js
@@ -2,7 +2,7 @@
import React from 'react';
import Button, { IconButton } from '../../components/button';
import Card, { CardActions, CardMedia, CardText, CardTitle } from '../../components/card';
-import style from '../style';
+import style from '../style.module.css';
const dummyText = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.';
diff --git a/spec/components/chip.js b/spec/components/chip.js
index 703a2b4d0..6f7d25856 100644
--- a/spec/components/chip.js
+++ b/spec/components/chip.js
@@ -1,7 +1,10 @@
import React from 'react';
import Avatar from '../../components/avatar';
import Chip from '../../components/chip';
-import style from '../style';
+import style from '../style.module.css';
+import { cold } from 'react-hot-loader';
+
+const ColdAvatar = cold(Avatar)
class ChipTest extends React.Component {
state = {
@@ -38,16 +41,16 @@ class ChipTest extends React.Component {
}
-
+ Avatar Chip
- Initial chip
+ Initial chip
-
+ Image contact chip
diff --git a/spec/components/drawer.js b/spec/components/drawer.js
index f71f3380c..1279e162f 100644
--- a/spec/components/drawer.js
+++ b/spec/components/drawer.js
@@ -1,7 +1,7 @@
import React from 'react';
import Button from '../../components/button';
import Drawer from '../../components/drawer';
-import style from '../style.css';
+import style from '../style.module.css';
class DrawerTest extends React.Component {
state = {
diff --git a/spec/components/dropdown.js b/spec/components/dropdown.js
index a7bd8b89f..52a12716d 100644
--- a/spec/components/dropdown.js
+++ b/spec/components/dropdown.js
@@ -1,6 +1,6 @@
import React from 'react';
import Dropdown from '../../components/dropdown';
-import style from '../style';
+import style from '../style.module.css';
const countries = [
{ value: 'EN-gb', label: 'England', img: 'http://' },
diff --git a/spec/components/input.js b/spec/components/input.js
index 8801cdf4d..52e67e99a 100644
--- a/spec/components/input.js
+++ b/spec/components/input.js
@@ -12,8 +12,8 @@ class InputTest extends React.Component {
multilineRows: 'A\n\B\nC\nD\nE\nF',
};
- handleChange = (name, value) => {
- this.setState({ ...this.state, [name]: value });
+ handleChange = (value, ev) => {
+ this.setState({[ev.target.name]: value });
};
render() {
@@ -23,18 +23,19 @@ class InputTest extends React.Component {
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default AutocompleteTest;
diff --git a/spec/ts/avatar.tsx b/spec/ts/avatar.tsx
new file mode 100644
index 000000000..87dfab0e3
--- /dev/null
+++ b/spec/ts/avatar.tsx
@@ -0,0 +1,22 @@
+import * as React from 'react';
+import Avatar from '../../components/avatar';
+import GithubIcon from './github_icon';
+
+const AvatarTest = () => (
+
+
Avatars
+
Provide an image source or object, a font icon, children or a title to use its first letter.
+
+ } />
+
+
+
+
+
+
+);
+
+export default AvatarTest;
diff --git a/spec/ts/button.tsx b/spec/ts/button.tsx
new file mode 100644
index 000000000..9a7c51ac7
--- /dev/null
+++ b/spec/ts/button.tsx
@@ -0,0 +1,51 @@
+import * as React from 'react';
+import GithubIcon from './github_icon';
+import { Button, IconButton, BrowseButton } from '../../components/button';
+
+const ButtonTest = () => (
+
+
Buttons
+
lorem ipsum...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Icon Button Alignment
+
+ Icon Buttons should align in the vertical center, to see this we need to
+ put them next to text or highlight thier background color.
+
+
+ Menu
+
+ Menu
+
+ Github
+
Browse Button
+
+
+
+
+
+);
+
+function rippleEnded() {
+ console.log('Ripple animation ended!');
+}
+
+export default ButtonTest;
diff --git a/spec/ts/card.tsx b/spec/ts/card.tsx
new file mode 100644
index 000000000..9ffbceff0
--- /dev/null
+++ b/spec/ts/card.tsx
@@ -0,0 +1,247 @@
+/* eslint-disable react/prop-types */
+import * as React from 'react';
+import Button, { IconButton } from '../../components/button';
+import Card, { CardActions, CardMedia, CardText, CardTitle } from '../../components/card';
+
+const style = require('../style.module.css');
+
+const dummyText = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.';
+
+const Spacer: React.SFC = () => ;
+const CardList: React.SFC = ({ children }) =>
You can navigate using a drawer to the left or right.
+
+
+
Officia deserunt mollit.
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.