UNPKG

@spark-web/combobox

Version:

--- title: Combobox storybookPath: forms-combobox--default isExperimentalPackage: true ---

348 lines (339 loc) 12.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray'); var _typeof = require('@babel/runtime/helpers/typeof'); var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator'); var _slicedToArray = require('@babel/runtime/helpers/slicedToArray'); var _regeneratorRuntime = require('@babel/runtime/regenerator'); var field = require('@spark-web/field'); var react = require('react'); var ReactSelect = require('react-select'); var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties'); var _objectSpread = require('@babel/runtime/helpers/objectSpread2'); var a11y = require('@spark-web/a11y'); var box = require('@spark-web/box'); var icon = require('@spark-web/icon'); var spinner = require('@spark-web/spinner'); var text = require('@spark-web/text'); var theme = require('@spark-web/theme'); var internal = require('@spark-web/utils/internal'); var jsxRuntime = require('react/jsx-runtime'); function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } var _regeneratorRuntime__default = /*#__PURE__*/_interopDefault(_regeneratorRuntime); var ReactSelect__default = /*#__PURE__*/_interopDefault(ReactSelect); var _excluded = ["children"]; var useReactSelectComponentsOverride = function useReactSelectComponentsOverride(data) { var _useFieldContext = field.useFieldContext(), _useFieldContext2 = _slicedToArray(_useFieldContext, 2), invalid = _useFieldContext2[0].invalid, fieldProps = _useFieldContext2[1]; return react.useMemo(function () { return { DropdownIndicator: function DropdownIndicator(props) { return /*#__PURE__*/jsxRuntime.jsx(ReactSelect.components.DropdownIndicator, _objectSpread(_objectSpread({}, props), {}, { children: /*#__PURE__*/jsxRuntime.jsx(icon.ChevronDownIcon, { size: "xxsmall", tone: "muted" }) })); }, Input: function Input(props) { return /*#__PURE__*/jsxRuntime.jsx(ReactSelect.components.Input, _objectSpread(_objectSpread(_objectSpread({}, props), data ? internal.buildDataAttributes(data) : undefined), {}, { "aria-invalid": fieldProps['aria-invalid'], "aria-describedby": fieldProps['aria-describedby'] })); }, IndicatorSeparator: function IndicatorSeparator() { return null; }, LoadingIndicator: function LoadingIndicator() { return null; }, LoadingMessage: function LoadingMessage(props) { return /*#__PURE__*/jsxRuntime.jsx(ReactSelect.components.LoadingMessage, _objectSpread(_objectSpread({}, props), {}, { children: /*#__PURE__*/jsxRuntime.jsx(box.Box, { paddingY: "large", children: /*#__PURE__*/jsxRuntime.jsx(spinner.Spinner, { size: "xsmall", tone: "primary" }) }) })); }, NoOptionsMessage: function NoOptionsMessage(props) { return /*#__PURE__*/jsxRuntime.jsx(ReactSelect.components.NoOptionsMessage, _objectSpread(_objectSpread({}, props), {}, { children: /*#__PURE__*/jsxRuntime.jsx(box.Box, { paddingY: "large", children: /*#__PURE__*/jsxRuntime.jsx(text.Text, { children: "No matching results" }) }) })); }, SingleValue: function SingleValue(_ref) { var children = _ref.children, props = _objectWithoutProperties(_ref, _excluded); return /*#__PURE__*/jsxRuntime.jsx(ReactSelect.components.SingleValue, _objectSpread(_objectSpread({}, props), {}, { children: /*#__PURE__*/jsxRuntime.jsx(box.Box, { data: invalid ? { invalid: invalid } : undefined, children: children }) })); } }; }, [data, fieldProps, invalid]); }; var useReactSelectStylesOverride = function useReactSelectStylesOverride(_ref2) { var invalid = _ref2.invalid; var theme$1 = theme.useTheme(); var _useText = text.useText({ baseline: false, tone: 'neutral', size: 'standard', weight: 'regular' }), _useText2 = _slicedToArray(_useText, 1), textStyles = _useText2[0]; var _useText3 = text.useText({ baseline: true, tone: 'muted', size: 'xsmall', weight: 'semibold' }), _useText4 = _slicedToArray(_useText3, 1), groupHeadingStyles = _useText4[0]; var focusRingStyles = a11y.useFocusRing({ always: true }); return { control: function control(provided, state) { return _objectSpread(_objectSpread(_objectSpread({}, provided), textStyles), state.isFocused ? focusRingStyles : invalid ? { borderColor: theme$1.color.foreground.critical } : { boxShadow: theme$1.shadow.small }); }, dropdownIndicator: function dropdownIndicator(provided, state) { return _objectSpread(_objectSpread({}, provided), {}, { transitionProperty: 'transform', transitionTimingFunction: 'linear', transitionDuration: '150ms' }, state.isFocused ? { transform: 'rotate(180deg)' } : {}); }, group: function group(provided) { return _objectSpread(_objectSpread(_objectSpread({}, provided), groupHeadingStyles), {}, { padding: 0, margin: 0 }); }, groupHeading: function groupHeading(provided) { return _objectSpread(_objectSpread(_objectSpread({}, provided), groupHeadingStyles), {}, { padding: theme$1.spacing.medium, paddingBottom: theme$1.spacing.small, margin: 0 }); }, menu: function menu(provided) { return _objectSpread(_objectSpread({}, provided), {}, { padding: theme$1.spacing.small, boxShadow: theme$1.shadow.medium, borderRadius: theme$1.border.radius.medium }); }, menuList: function menuList(provided) { return _objectSpread(_objectSpread({}, provided), {}, { padding: 0, display: 'flex', flexDirection: 'column', gap: theme$1.spacing.xsmall }); }, option: function option(provided, state) { return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), textStyles), {}, { borderRadius: theme$1.border.radius.small }, state.isSelected ? { color: theme$1.color.foreground.primaryActive, backgroundColor: theme$1.color.background.primaryMuted } : {}), state.isFocused ? { backgroundColor: state.isSelected ? theme$1.backgroundInteractions.primaryLowHover : theme$1.color.background.surfaceMuted, '> *': { color: state.isSelected ? theme$1.color.foreground.primaryHover : undefined, stroke: state.isSelected ? theme$1.color.foreground.primaryHover : undefined } } : {}), {}, { ':active': { backgroundColor: state.isSelected ? theme$1.backgroundInteractions.positiveLowActive : theme$1.color.background.surfacePressed, '> *': { color: state.isSelected ? theme$1.color.foreground.primaryActive : undefined, stroke: state.isSelected ? theme$1.color.foreground.primaryActive : undefined } } }); }, singleValue: function singleValue(provided) { return _objectSpread(_objectSpread({}, provided), {}, { '[data-invalid=true]': { color: theme$1.color.foreground.muted } }); } }; }; var useReactSelectThemeOverride = function useReactSelectThemeOverride() { var theme$1 = theme.useTheme(); return function (selectTheme) { return _objectSpread(_objectSpread({}, selectTheme), {}, { borderRadius: theme$1.border.radius.small, colors: _objectSpread(_objectSpread({}, selectTheme.colors), {}, { // TODO: map from theme object when tokens are revised primary: '#00a87b', primary75: '#00c28d', primary50: '#9acbb8', primary25: '#c8eada', danger: '#e61e32', dangerLight: '#fec1b5', neutral0: 'white', neutral5: '#fafcfe', neutral10: '#f1f4fb', neutral20: '#dce1ec', neutral30: '#c7cedb', // neutral40, neutral50: '#98a2b8', neutral60: '#646f84', neutral70: '#1a2a3a' // neutral80, // neutral90, }), spacing: { baseUnit: theme$1.spacing.xsmall, controlHeight: theme$1.sizing.medium, menuGutter: theme$1.spacing.xxsmall } }); }; }; var isBrowser = typeof window !== 'undefined'; var useAwaitableItems = function useAwaitableItems(awaitableItems) { var ref = react.useRef(); var _useState = react.useState(false), _useState2 = _slicedToArray(_useState, 2), loading = _useState2[0], setLoading = _useState2[1]; var _useState3 = react.useState([]), _useState4 = _slicedToArray(_useState3, 2), items = _useState4[0], setItems = _useState4[1]; react.useEffect(function () { _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee() { var itemsResult; return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: ref.current = awaitableItems; setLoading(true); _context.next = 4; return awaitableItems; case 4: itemsResult = _context.sent; if (!(ref.current !== awaitableItems)) { _context.next = 7; break; } return _context.abrupt("return"); case 7: setItems(itemsResult); setLoading(false); case 9: case "end": return _context.stop(); } } }, _callee); }))(); }, [awaitableItems]); return { loading: loading, items: items }; }; var Combobox = function Combobox(_ref2) { var data = _ref2.data, getOptionLabel = _ref2.getOptionLabel, getOptionValue = _ref2.getOptionValue, inputValue = _ref2.inputValue, isLoading = _ref2.isLoading, _items = _ref2.items, menuPortalTarget = _ref2.menuPortalTarget, onChange = _ref2.onChange, onInputChange = _ref2.onInputChange, placeholder = _ref2.placeholder, value = _ref2.value, defaultOption = _ref2.defaultOption; var _useFieldContext = field.useFieldContext(), _useFieldContext2 = _slicedToArray(_useFieldContext, 2), _useFieldContext2$ = _useFieldContext2[0], disabled = _useFieldContext2$.disabled, invalid = _useFieldContext2$.invalid, inputId = _useFieldContext2[1].id; var _useAwaitableItems = useAwaitableItems(_items), items = _useAwaitableItems.items, loading = _useAwaitableItems.loading; var components = useReactSelectComponentsOverride(data); var styles = useReactSelectStylesOverride({ invalid: invalid }); var theme = useReactSelectThemeOverride(); var defaultFilter = ReactSelect.createFilter(); var getDefaultOptionValue = function getDefaultOptionValue() { if (!defaultOption) { return undefined; } var option = defaultOption.option; if (option && _typeof(option) === 'object' && 'value' in option) { return option.value; } return getOptionValue === null || getOptionValue === void 0 ? void 0 : getOptionValue(defaultOption.option); }; var filterOptions = function filterOptions(candidate, input) { var defaultOptionValue = getDefaultOptionValue(); if (input) { var isDefault = candidate.value === defaultOptionValue; return isDefault || defaultFilter(candidate, input); } return true; }; var getOptions = function getOptions() { if (defaultOption) { if (defaultOption.position === 'end') { return [].concat(_toConsumableArray(items), [defaultOption.option]); } return [defaultOption.option].concat(_toConsumableArray(items)); } return items; }; return /*#__PURE__*/jsxRuntime.jsx(ReactSelect__default["default"], { components: components, getOptionLabel: getOptionLabel, getOptionValue: getOptionValue, inputId: inputId, inputValue: inputValue, isDisabled: disabled, isLoading: isLoading !== null && isLoading !== void 0 ? isLoading : loading, menuPortalTarget: menuPortalTarget !== null && menuPortalTarget !== void 0 ? menuPortalTarget : isBrowser ? document.body : undefined, onChange: onChange, onInputChange: onInputChange, options: getOptions(), placeholder: placeholder, styles: styles, theme: theme, value: value, filterOption: defaultOption ? filterOptions : undefined }); }; exports.Combobox = Combobox; exports.useAwaitableItems = useAwaitableItems;