UNPKG

@commercetools-uikit/select-input

Version:

An input component getting a selection from the user.

251 lines (243 loc) • 13 kB
import _defineProperty from '@babel/runtime-corejs3/helpers/esm/defineProperty'; import _objectWithoutProperties from '@babel/runtime-corejs3/helpers/esm/objectWithoutProperties'; import _flatMapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/flat-map'; import _filterInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/filter'; import _mapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/map'; import _findInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/find'; import _Object$keys from '@babel/runtime-corejs3/core-js-stable/object/keys'; import _Object$getOwnPropertySymbols from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols'; import _Object$getOwnPropertyDescriptor from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor'; import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each'; import _Object$getOwnPropertyDescriptors from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors'; import _Object$defineProperties from '@babel/runtime-corejs3/core-js-stable/object/define-properties'; import _Object$defineProperty from '@babel/runtime-corejs3/core-js-stable/object/define-property'; import { useIntl } from 'react-intl'; import isEmpty from 'lodash/isEmpty'; import has from 'lodash/has'; import Select, { components } from 'react-select'; import Constraints from '@commercetools-uikit/constraints'; import { warnIfMenuPortalPropsAreMissing, messages, customComponentsWithIcons, optionStyleCheckboxComponents, createSelectStyles, optionsStyleCheckboxSelectProps, DropdownIndicator, ClearIndicator, TagRemove } from '@commercetools-uikit/select-utils'; import { filterDataAttributes } from '@commercetools-uikit/utils'; import { SearchIcon } from '@commercetools-uikit/icons'; import { jsx } from '@emotion/react/jsx-runtime'; const _excluded = ["appearance", "maxMenuHeight", "menuPortalZIndex", "options", "optionStyle"]; function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context4, _context5; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context4 = ownKeys(Object(t), !0)).call(_context4, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context5 = ownKeys(Object(t))).call(_context5, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; } const customizedComponents = { DropdownIndicator, ClearIndicator, MultiValueRemove: TagRemove }; const isOptionObject = option => option.options !== undefined; const SelectInput = _ref => { var _context, _context2; let _ref$appearance = _ref.appearance, appearance = _ref$appearance === void 0 ? 'default' : _ref$appearance, _ref$maxMenuHeight = _ref.maxMenuHeight, maxMenuHeight = _ref$maxMenuHeight === void 0 ? 220 : _ref$maxMenuHeight, _ref$menuPortalZIndex = _ref.menuPortalZIndex, menuPortalZIndex = _ref$menuPortalZIndex === void 0 ? 1 : _ref$menuPortalZIndex, _ref$options = _ref.options, options = _ref$options === void 0 ? [] : _ref$options, _ref$optionStyle = _ref.optionStyle, optionStyle = _ref$optionStyle === void 0 ? 'list' : _ref$optionStyle, props = _objectWithoutProperties(_ref, _excluded); const intl = useIntl(); warnIfMenuPortalPropsAreMissing({ menuPortalZIndex: menuPortalZIndex, menuPortalTarget: props.menuPortalTarget, componentName: 'SelectInput' }); const placeholder = appearance === 'filter' && !props.placeholder ? intl.formatMessage(messages.selectInputAsFilterPlaceholder) : props.placeholder || intl.formatMessage(messages.placeholder); // Options can be grouped as // const colourOptions = [{ value: 'green', label: 'Green' }]; // const flavourOptions = [{ value: 'vanilla', label: 'Vanilla' }]; // const groupedOptions = [ // { label: 'Colours', options: colourOptions }, // { label: 'Flavours', options: flavourOptions }, // ]; // So we "ungroup" the options by merging them all into one list first. const optionsWithoutGroups = _flatMapInstanceProperty(options).call(options, option => { if (isOptionObject(option)) { return option.options; } return option; }); const selectedOptions = props.isMulti ? _filterInstanceProperty(_context = _mapInstanceProperty(_context2 = props.value || [] // Pass the options in the order selected by the user, so that the // sorting is not lost ).call(_context2, value => _findInstanceProperty(optionsWithoutGroups).call(optionsWithoutGroups, option => option.value === value))).call(_context, option => Boolean(option)) : _findInstanceProperty(optionsWithoutGroups).call(optionsWithoutGroups, option => has(option, 'value') && option.value === props.value) || null; return jsx(Constraints.Horizontal, { max: props.horizontalConstraint, children: jsx("div", _objectSpread(_objectSpread({}, filterDataAttributes(_objectSpread({ appearance, maxMenuHeight, menuPortalZIndex, optionStyle }, props))), {}, { children: jsx(Select, _objectSpread(_objectSpread({ "aria-label": props['aria-label'], "aria-labelledby": props['aria-labelledby'], "aria-invalid": props['aria-invalid'], "aria-errormessage": props['aria-errormessage'], autoFocus: props.isAutofocussed, backspaceRemovesValue: props.isReadOnly ? false : props.backspaceRemovesValue, components: _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, customizedComponents), props.iconLeft && !props.isMulti ? customComponentsWithIcons : {}), props.isReadOnly ? { Input: ownProps => jsx(components.Input, _objectSpread(_objectSpread({}, ownProps), {}, { readOnly: true })) } : {}), appearance === 'filter' && { DropdownIndicator: () => jsx(SearchIcon, { color: "neutral60" }), ClearIndicator: null }), optionStyle === 'checkbox' ? optionStyleCheckboxComponents(appearance) : {}), props.components), menuIsOpen: props.isReadOnly ? false : appearance === 'filter' ? true : props.menuIsOpen, styles: createSelectStyles({ hasWarning: props.hasWarning, hasError: props.hasError, showOptionGroupDivider: props.showOptionGroupDivider, menuPortalZIndex: menuPortalZIndex, appearance: appearance, isDisabled: props.isDisabled, isReadOnly: props.isReadOnly, isCondensed: appearance === 'filter' ? true : props.isCondensed, iconLeft: props.iconLeft, isMulti: props.isMulti, hasValue: !isEmpty(selectedOptions), controlShouldRenderValue: props.controlShouldRenderValue, horizontalConstraint: props.horizontalConstraint, minMenuWidth: props.minMenuWidth, maxMenuWidth: props.maxMenuWidth }), filterOption: props.filterOption // react-select uses "id" (for the container) and "inputId" (for the input), // but we use "id" (for the input) and "containerId" (for the container) // instead. // This makes it easier to less confusing to use with <label />s. , id: props.containerId, inputId: props.id, inputValue: props.inputValue, isClearable: props.isReadOnly ? false : props.isClearable, isDisabled: props.isDisabled, isOptionDisabled: props.isOptionDisabled }, optionStyle === 'checkbox' ? optionsStyleCheckboxSelectProps() : { hideSelectedOptions: props.hideSelectedOptions }), {}, { // @ts-ignore isReadOnly: props.isReadOnly, isMulti: props.isMulti, isSearchable: props.isSearchable, isCondensed: props.isCondensed, maxMenuHeight: maxMenuHeight, menuPortalTarget: props.menuPortalTarget, menuShouldBlockScroll: props.menuShouldBlockScroll // @ts-expect-error: optionStyle 'checkbox' will override this property (if set) , closeMenuOnSelect: props.closeMenuOnSelect, name: props.name, noOptionsMessage: props.noOptionsMessage || (_ref2 => { let inputValue = _ref2.inputValue; return !inputValue || inputValue === '' ? intl.formatMessage(messages.noOptionsMessageWithoutInputValue) : intl.formatMessage(messages.noOptionsMessageWithInputValue, { inputValue }); }), onBlur: typeof props.onBlur === 'function' ? () => { const event = { target: { id: props.id, name: (() => { if (!props.isMulti) return props.name; // We append the ".0" to make Formik set the touched // state as an array instead of a boolean only. // Otherwise the shapes would clash on submission, as // Formik will create an array on submission anyways. return props.name ? `${props.name}.0` : undefined; })() }, persist: () => {} }; props.onBlur && props.onBlur(event); } : undefined, onChange: nextSelectedOptions => { // nextSelectedOptions is either an array, or a single option, or null // depending on whether we're in multi-mode or not (isMulti) let value = null; if (props.isMulti) { if (nextSelectedOptions) { var _context3; value = _mapInstanceProperty(_context3 = nextSelectedOptions).call(_context3, option => option.value); } else { value = []; } } else if (nextSelectedOptions) { value = nextSelectedOptions.value; } props.onChange && props.onChange({ target: { id: props.id, name: props.name, value }, persist: () => {} }); }, onFocus: props.onFocus, onInputChange: props.onInputChange, options: options, placeholder: placeholder, tabIndex: props.tabIndex, tabSelectsValue: props.tabSelectsValue, value: selectedOptions, iconLeft: props.iconLeft, controlShouldRenderValue: appearance === 'filter' ? false : props.controlShouldRenderValue, menuPlacement: "auto" }, optionStyle === 'checkbox' ? optionsStyleCheckboxSelectProps() : {})) })) }); }; SelectInput.displayName = 'SelectInput'; /** * Expose static helper methods. */ // Both "true" and an empty array [] represent a touched state. SelectInput.isTouched = touched => Boolean(touched); /** * Expose react-select components for customization purposes. */ // custom SelectInput.ClearIndicator = customizedComponents.ClearIndicator; SelectInput.Control = components.Control; //https://github.com/commercetools/ui-kit/pull/3054/files#r1943026570 SelectInput.CrossIcon = components.CrossIcon; //https://github.com/commercetools/ui-kit/pull/3054/files#r1943026570 SelectInput.DownChevron = components.DownChevron; // custom SelectInput.DropdownIndicator = customizedComponents.DropdownIndicator; SelectInput.Group = components.Group; SelectInput.GroupHeading = components.GroupHeading; SelectInput.IndicatorSeparator = components.IndicatorSeparator; SelectInput.IndicatorsContainer = components.IndicatorsContainer; SelectInput.Input = components.Input; SelectInput.LoadingIndicator = components.LoadingIndicator; SelectInput.LoadingMessage = components.LoadingMessage; SelectInput.Menu = components.Menu; SelectInput.MenuList = components.MenuList; //https://github.com/commercetools/ui-kit/pull/3054/files#r1943026570 SelectInput.MenuPortal = components.MenuPortal; SelectInput.MultiValue = components.MultiValue; SelectInput.MultiValueContainer = components.MultiValueContainer; SelectInput.MultiValueLabel = components.MultiValueLabel; // custom SelectInput.MultiValueRemove = customizedComponents.MultiValueRemove; SelectInput.NoOptionsMessage = components.NoOptionsMessage; SelectInput.Option = components.Option; SelectInput.Placeholder = components.Placeholder; SelectInput.SelectContainer = components.SelectContainer; SelectInput.SingleValue = components.SingleValue; SelectInput.ValueContainer = components.ValueContainer; var SelectInput$1 = SelectInput; // NOTE: This string will be replaced on build time with the package version. var version = "20.2.3"; export { SelectInput$1 as default, version };