@gechiui/components
Version:
UI components for GeChiUI.
156 lines (137 loc) • 4.97 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement } from "@gechiui/element";
/**
* External dependencies
*/
import { useSelect } from 'downshift';
import classnames from 'classnames';
/**
* GeChiUI dependencies
*/
import { Icon, check, chevronDown } from '@gechiui/icons';
import { __, sprintf } from '@gechiui/i18n';
import { useCallback } from '@gechiui/element';
/**
* Internal dependencies
*/
import { Button, VisuallyHidden } from '../';
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(_ref3) {
var _menuProps$ariaActiv;
let {
className,
hideLabelFromVision,
label,
describedBy,
options: items,
onChange: onSelectedItemChange,
value: _selectedItem
} = _ref3;
const {
getLabelProps,
getToggleButtonProps,
getMenuProps,
getItemProps,
isOpen,
highlightedIndex,
selectedItem
} = useSelect({
initialSelectedItem: items[0],
items,
itemToString,
onSelectedItemChange,
...(typeof _selectedItem !== 'undefined' && _selectedItem !== null ? {
selectedItem: _selectedItem
} : undefined),
stateReducer
});
function getDescribedBy() {
if (describedBy) {
return describedBy;
}
if (!selectedItem) {
return __('暂无选择');
} // translators: %s: The selected option.
return sprintf(__('当前选择:%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("label", getLabelProps({
className: 'components-custom-select-control__label'
}), label), 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,
describedBy: getDescribedBy()
}), itemToString(selectedItem), createElement(Icon, {
icon: chevronDown,
className: "components-custom-select-control__button-icon"
})), 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
}),
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"
})))));
}
//# sourceMappingURL=index.js.map