UNPKG

wix-style-react

Version:
419 lines (353 loc) • 14.9 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _InputWithOptions2 = require('../InputWithOptions/InputWithOptions'); var _InputWithOptions3 = _interopRequireDefault(_InputWithOptions2); var _InputWithTags = require('./InputWithTags'); var _InputWithTags2 = _interopRequireDefault(_InputWithTags); var _last = require('lodash/last'); var _last2 = _interopRequireDefault(_last); var _difference = require('difference'); var _difference2 = _interopRequireDefault(_difference); var _uniqueId = require('lodash/uniqueId'); var _uniqueId2 = _interopRequireDefault(_uniqueId); var _propTypes3 = require('../utils/propTypes'); var _deprecationLog = require('../utils/deprecationLog'); var _deprecationLog2 = _interopRequireDefault(_deprecationLog); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 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 MultiSelect = function (_InputWithOptions) { _inherits(MultiSelect, _InputWithOptions); function MultiSelect(props) { _classCallCheck(this, MultiSelect); var _this = _possibleConstructorReturn(this, (MultiSelect.__proto__ || Object.getPrototypeOf(MultiSelect)).call(this, props)); _this.onKeyDown = _this.onKeyDown.bind(_this); _this.onPaste = _this.onPaste.bind(_this); _this.state = _extends({}, _this.state, { pasteDetected: false }); return _this; } _createClass(MultiSelect, [{ key: '_isNewCallbackApi', value: function _isNewCallbackApi() { return this.props.upgrade; } }, { key: 'hideOptions', value: function hideOptions() { _get(MultiSelect.prototype.__proto__ || Object.getPrototypeOf(MultiSelect.prototype), 'hideOptions', this).call(this); this.clearInput(); } }, { key: 'onClickOutside', value: function onClickOutside() { var _props = this.props, value = _props.value, options = _props.options, onSelect = _props.onSelect; if (!this._isNewCallbackApi()) { if (!options.length && value) { onSelect([{ id: value.trim(), label: value.trim() }]); } } if (this.state.showOptions) { this.hideOptions(); } } }, { key: 'getUnselectedOptions', value: function getUnselectedOptions() { var optionIds = this.props.options.map(function (option) { return option.id; }); var tagIds = this.props.tags.map(function (tag) { return tag.id; }); var unselectedOptionsIds = (0, _difference2.default)(optionIds, tagIds); return this.props.options.filter(function (option) { return unselectedOptionsIds.includes(option.id); }); } }, { key: 'dropdownAdditionalProps', value: function dropdownAdditionalProps() { return { options: this.getUnselectedOptions().filter(this.props.predicate), closeOnSelect: false, selectedHighlight: false, selectedId: -1 }; } }, { key: 'closeOnSelect', value: function closeOnSelect() { return false; } }, { key: 'inputAdditionalProps', value: function inputAdditionalProps() { return { inputElement: _react2.default.createElement(_InputWithTags2.default, { onReorder: this.props.onReorder, maxNumRows: this.props.maxNumRows, mode: this.props.mode }), onKeyDown: this.onKeyDown, delimiters: this.props.delimiters, onPaste: this.onPaste }; } }, { key: 'onPaste', value: function onPaste() { this.setState({ pasteDetected: true }); } }, { key: '_splitByDelimitersAndTrim', value: function _splitByDelimitersAndTrim(value) { var delimitersRegexp = new RegExp(this.props.delimiters.join('|'), 'g'); return value.split(delimitersRegexp).map(function (str) { return str.trim(); }).filter(function (str) { return str; }); } }, { key: '_onChange', value: function _onChange(event) { var _this2 = this; if (this.state.pasteDetected) { var value = event.target.value; if (this._isNewCallbackApi()) { this.setState({ pasteDetected: false }, function () { _this2.submitValue(value); }); } else { this.deprecatedOnChangePaste(value); } } else { this.setState({ inputValue: event.target.value }); this.props.onChange && this.props.onChange(event); } // If the input value is not empty, should show the options if (event.target.value.trim()) { this.showOptions(); } } }, { key: 'deprecatedOnChangePaste', value: function deprecatedOnChangePaste(value) { var _this3 = this; var tags = this._splitByDelimitersAndTrim(value); var suggestedOptions = tags.map(function (tag) { var tagObj = _this3.getUnselectedOptions().find(function (element) { return _this3.props.valueParser(element).toLowerCase() === tag.toLowerCase(); }); return tagObj ? tagObj : { id: (0, _uniqueId2.default)('customOption_'), value: tag, theme: 'error' }; }); this.setState({ pasteDetected: false }, function () { _this3.deprecatedOnSelect(suggestedOptions); _this3.clearInput(); }); } }, { key: '_onSelect', value: function _onSelect(option) { if (this._isNewCallbackApi()) { this.onSelect(option); } else { this.deprecatedOnSelect([option]); } } }, { key: '_onManuallyInput', value: function _onManuallyInput(inputValue) { if (this._isNewCallbackApi()) { var value = this.props.value; // FIXME: InputWithOptions is not updating it's inputValue state when the `value` prop changes. // So using `value` here, covers for that bug. (This is tested) // BTW: Previously, `value` was used to trigger onSelect, and `inputValue` was used to trigger onManuallyInput. Which is crazy. // So now both of them trigger a submit (onManuallyInput). var _value = value && value.trim() || inputValue && inputValue.trim(); this.submitValue(_value); if (this.closeOnSelect()) { this.hideOptions(); } } else { this._deprecatedOnManuallyInput(inputValue); } } }, { key: '_deprecatedOnManuallyInput', value: function _deprecatedOnManuallyInput(inputValue) { var _props2 = this.props, value = _props2.value, options = _props2.options; if (value && value.trim()) { if (options.length) { var unselectedOptions = this.getUnselectedOptions(); var visibleOptions = unselectedOptions.filter(this.props.predicate); var maybeNearestOption = visibleOptions[0]; if (maybeNearestOption) { this.deprecatedOnSelect([maybeNearestOption]); } } else { this.props.onSelect([{ id: value.trim(), label: value.trim() }]); } } if (inputValue) { inputValue = inputValue.trim(); if (this.closeOnSelect()) { this.hideOptions(); } this.submitValue(inputValue); } this.clearInput(); } }, { key: 'getManualSubmitKeys', value: function getManualSubmitKeys() { return ['Enter', 'Tab'].concat(this.props.delimiters); } }, { key: 'onKeyDown', value: function onKeyDown(event) { var _props3 = this.props, tags = _props3.tags, value = _props3.value, onRemoveTag = _props3.onRemoveTag; if (tags.length > 0 && (event.key === 'Delete' || event.key === 'Backspace') && value.length === 0) { onRemoveTag((0, _last2.default)(tags).id); } if (event.key === 'Escape') { this.clearInput(); _get(MultiSelect.prototype.__proto__ || Object.getPrototypeOf(MultiSelect.prototype), 'hideOptions', this).call(this); } if (this.props.onKeyDown) { this.props.onKeyDown(event); } } }, { key: 'optionToTag', value: function optionToTag(_ref) { var id = _ref.id, value = _ref.value, tag = _ref.tag, theme = _ref.theme; return tag ? _extends({ id: id }, tag) : { id: id, label: value, theme: theme }; } }, { key: 'onSelect', value: function onSelect(option) { this.clearInput(); var onSelect = this.props.onSelect; if (onSelect) { onSelect(this.props.options.find(function (o) { return o.id === option.id; })); } this.input.focus(); } }, { key: 'deprecatedOnSelect', value: function deprecatedOnSelect(_options) { this.clearInput(); var onSelect = this.props.onSelect; if (onSelect) { var tags = _options.map(this.optionToTag); onSelect(tags); } this.input.focus(); } }, { key: 'submitValue', value: function submitValue(inputValue) { if (!inputValue) { return; } var onManuallyInput = this.props.onManuallyInput; if (this._isNewCallbackApi()) { var values = this._splitByDelimitersAndTrim(inputValue); onManuallyInput && values.length && onManuallyInput(values); } else { if (onManuallyInput) { onManuallyInput(inputValue, this.optionToTag({ id: (0, _uniqueId2.default)('customOption_'), value: inputValue })); } } this.clearInput(); } }, { key: 'clearInput', value: function clearInput() { this.input.clear(); if (this.props.onChange) { this.props.onChange({ target: { value: '' } }); } } }]); return MultiSelect; }(_InputWithOptions3.default); function inputWithOptionsPropTypes() { var _InputWithOptions$pro = _InputWithOptions3.default.propTypes, selectedId = _InputWithOptions$pro.selectedId, closeOnSelect = _InputWithOptions$pro.closeOnSelect, selectedHighlight = _InputWithOptions$pro.selectedHighlight, rest = _objectWithoutProperties(_InputWithOptions$pro, ['selectedId', 'closeOnSelect', 'selectedHighlight']); return rest; } MultiSelect.propTypes = _extends({}, inputWithOptionsPropTypes(), { predicate: _propTypes2.default.func, tags: _propTypes2.default.array, maxNumRows: _propTypes2.default.number, delimiters: _propTypes2.default.array, mode: _propTypes2.default.string, error: _propTypes2.default.bool, errorMessage: _propTypes2.default.string, onReorder: _propTypes2.default.func, /** A callback which is called when the user performs a Submit-Action. * Submit-Action triggers are: "Enter", "Tab", [typing any defined delimiters], Paste action. * `onManuallyInput(values: Array<string>): void - The array of strings is the result of splitting the input value by the given delimiters */ onManuallyInput: _propTypes2.default.func, /** A callback which is called when the user selects an option from the list. * `onSelect(option: Option): void` - Option is the original option from the provided `options` prop. */ onSelect: _propTypes2.default.func, /** When `true`, then the latest Callback API will be used. Otherwise, see the Old API under the Deprecated stories. */ upgrade: _propTypes2.default.bool }); (0, _propTypes3.extendPropTypes)(MultiSelect, { valueParser: (0, _propTypes3.allValidators)(_propTypes2.default.func, function (props, propName) { var valueParser = props[propName]; if (valueParser && valueParser !== _InputWithOptions2.DEFAULT_VALUE_PARSER && props['upgrade']) { return new Error('When \'upgrade\' is passed then \'valueParser\' will not be used. Please remove the \'valueParser\' prop.'); } }), upgrade: (0, _propTypes3.allValidators)(_propTypes2.default.bool, function (props, propName) { if (!props[propName]) { (0, _deprecationLog2.default)('MultiSelect: New API! Please upgrade by passing the prop \'upgrade=true\', and refer to documentation.'); } }) }); MultiSelect.defaultProps = _extends({}, _InputWithOptions3.default.defaultProps, { highlight: true, theme: 'tags', predicate: function predicate() { return true; }, tags: [], delimiters: [','] }); exports.default = MultiSelect;