wix-style-react
Version:
377 lines (314 loc) • 14.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _InputWithOptions2 = _interopRequireDefault(require("../InputWithOptions/InputWithOptions"));
var _InputWithTags = _interopRequireDefault(require("./InputWithTags"));
var _last = _interopRequireDefault(require("lodash/last"));
var _difference = _interopRequireDefault(require("difference"));
var _MultiSelectSt = require("./MultiSelect.st.css");
var _excluded = ["className", "data-ref"],
_excluded2 = ["className", "ref"];
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var MultiSelect = /*#__PURE__*/function (_InputWithOptions) {
(0, _inherits2["default"])(MultiSelect, _InputWithOptions);
var _super = _createSuper(MultiSelect);
function MultiSelect(props) {
var _this;
(0, _classCallCheck2["default"])(this, MultiSelect);
_this = _super.call(this, props);
_this.onKeyDown = _this.onKeyDown.bind((0, _assertThisInitialized2["default"])(_this));
_this.onPaste = _this.onPaste.bind((0, _assertThisInitialized2["default"])(_this));
_this.state = _objectSpread(_objectSpread({}, _this.state), {}, {
pasteDetected: false
});
return _this;
}
(0, _createClass2["default"])(MultiSelect, [{
key: "hideOptions",
value: function hideOptions() {
(0, _get2["default"])((0, _getPrototypeOf2["default"])(MultiSelect.prototype), "hideOptions", this).call(this);
if (this.props.clearOnBlur) {
this.clearInput();
}
}
}, {
key: "onClickOutside",
value: function onClickOutside() {
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, _difference["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 {
readOnly: false,
disableEditing: true,
inputElement: /*#__PURE__*/_react["default"].createElement(_InputWithTags["default"], {
onReorder: this.props.onReorder,
maxNumRows: this.props.maxNumRows,
mode: this.props.mode,
hideCustomSuffix: this.isDropdownLayoutVisible(),
customSuffix: this.props.customSuffix
}),
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;
this.setState({
pasteDetected: false
}, function () {
_this2.submitValue(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: "_onSelect",
value: function _onSelect(option) {
this.onSelect(option);
}
}, {
key: "_onManuallyInput",
value: function _onManuallyInput(inputValue, event) {
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);
_value && event.preventDefault();
if (this.closeOnSelect()) {
this.hideOptions();
}
}
}, {
key: "getManualSubmitKeys",
value: function getManualSubmitKeys() {
return ['Enter', 'Tab'].concat(this.props.delimiters);
}
}, {
key: "onKeyDown",
value: function onKeyDown(event) {
var _this$props = this.props,
tags = _this$props.tags,
value = _this$props.value,
onRemoveTag = _this$props.onRemoveTag;
if (tags.length > 0 && (event.key === 'Delete' || event.key === 'Backspace') && value.length === 0) {
onRemoveTag((0, _last["default"])(tags).id);
}
if (event.key === 'Escape') {
this.clearInput();
(0, _get2["default"])((0, _getPrototypeOf2["default"])(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 ? _objectSpread({
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;
}));
}
}
}, {
key: "submitValue",
value: function submitValue(inputValue) {
if (!inputValue) {
return;
}
var onManuallyInput = this.props.onManuallyInput;
var values = this._splitByDelimitersAndTrim(inputValue);
onManuallyInput && values.length && onManuallyInput(values);
this.clearInput();
}
}, {
key: "clearInput",
value: function clearInput() {
this.input.current && this.input.current.clear();
if (this.props.onChange) {
this.props.onChange({
target: {
value: ''
}
});
}
}
}]);
return MultiSelect;
}(_InputWithOptions2["default"]);
(0, _defineProperty2["default"])(MultiSelect, "autoSizeInput", function (_ref2) {
var className = _ref2.className,
dataRef = _ref2['data-ref'],
rest = (0, _objectWithoutProperties2["default"])(_ref2, _excluded);
var inputClassName = (0, _classnames["default"])(className, _MultiSelectSt.classes.autoSizeInput);
return /*#__PURE__*/_react["default"].createElement("input", (0, _extends2["default"])({}, rest, {
ref: dataRef,
className: inputClassName
}));
});
(0, _defineProperty2["default"])(MultiSelect, "autoSizeInputWithRef", function () {
return /*#__PURE__*/_react["default"].forwardRef(function (props, ref) {
return function (_ref3) {
var className = _ref3.className,
ref = _ref3.ref,
rest = (0, _objectWithoutProperties2["default"])(_ref3, _excluded2);
var inputClassName = (0, _classnames["default"])(className, _MultiSelectSt.classes.autoSizeInput);
return /*#__PURE__*/_react["default"].createElement("input", (0, _extends2["default"])({}, rest, {
ref: ref,
className: inputClassName
}));
}(_objectSpread(_objectSpread({}, props), {}, {
ref: ref
}));
});
});
MultiSelect.displayName = 'MultiSelect';
MultiSelect.propTypes = {
/** Closes list once list item is selected */
closeOnSelect: _propTypes["default"].bool,
/** Callback predicate for the filtering options function */
predicate: _propTypes["default"].func,
/** Optional list of strings that are selected suggestions. */
tags: _propTypes["default"].array,
/** Max number of visible lines */
maxNumRows: _propTypes["default"].number,
/** Delimiters that will trigger a Submit action (call to onTagsAdded). By default it is [,] but also enter and tab keys work. */
delimiters: _propTypes["default"].array,
/** Passing 'select' will render a readOnly input with menuArrow suffix **/
mode: _propTypes["default"].string,
/** The status of the Multiselect */
status: _propTypes["default"].oneOf(['loading', 'warning', 'error']),
/** Text to be shown in the status icon tooltip */
statusMessage: _propTypes["default"].string,
/** When this callback function is set, tags can be reordered. The expected callback signature is `onReorder({addedIndex: number, removedIndex: number}) => void` **/
onReorder: _propTypes["default"].func,
/** A callback which is called when the user enters something in the input and then confirms the input with some action like Enter key or Tab. */
onManuallyInput: _propTypes["default"].func,
/** A callback which is called when options dropdown is shown */
onOptionsShow: _propTypes["default"].func,
/** A callback which is called when options dropdown is hidden */
onOptionsHide: _propTypes["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: _propTypes["default"].func,
/** Allows adding your own custom Input component instead of the one that is used by default internally. */
customInput: _propTypes["default"].elementType ? _propTypes["default"].oneOfType([_propTypes["default"].func, _propTypes["default"].elementType]) : _propTypes["default"].oneOfType([_propTypes["default"].func]),
/** A node to display as input suffix when the dropdown is closed */
customSuffix: _propTypes["default"].node,
/** When set to true this component is disabled */
disabled: _propTypes["default"].bool,
/** When set to false, the input will not be cleared on blur */
clearOnBlur: _propTypes["default"].bool,
/** A callback function to be called when a tag should be removed. The expected callback signature is `onRemoveTag(tagId: number | string) => void.` */
onRemoveTag: _propTypes["default"].func
};
MultiSelect.defaultProps = _objectSpread(_objectSpread({}, _InputWithOptions2["default"].defaultProps), {}, {
predicate: function predicate() {
return true;
},
tags: [],
delimiters: [','],
clearOnBlur: true,
customInput: MultiSelect.autoSizeInputWithRef()
});
var _default = MultiSelect;
exports["default"] = _default;