UNPKG

@wordpress/components

Version:
214 lines (190 loc) 7.4 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import { createElement } from "@wordpress/element"; // @ts-nocheck /** * External dependencies */ import { useSelect } from 'downshift'; import classnames from 'classnames'; /** * WordPress dependencies */ import { Icon, check } from '@wordpress/icons'; import { __, sprintf } from '@wordpress/i18n'; import { useCallback, useState } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ import { VisuallyHidden } from '../visually-hidden'; import { Select as SelectControlSelect } from '../select-control/styles/select-control-styles'; import SelectControlChevronDown from '../select-control/chevron-down'; import { InputBaseWithBackCompatMinWidth } from './styles'; import { StyledLabel } from '../base-control/styles/base-control-styles'; const itemToString = item => item === null || item === void 0 ? void 0 : item.name; // This is needed so that in Windows, where // the menu does not necessarily open on // key up/down, you can still switch between // options with the menu closed. const stateReducer = (_ref, _ref2) => { let { selectedItem } = _ref; let { type, changes, props: { items } } = _ref2; switch (type) { case useSelect.stateChangeTypes.ToggleButtonKeyDownArrowDown: // If we already have a selected item, try to select the next one, // without circular navigation. Otherwise, select the first item. return { selectedItem: items[selectedItem ? Math.min(items.indexOf(selectedItem) + 1, items.length - 1) : 0] }; case useSelect.stateChangeTypes.ToggleButtonKeyDownArrowUp: // If we already have a selected item, try to select the previous one, // without circular navigation. Otherwise, select the last item. return { selectedItem: items[selectedItem ? Math.max(items.indexOf(selectedItem) - 1, 0) : items.length - 1] }; default: return changes; } }; export default function CustomSelectControl(props) { var _menuProps$ariaActiv; const { /** Start opting into the larger default height that will become the default size in a future version. */ __next36pxDefaultSize = false, /** Start opting into the unconstrained width that will become the default in a future version. */ __nextUnconstrainedWidth = false, className, hideLabelFromVision, label, describedBy, options: items, onChange: onSelectedItemChange, /** @type {import('../select-control/types').SelectControlProps.size} */ size = 'default', value: _selectedItem, onMouseOver, onMouseOut, onFocus, onBlur, __experimentalShowSelectedHint = false } = props; const { getLabelProps, getToggleButtonProps, getMenuProps, getItemProps, isOpen, highlightedIndex, selectedItem } = useSelect({ initialSelectedItem: items[0], items, itemToString, onSelectedItemChange, ...(typeof _selectedItem !== 'undefined' && _selectedItem !== null ? { selectedItem: _selectedItem } : undefined), stateReducer }); const [isFocused, setIsFocused] = useState(false); function handleOnFocus(e) { setIsFocused(true); onFocus === null || onFocus === void 0 ? void 0 : onFocus(e); } function handleOnBlur(e) { setIsFocused(false); onBlur === null || onBlur === void 0 ? void 0 : onBlur(e); } if (!__nextUnconstrainedWidth) { deprecated('Constrained width styles for wp.components.CustomSelectControl', { since: '6.1', version: '6.4', hint: 'Set the `__nextUnconstrainedWidth` prop to true to start opting into the new styles, which will become the default in a future version' }); } function getDescribedBy() { if (describedBy) { return describedBy; } if (!selectedItem) { return __('No selection'); } // translators: %s: The selected option. return sprintf(__('Currently selected: %s'), selectedItem.name); } const menuProps = getMenuProps({ className: 'components-custom-select-control__menu', 'aria-hidden': !isOpen }); const onKeyDownHandler = useCallback(e => { var _menuProps$onKeyDown; e.stopPropagation(); menuProps === null || menuProps === void 0 ? void 0 : (_menuProps$onKeyDown = menuProps.onKeyDown) === null || _menuProps$onKeyDown === void 0 ? void 0 : _menuProps$onKeyDown.call(menuProps, e); }, [menuProps]); // We need this here, because the null active descendant is not fully ARIA compliant. if ((_menuProps$ariaActiv = menuProps['aria-activedescendant']) !== null && _menuProps$ariaActiv !== void 0 && _menuProps$ariaActiv.startsWith('downshift-null')) { delete menuProps['aria-activedescendant']; } return createElement("div", { className: classnames('components-custom-select-control', className) }, hideLabelFromVision ? createElement(VisuallyHidden, _extends({ as: "label" }, getLabelProps()), label) : /* eslint-disable-next-line jsx-a11y/label-has-associated-control, jsx-a11y/label-has-for */ createElement(StyledLabel, getLabelProps({ className: 'components-custom-select-control__label' }), label), createElement(InputBaseWithBackCompatMinWidth, { __next36pxDefaultSize: __next36pxDefaultSize, __nextUnconstrainedWidth: __nextUnconstrainedWidth, isFocused: isOpen || isFocused, __unstableInputWidth: __nextUnconstrainedWidth ? undefined : 'auto', labelPosition: __nextUnconstrainedWidth ? undefined : 'top', size: size, suffix: createElement(SelectControlChevronDown, null) }, createElement(SelectControlSelect, _extends({ onMouseOver: onMouseOver, onMouseOut: onMouseOut, as: "button", onFocus: handleOnFocus, onBlur: handleOnBlur, selectSize: size, __next36pxDefaultSize: __next36pxDefaultSize }, getToggleButtonProps({ // This is needed because some speech recognition software don't support `aria-labelledby`. 'aria-label': label, 'aria-labelledby': undefined, className: 'components-custom-select-control__button', describedBy: getDescribedBy() })), itemToString(selectedItem), __experimentalShowSelectedHint && selectedItem.__experimentalHint && createElement("span", { className: "components-custom-select-control__hint" }, selectedItem.__experimentalHint))), createElement("ul", _extends({}, menuProps, { onKeyDown: onKeyDownHandler }), isOpen && items.map((item, index) => // eslint-disable-next-line react/jsx-key createElement("li", getItemProps({ item, index, key: item.key, className: classnames(item.className, 'components-custom-select-control__item', { 'is-highlighted': index === highlightedIndex, 'has-hint': !!item.__experimentalHint, 'is-next-36px-default-size': __next36pxDefaultSize }), style: item.style }), item.name, item.__experimentalHint && createElement("span", { className: "components-custom-select-control__item-hint" }, item.__experimentalHint), item === selectedItem && createElement(Icon, { icon: check, className: "components-custom-select-control__item-icon" }))))); } export function StableCustomSelectControl(props) { return createElement(CustomSelectControl, _extends({}, props, { __experimentalShowSelectedHint: false })); } //# sourceMappingURL=index.js.map