diff --git a/lib/autocomplete/Autocomplete.js b/lib/autocomplete/Autocomplete.js index 33f4a169..eeea6ec0 100644 --- a/lib/autocomplete/Autocomplete.js +++ b/lib/autocomplete/Autocomplete.js @@ -81,18 +81,24 @@ var factory = function factory(Chip, Input) { query: _this.query(_this.props.value) }, _this.handleChange = function (keys, event) { var key = _this.props.multiple ? keys : keys[0]; + var showAllSuggestions = _this.props.showSuggestionsWhenValueIsSet; + var query = _this.query(key); if (_this.props.onChange) _this.props.onChange(key, event); - _this.setState({ focus: false, query: query, showAllSuggestions: _this.props.showSuggestionsWhenValueIsSet }, function () { - _reactDom2.default.findDOMNode(_this).querySelector('input').blur(); - }); + if (_this.props.keepFocusOnChange) { + _this.setState({ query: query, showAllSuggestions: showAllSuggestions }); + } else { + _this.setState({ focus: false, query: query, showAllSuggestions: showAllSuggestions }, function () { + _reactDom2.default.findDOMNode(_this).querySelector('input').blur(); + }); + } }, _this.handleQueryBlur = function (event) { if (_this.state.focus) _this.setState({ focus: false }); if (_this.props.onBlur) _this.props.onBlur(event, _this.state.active); }, _this.handleQueryChange = function (value) { _this.setState({ query: value, showAllSuggestions: false, active: null }); }, _this.handleQueryFocus = function () { - _this.refs.suggestions.scrollTop = 0; + _this.suggestionsNode.scrollTop = 0; _this.setState({ active: '', focus: true }); if (_this.props.onFocus) _this.props.onFocus(); }, _this.handleQueryKeyDown = function (event) { @@ -154,7 +160,7 @@ var factory = function factory(Chip, Input) { key: 'calculateDirection', value: function calculateDirection() { if (this.props.direction === 'auto') { - var client = _reactDom2.default.findDOMNode(this.refs.input).getBoundingClientRect(); + var client = _reactDom2.default.findDOMNode(this.inputNode).getBoundingClientRect(); var screen_height = window.innerHeight || document.documentElement.offsetHeight; var up = client.top > screen_height / 2 + client.height; return up ? 'up' : 'down'; @@ -381,16 +387,22 @@ var factory = function factory(Chip, Input) { ); }); - var className = (0, _classnames5.default)(theme.suggestions, _defineProperty({}, theme.up, this.state.direction === 'up')); return _react2.default.createElement( 'ul', - { ref: 'suggestions', className: className }, + { + className: (0, _classnames5.default)(theme.suggestions, _defineProperty({}, theme.up, this.state.direction === 'up')), + ref: function ref(node) { + _this3.suggestionsNode = node; + } + }, suggestions ); } }, { key: 'render', value: function render() { + var _this4 = this; + var _props = this.props, allowCreate = _props.allowCreate, error = _props.error, @@ -398,9 +410,10 @@ var factory = function factory(Chip, Input) { source = _props.source, suggestionMatch = _props.suggestionMatch, selectedPosition = _props.selectedPosition, + keepFocusOnChange = _props.keepFocusOnChange, showSuggestionsWhenValueIsSet = _props.showSuggestionsWhenValueIsSet, theme = _props.theme, - other = _objectWithoutProperties(_props, ['allowCreate', 'error', 'label', 'source', 'suggestionMatch', 'selectedPosition', 'showSuggestionsWhenValueIsSet', 'theme']); + other = _objectWithoutProperties(_props, ['allowCreate', 'error', 'label', 'source', 'suggestionMatch', 'selectedPosition', 'keepFocusOnChange', 'showSuggestionsWhenValueIsSet', 'theme']); var className = (0, _classnames5.default)(theme.autocomplete, _defineProperty({}, theme.focus, this.state.focus), this.props.className); @@ -409,7 +422,10 @@ var factory = function factory(Chip, Input) { { 'data-react-toolbox': 'autocomplete', className: className }, this.props.selectedPosition === 'above' ? this.renderSelected() : null, _react2.default.createElement(Input, _extends({}, other, { - ref: 'input', + ref: function ref(node) { + _this4.inputNode = node; + }, + autoComplete: 'off', className: theme.input, error: error, label: label, @@ -437,6 +453,7 @@ var factory = function factory(Chip, Input) { direction: _react.PropTypes.oneOf(['auto', 'up', 'down']), disabled: _react.PropTypes.bool, error: _react.PropTypes.string, + keepFocusOnChange: _react.PropTypes.bool, label: _react.PropTypes.string, multiple: _react.PropTypes.bool, onBlur: _react.PropTypes.func, @@ -463,8 +480,9 @@ var factory = function factory(Chip, Input) { allowCreate: false, className: '', direction: 'auto', - selectedPosition: 'above', + keepFocusOnChange: false, multiple: true, + selectedPosition: 'above', showSuggestionsWhenValueIsSet: false, source: {}, suggestionMatch: 'start' diff --git a/lib/checkbox/Checkbox.js b/lib/checkbox/Checkbox.js index 97c7320e..24582244 100644 --- a/lib/checkbox/Checkbox.js +++ b/lib/checkbox/Checkbox.js @@ -67,22 +67,25 @@ var factory = function factory(Check) { _createClass(Checkbox, [{ key: 'blur', value: function blur() { - this.refs.input.blur(); + this.inputNode && this.inputNode.blur(); } }, { key: 'focus', value: function focus() { - this.refs.input.focus(); + this.inputNode && this.inputNode.focus(); } }, { key: 'render', value: function render() { - var _props = this.props, - onChange = _props.onChange, - theme = _props.theme, - style = _props.style, - others = _objectWithoutProperties(_props, ['onChange', 'theme', 'style']); //eslint-disable-line no-unused-vars + var _this2 = this; + var _props = this.props, + checked = _props.checked, + disabled = _props.disabled, + label = _props.label, + style = _props.style, + theme = _props.theme, + others = _objectWithoutProperties(_props, ['checked', 'disabled', 'label', 'style', 'theme']); var className = (0, _classnames3.default)(theme.field, _defineProperty({}, theme.disabled, this.props.disabled), this.props.className); @@ -90,23 +93,27 @@ var factory = function factory(Check) { 'label', { 'data-react-toolbox': 'checkbox', className: className }, _react2.default.createElement('input', _extends({}, others, { + checked: checked, className: theme.input, + disabled: disabled, + onChange: function onChange() {}, onClick: this.handleToggle, - readOnly: true, - ref: 'input', + ref: function ref(node) { + _this2.inputNode = node; + }, type: 'checkbox' })), _react2.default.createElement(Check, { - checked: this.props.checked, - disabled: this.props.disabled, + checked: checked, + disabled: disabled, rippleClassName: theme.ripple, style: style, - theme: this.props.theme + theme: theme }), - this.props.label ? _react2.default.createElement( + label ? _react2.default.createElement( 'span', { 'data-react-toolbox': 'label', className: theme.text }, - this.props.label + label ) : null ); } diff --git a/lib/dropdown/Dropdown.js b/lib/dropdown/Dropdown.js index f03cfe9f..55994c8a 100644 --- a/lib/dropdown/Dropdown.js +++ b/lib/dropdown/Dropdown.js @@ -68,6 +68,12 @@ var factory = function factory(Input) { click: _this.handleDocumentClick, touchend: _this.handleDocumentClick }; + }, _this.open = function () { + var client = event.target.getBoundingClientRect(); + var screenHeight = window.innerHeight || document.documentElement.offsetHeight; + var up = _this.props.auto ? client.top > screenHeight / 2 + client.height : false; + if (_this.inputNode) _this.inputNode.blur(); + _this.setState({ active: true, up: up }); }, _this.close = function () { if (_this.state.active) { _this.setState({ active: false }); @@ -77,14 +83,9 @@ var factory = function factory(Input) { _this.setState({ active: false }); } }, _this.handleClick = function (event) { + _this.open(); _events2.default.pauseEvent(event); - var client = event.target.getBoundingClientRect(); - var screen_height = window.innerHeight || document.documentElement.offsetHeight; - var up = _this.props.auto ? client.top > screen_height / 2 + client.height : false; if (_this.props.onClick) _this.props.onClick(event); - if (_this.props.onFocus) _this.props.onFocus(event); - if (_this.inputNode) _this.inputNode.blur(); - _this.setState({ active: true, up: up }); }, _this.handleSelect = function (item, event) { if (_this.props.onBlur) _this.props.onBlur(event); if (!_this.props.disabled && _this.props.onChange) { @@ -92,7 +93,7 @@ var factory = function factory(Input) { event.target.name = _this.props.name; } _this.props.onChange(item, event); - _this.setState({ active: false }); + _this.close(); } }, _this.getSelectedItem = function () { var _iteratorNormalCompletion = true; @@ -132,6 +133,14 @@ var factory = function factory(Input) { { key: idx, className: className, onClick: _this.handleSelect.bind(_this, item.value) }, _this.props.template ? _this.props.template(item) : item.label ); + }, _this.handleFocus = function (event) { + event.stopPropagation(); + if (!_this.props.disabled) _this.open(); + if (_this.props.onFocus) _this.props.onFocus(event); + }, _this.handleBlur = function (event) { + event.stopPropagation(); + if (_this.state.active) _this.close(); + if (_this.props.onBlur) _this.props.onBlur(event); }, _temp), _possibleConstructorReturn(_this, _ret); } @@ -197,22 +206,31 @@ var factory = function factory(Input) { _this2 = this; var _props = this.props, - template = _props.template, - theme = _props.theme, - source = _props.source, allowBlank = _props.allowBlank, auto = _props.auto, required = _props.required, - others = _objectWithoutProperties(_props, ['template', 'theme', 'source', 'allowBlank', 'auto', 'required']); //eslint-disable-line no-unused-vars - + onChange = _props.onChange, + onFocus = _props.onFocus, + onBlur = _props.onBlur, + source = _props.source, + template = _props.template, + theme = _props.theme, + others = _objectWithoutProperties(_props, ['allowBlank', 'auto', 'required', 'onChange', 'onFocus', 'onBlur', 'source', 'template', 'theme']); var selected = this.getSelectedItem(); var className = (0, _classnames4.default)(theme.dropdown, (_classnames2 = {}, _defineProperty(_classnames2, theme.up, this.state.up), _defineProperty(_classnames2, theme.active, this.state.active), _defineProperty(_classnames2, theme.disabled, this.props.disabled), _defineProperty(_classnames2, theme.required, this.props.required), _classnames2), this.props.className); return _react2.default.createElement( 'div', - { 'data-react-toolbox': 'dropdown', className: className }, + { + className: className, + 'data-react-toolbox': 'dropdown', + onBlur: this.handleBlur, + onFocus: this.handleFocus, + tabIndex: '0' + }, _react2.default.createElement(Input, _extends({}, others, { + tabIndex: '-1', className: theme.value, onClick: this.handleClick, required: this.props.required, diff --git a/lib/hoc/ActivableRenderer.js b/lib/hoc/ActivableRenderer.js index d5218ef5..09c34f98 100644 --- a/lib/hoc/ActivableRenderer.js +++ b/lib/hoc/ActivableRenderer.js @@ -53,6 +53,12 @@ var ActivableRendererFactory = function ActivableRendererFactory() { if (nextProps.active && !this.props.active) this.renderAndActivate(); if (!nextProps.active && this.props.active) this.deactivateAndUnrender(); } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + clearTimeout(this.activateTimeout); + clearTimeout(this.unrenderTimeout); + } }, { key: 'renderAndActivate', value: function renderAndActivate() { @@ -60,7 +66,7 @@ var ActivableRendererFactory = function ActivableRendererFactory() { if (this.unrenderTimeout) clearTimeout(this.unrenderTimeout); this.setState({ rendered: true, active: false }, function () { - setTimeout(function () { + _this2.activateTimeout = setTimeout(function () { return _this2.setState({ active: true }); }, 20); }); diff --git a/lib/list/List.js b/lib/list/List.js index eac163f8..d0859031 100644 --- a/lib/list/List.js +++ b/lib/list/List.js @@ -31,6 +31,10 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +var mergeProp = function mergeProp(propName, child, parent) { + return child[propName] !== undefined ? child[propName] : parent[propName]; +}; + var factory = function factory(ListItem) { var List = function (_Component) { _inherits(List, _Component); @@ -48,10 +52,9 @@ var factory = function factory(ListItem) { return _react2.default.Children.map(this.props.children, function (item) { if (item.type === ListItem) { - return _react2.default.cloneElement(item, { - ripple: _this2.props.ripple, - selectable: _this2.props.selectable - }); + var selectable = mergeProp('selectable', item.props, _this2.props); + var ripple = mergeProp('ripple', item.props, _this2.props); + return _react2.default.cloneElement(item, { selectable: selectable, ripple: ripple }); } else { return _react2.default.cloneElement(item); } diff --git a/lib/radio/RadioButton.js b/lib/radio/RadioButton.js index 4f1d4724..cc0f32bc 100644 --- a/lib/radio/RadioButton.js +++ b/lib/radio/RadioButton.js @@ -68,16 +68,18 @@ var factory = function factory(Radio) { _createClass(RadioButton, [{ key: 'blur', value: function blur() { - this.refs.input.blur(); + this.inputNode && this.inputNode.blur(); } }, { key: 'focus', value: function focus() { - this.refs.input.focus(); + this.inputNode && this.inputNode.focus(); } }, { key: 'render', value: function render() { + var _this2 = this; + var _props = this.props, className = _props.className, checked = _props.checked, @@ -93,10 +95,14 @@ var factory = function factory(Radio) { 'label', { 'data-react-toolbox': 'radio-button', className: _className }, _react2.default.createElement('input', _extends({}, others, { + checked: checked, className: theme.input, + disabled: disabled, onClick: this.handleClick, - readOnly: true, - ref: 'input', + onChange: function onChange() {}, + ref: function ref(node) { + _this2.inputNode = node; + }, type: 'radio' })), _react2.default.createElement(Radio, { checked: checked, disabled: disabled, theme: theme }), diff --git a/lib/snackbar/Snackbar.js b/lib/snackbar/Snackbar.js index 2535733a..653de016 100644 --- a/lib/snackbar/Snackbar.js +++ b/lib/snackbar/Snackbar.js @@ -46,22 +46,40 @@ var factory = function factory(Overlay, Button) { _inherits(Snackbar, _Component); function Snackbar() { + var _ref; + + var _temp, _this, _ret; + _classCallCheck(this, Snackbar); - return _possibleConstructorReturn(this, (Snackbar.__proto__ || Object.getPrototypeOf(Snackbar)).apply(this, arguments)); + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Snackbar.__proto__ || Object.getPrototypeOf(Snackbar)).call.apply(_ref, [this].concat(args))), _this), _this.scheduleTimeout = function (props) { + var onTimeout = props.onTimeout, + timeout = props.timeout; + + if (_this.curTimeout) clearTimeout(_this.curTimeout); + _this.curTimeout = setTimeout(function () { + if (onTimeout) onTimeout(); + _this.curTimeout = null; + }, timeout); + }, _temp), _possibleConstructorReturn(_this, _ret); } _createClass(Snackbar, [{ + key: 'componentDidMount', + value: function componentDidMount() { + if (this.props.active && this.props.timeout) { + this.scheduleTimeout(this.props); + } + } + }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { - var _this2 = this; - if (nextProps.active && nextProps.timeout) { - if (this.curTimeout) clearTimeout(this.curTimeout); - this.curTimeout = setTimeout(function () { - nextProps.onTimeout(); - _this2.curTimeout = null; - }, nextProps.timeout); + this.scheduleTimeout(nextProps); } } }, { diff --git a/package.json b/package.json index e52b2bf5..6c6af089 100644 --- a/package.json +++ b/package.json @@ -36,64 +36,64 @@ "toolkit" ], "dependencies": { - "classnames": "~2.2.5", - "core-js": "~2.4.0", - "normalize.css": "~4.2.0", - "react-css-themr": "~1.6.0" + "classnames": "^2.2.5", + "core-js": "^2.4.0", + "normalize.css": "^4.2.0", + "react-css-themr": "^1.6.0" }, "devDependencies": { - "autoprefixer": "~6.5.1", - "babel-cli": "~6.16.0", - "babel-core": "~6.17.0", - "babel-eslint": "~7.0.0", - "babel-loader": "~6.2.4", - "babel-plugin-react-transform": "~2.0.2", - "babel-polyfill": "~6.16.0", - "babel-preset-es2015": "~6.16.0", - "babel-preset-react": "~6.16.0", - "babel-preset-stage-0": "~6.16.0", - "cpx": "~1.5.0", - "cross-env": "~3.1.3", - "css-loader": "~0.25.0", - "eslint": "~3.8.1", - "eslint-import-resolver-webpack": "~0.6.0", - "eslint-plugin-babel": "~3.3.0", - "eslint-plugin-import": "~2.0.1", - "eslint-plugin-jsx-a11y": "~2.2.3", - "eslint-plugin-react": "~6.4.1", - "expect": "~1.20.1", - "express": "~4.14.0", - "extract-text-webpack-plugin": "~1.0.1", - "git-dirty": "~1.0.2", - "glob": "~7.1.1", - "immutability-helper": "~2.0.0", - "internal-ip": "~1.2.0", - "karma": "~1.3.0", - "karma-cli": "~1.0.0", - "karma-mocha": "~1.2.0", - "karma-phantomjs-launcher": "~1.0.0", - "karma-webpack": "~1.8.0", + "autoprefixer": "^6.5.1", + "babel-cli": "^6.18.0", + "babel-core": "^6.18.2", + "babel-eslint": "^7.1.1", + "babel-loader": "^6.2.4", + "babel-plugin-react-transform": "^2.0.2", + "babel-polyfill": "^6.16.0", + "babel-preset-es2015": "^6.18.0", + "babel-preset-react": "^6.16.0", + "babel-preset-stage-0": "^6.16.0", + "cpx": "^1.5.0", + "cross-env": "^3.1.3", + "css-loader": "^0.26.0", + "eslint": "^3.10.2", + "eslint-import-resolver-webpack": "^0.7.0", + "eslint-plugin-babel": "^4.0.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^3.0.1", + "eslint-plugin-react": "^6.7.1", + "expect": "^1.20.1", + "express": "^4.14.0", + "extract-text-webpack-plugin": "^1.0.1", + "git-dirty": "^1.0.2", + "glob": "^7.1.1", + "immutability-helper": "^2.0.0", + "internal-ip": "^1.2.0", + "karma": "^1.3.0", + "karma-cli": "^1.0.0", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.0", + "karma-webpack": "^1.8.0", "lint-staged": "^3.2.0", - "mocha": "~3.1.2", - "node-sass": "~3.10.1", - "phantomjs-prebuilt": "~2.1.7", - "postcss-loader": "~1.0.0", + "mocha": "^3.1.2", + "node-sass": "^3.13.0", + "phantomjs-prebuilt": "^2.1.7", + "postcss-loader": "^1.1.1", "pre-commit": "^1.1.3", - "react": "~15.3.0", - "react-addons-css-transition-group": "~15.3.0", - "react-addons-test-utils": "~15.3.0", - "react-dom": "~15.3.0", - "react-transform-catch-errors": "~1.0.2", - "react-transform-hmr": "~1.0.4", - "redbox-react": "~1.3.2", - "rimraf": "~2.5.2", - "sass-lint": "1.9.1", - "sass-loader": "~4.0.0", - "sinon": "~2.0.0-pre.2", - "style-loader": "~0.13.1", - "webpack": "~1.13.0", - "webpack-dev-middleware": "~1.8.4", - "webpack-hot-middleware": "~2.13.0" + "react": "^15.4.0", + "react-addons-css-transition-group": "^15.4.0", + "react-addons-test-utils": "^15.4.0", + "react-dom": "^15.4.0", + "react-transform-catch-errors": "^1.0.2", + "react-transform-hmr": "^1.0.4", + "redbox-react": "^1.3.2", + "rimraf": "^2.5.2", + "sass-lint": "^1.10.2", + "sass-loader": "^4.0.0", + "sinon": "^2.0.0-pre.2", + "style-loader": "^0.13.1", + "webpack": "^1.13.0", + "webpack-dev-middleware": "^1.8.4", + "webpack-hot-middleware": "^2.13.0" }, "scripts": { "babel": "babel ./components --out-dir ./lib", @@ -115,11 +115,11 @@ }, "license": "MIT", "peerDependencies": { - "classnames": "~2.2.0", - "immutability-helper": "~2.0.0", - "react": "~0.14 || ~15.3.0", - "react-addons-css-transition-group": "~0.14.0 || ~15.3.0", - "react-dom": "~0.14.0 || ~15.3.0" + "classnames": "^2.2.0", + "immutability-helper": "^2.0.0", + "react": "^0.14 || ~15.4.0", + "react-addons-css-transition-group": "^0.14.0 || ~15.4.0", + "react-dom": "^0.14.0 || ~15.4.0" }, "pre-commit": "lint:staged" }