@wordpress/components
Version:
UI components for WordPress.
133 lines (115 loc) • 4.16 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = CustomSelectControl;
var _element = require("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _downshift = require("downshift");
var _classnames = _interopRequireDefault(require("classnames"));
var _icons = require("@wordpress/icons");
var _ = require("../");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const itemToString = item => item && 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 = ({
selectedItem
}, {
type,
changes,
props: {
items
}
}) => {
switch (type) {
case _downshift.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 _downshift.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;
}
};
function CustomSelectControl({
className,
hideLabelFromVision,
label,
options: items,
onChange: onSelectedItemChange,
value: _selectedItem
}) {
const {
getLabelProps,
getToggleButtonProps,
getMenuProps,
getItemProps,
isOpen,
highlightedIndex,
selectedItem
} = (0, _downshift.useSelect)({
initialSelectedItem: items[0],
items,
itemToString,
onSelectedItemChange,
selectedItem: _selectedItem,
stateReducer
});
const menuProps = getMenuProps({
className: 'components-custom-select-control__menu',
'aria-hidden': !isOpen
}); // We need this here, because the null active descendant is not
// fully ARIA compliant.
if (menuProps['aria-activedescendant'] && menuProps['aria-activedescendant'].slice(0, 'downshift-null'.length) === 'downshift-null') {
delete menuProps['aria-activedescendant'];
}
return (0, _element.createElement)("div", {
className: (0, _classnames.default)('components-custom-select-control', className)
}, hideLabelFromVision ? (0, _element.createElement)(_.VisuallyHidden, (0, _extends2.default)({
as: "label"
}, getLabelProps()), label) :
/* eslint-disable-next-line jsx-a11y/label-has-associated-control, jsx-a11y/label-has-for */
(0, _element.createElement)("label", getLabelProps({
className: 'components-custom-select-control__label'
}), label), (0, _element.createElement)(_.Button, 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',
isSmall: true
}), itemToString(selectedItem), (0, _element.createElement)(_icons.Icon, {
icon: _icons.chevronDown,
className: "components-custom-select-control__button-icon"
})), (0, _element.createElement)("ul", menuProps, isOpen && items.map((item, index) => // eslint-disable-next-line react/jsx-key
(0, _element.createElement)("li", getItemProps({
item,
index,
key: item.key,
className: (0, _classnames.default)(item.className, 'components-custom-select-control__item', {
'is-highlighted': index === highlightedIndex
}),
style: item.style
}), item.name, item === selectedItem && (0, _element.createElement)(_icons.Icon, {
icon: _icons.check,
className: "components-custom-select-control__item-icon"
})))));
}
//# sourceMappingURL=index.js.map