UNPKG

calcite-react

Version:
412 lines (334 loc) 15.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _propTypes = _interopRequireDefault(require("prop-types")); var _downshift = _interopRequireDefault(require("downshift")); var _memoizeOne = _interopRequireDefault(require("memoize-one")); var _reactVirtualized = require("react-virtualized"); var _reactPopper = require("react-popper"); var _helpers = require("../utils/helpers"); var _MultiSelectStyled = require("./MultiSelect-styled"); var _MultiSelectMenu = _interopRequireDefault(require("./MultiSelectMenu")); var _FormControl = require("../Form/FormControl"); var _Popover = require("../Popover/Popover"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } function _extends() { _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; }; return _extends.apply(this, arguments); } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } var MultiSelect = function MultiSelect(_ref) { var children = _ref.children, selectedValues = _ref.selectedValues, placeholder = _ref.placeholder, wrapperStyle = _ref.wrapperStyle, menuStyle = _ref.menuStyle, id = _ref.id, fullWidth = _ref.fullWidth, minimal = _ref.minimal, onChange = _ref.onChange, renderValue = _ref.renderValue, positionFixed = _ref.positionFixed, appendToBody = _ref.appendToBody, disabled = _ref.disabled, onBlur = _ref.onBlur, field = _ref.field, form = _ref.form, closeOnSelect = _ref.closeOnSelect, virtualized = _ref.virtualized, virtualizedRowHeight = _ref.virtualizedRowHeight, virtualizedMenuWidth = _ref.virtualizedMenuWidth, popperModifiers = _ref.popperModifiers, other = _objectWithoutProperties(_ref, ["children", "selectedValues", "placeholder", "wrapperStyle", "menuStyle", "id", "fullWidth", "minimal", "onChange", "renderValue", "positionFixed", "appendToBody", "disabled", "onBlur", "field", "form", "closeOnSelect", "virtualized", "virtualizedRowHeight", "virtualizedMenuWidth", "popperModifiers"]); var name, touched, errors, isSubmitting, setFieldValue; if (field) { name = field.name; touched = form.touched; errors = form.errors; isSubmitting = form.isSubmitting; setFieldValue = form.setFieldValue; } var menuHeight = menuStyle && parseInt(menuStyle.height, 10) || menuStyle && parseInt(menuStyle.maxHeight, 10) || 300; function itemToString(item) { var label = item; if (item && item.props) { label = item.props.label || item.props.children || item; } return label; } function downshiftRenderValue(items) { if (renderValue) return renderValue(items); if (!items || !items.length) return placeholder; return items.map(function (item) { return itemToString(item); }).join(', '); } function downshiftOnChange(selectedItem, downshiftProps) { var selectedItems = downshiftProps.selectedItem; // Ignore onChange if not item was selected (e.g. escape key) if (!selectedItem) return; var existingValues = selectedItems.map(function (item) { return item.props.value; }); var values; if (existingValues.indexOf(selectedItem.props.value) !== -1) { // Already selected item was clicked, remove it values = selectedItems.filter(function (item) { return item.props.value !== selectedItem.props.value; }).map(function (item) { return item.props.value; }); } else { // An unselected item was clicked, add it selection values = [].concat(_toConsumableArray(existingValues), [selectedItem.props.value]); } if (setFieldValue) { setFieldValue(name, values); } onChange(values); } function _getItemsFromValues(values) { return _react.Children.toArray(children).filter(function (child) { return values.indexOf(child.props.value) !== -1; }); } function getSelectedValues() { return field ? field.value : selectedValues; } function handleBlur(e) { if (field) { field.onBlur(e); } onBlur(e); } function isSuccess(formControlContext) { if (touched) { return touched[name] && !errors[name] ? true : false; } return formControlContext.success; } function isError(formControlContext) { if (touched) { return touched[name] && errors[name] ? true : false; } return formControlContext.error; } function isDisabled() { return isSubmitting || disabled; } function _getPopper(popper, isOpen, isInPopover, appendToBody) { if (isOpen || isInPopover) { if (appendToBody) { return _reactDom.default.createPortal(popper, document.body); } return popper; } } function _stateReducer(state, changes) { if (closeOnSelect) { return changes; } switch (changes.type) { case _downshift.default.stateChangeTypes.keyDownEnter: case _downshift.default.stateChangeTypes.clickItem: return _objectSpread({}, changes, { isOpen: state.isOpen, highlightedIndex: state.highlightedIndex }); default: return changes; } } var getValues = (0, _memoizeOne.default)(function (selectedItems) { return selectedItems.map(function (selectedItem) { return selectedItem.props.value; }); }); function getMenuItems(filteredList, params) { var getItemProps = params.getItemProps, highlightedIndex = params.highlightedIndex, selectedValues = params.selectedValues; if (virtualized) { return _react.default.createElement(_reactVirtualized.List, { width: virtualizedMenuWidth || 9999, autoWidth: !virtualizedMenuWidth, scrollToIndex: highlightedIndex || 0, scrollToAlignment: "auto", height: filteredList.length < 7 ? filteredList.length * virtualizedRowHeight : menuHeight, rowCount: filteredList.length, rowHeight: virtualizedRowHeight, rowRenderer: function rowRenderer(_ref2) { var index = _ref2.index, rowRenderStyle = _ref2.style; return getMenuItem(filteredList[index], { getItemProps: getItemProps, highlightedIndex: highlightedIndex, index: index, selectedValues: selectedValues, rowRenderStyle: rowRenderStyle }); }, style: { direction: document && document.documentElement.dir || 'ltr' } }); } return filteredList.map(function (item, index) { return getMenuItem(item, { getItemProps: getItemProps, highlightedIndex: highlightedIndex, index: index, selectedValues: selectedValues }); }); } function getMenuItem(item, params) { var getItemProps = params.getItemProps, highlightedIndex = params.highlightedIndex, index = params.index, selectedValues = params.selectedValues, rowRenderStyle = params.rowRenderStyle; return _react.default.cloneElement(item, _objectSpread({}, getItemProps({ style: _objectSpread({}, item.props.style, rowRenderStyle), item: item, index: index, active: highlightedIndex === index, selected: selectedValues.indexOf(item.props.value) > -1, key: item.props.value }))); } return _react.default.createElement(_reactPopper.Manager, null, _react.default.createElement(_downshift.default, { itemToString: itemToString, onChange: downshiftOnChange, onBlur: handleBlur, stateReducer: _stateReducer, selectedItem: _getItemsFromValues(getSelectedValues()) }, function (_ref3) { var getRootProps = _ref3.getRootProps, getToggleButtonProps = _ref3.getToggleButtonProps, getInputProps = _ref3.getInputProps, getItemProps = _ref3.getItemProps, isOpen = _ref3.isOpen, openMenu = _ref3.openMenu, selectedItem = _ref3.selectedItem, highlightedIndex = _ref3.highlightedIndex, selectHighlightedItem = _ref3.selectHighlightedItem; var selectedValues = getValues(selectedItem); var onKeyDown = function onKeyDown(event) { if (!event) return; if (event.key === 'Enter') {} else if (event.key === ' ') { if (highlightedIndex === null) openMenu();else { event.nativeEvent.preventDefault(); // Avoids an extra space after value selectHighlightedItem(); } } }; return _react.default.createElement(_MultiSelectStyled.StyledMultiSelectWrapper, _extends({}, getRootProps({}, { suppressRefError: true }), { style: wrapperStyle }), _react.default.createElement(_reactPopper.Reference, { style: { display: 'inline-block' } }, function (_ref4) { var ref = _ref4.ref; return _react.default.createElement(_FormControl.FormControlContext.Consumer, null, function (formControlContext) { return _react.default.createElement(_MultiSelectStyled.StyledMultiSelectButton, _extends({ ref: ref, success: isSuccess(formControlContext), error: isError(formControlContext), disabled: isDisabled(), as: "button" }, getToggleButtonProps(), getInputProps({ id: id || formControlContext._generatedId, fullWidth: fullWidth, minimal: minimal, onKeyDown: onKeyDown }), other), downshiftRenderValue(selectedItem)); }); }), _react.default.createElement(_Popover.PopoverContext.Consumer, null, function (popoverContext) { return _getPopper(_react.default.createElement(_reactPopper.Popper, { positionFixed: positionFixed, placement: (0, _helpers.rtlPlacement)(other.placement), modifiers: _objectSpread({ preventOverflow: { boundariesElement: positionFixed || appendToBody ? 'window' : 'scrollParent' } }, popperModifiers) }, function (_ref5) { var popperRef = _ref5.ref, style = _ref5.style, placement = _ref5.placement, scheduleUpdate = _ref5.scheduleUpdate; return _react.default.createElement(_MultiSelectMenu.default, { innerRef: popperRef, style: _objectSpread({}, style, menuStyle), fullWidth: fullWidth, "data-placement": placement, isOpen: isOpen, scheduleUpdate: scheduleUpdate }, getMenuItems(children, { getItemProps: getItemProps, highlightedIndex: highlightedIndex, selectedValues: selectedValues })); }), isOpen, popoverContext.isInPopover, appendToBody); })); })); }; MultiSelect.propTypes = { /** Nodes to be used as options in the Select. */ children: _propTypes.default.node, /** Callback function fired when the value of the Select changes. */ onChange: _propTypes.default.func, /** Callback function fired when the Select element is blurred. */ onBlur: _propTypes.default.func, /** The selected item of the Select. */ selectedItem: _propTypes.default.node, /** Value of the selected item. */ selectedValue: _propTypes.default.node, /** Function to run when determining how to display selected values in a collapsed MultiSelect. */ renderValue: _propTypes.default.func, /** Placement of the popover in relation to the target. */ placement: _propTypes.default.oneOf(['top', 'right', 'bottom', 'left', 'top-start', 'right-start', 'bottom-start', 'left-start', 'top-end', 'right-end', 'bottom-end', 'left-end']), /** Placeholder text for the input. */ placeholder: _propTypes.default.string, /** Whether or not the Select will fill its container's width. */ fullWidth: _propTypes.default.bool, /** A style variant for Select inputs. */ minimal: _propTypes.default.bool, /** Style prop applied to the menu wrapper. */ menuStyle: _propTypes.default.object, /** Uses `position: fixed` on the tooltip allowing it to show up outside of containers that have `overflow: hidden`. */ positionFixed: _propTypes.default.bool, /** Whether or not to close the menu on each selection. */ closeOnSelect: _propTypes.default.bool, /** Use react-virtualized to render rows as the user scrolls. */ virtualized: _propTypes.default.bool, /** (virtualized only) Row height used to calculate how many rows to render in a virtualized Menu. */ virtualizedRowHeight: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.func]), /** (virtualized only) Width of the menu; unloaded rows may be wider than the initial set. */ virtualizedMenuWidth: _propTypes.default.number, /** Modifiers to be passed to the Popper element */ popperModifiers: _propTypes.default.object }; MultiSelect.defaultProps = { placeholder: 'Select...', placement: 'bottom-start', closeOnSelect: true, virtualizedRowHeight: 42, onChange: function onChange() {}, onBlur: function onBlur() {} }; MultiSelect.displayName = 'MultiSelect'; var _default = MultiSelect; exports.default = _default;