UNPKG

@s-ui/react-molecule-dropdown-list

Version:

`MoleculeDropdownList` is a composition of DropdownOptions

100 lines (99 loc) 4.5 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; var _excluded = ["children", "onSelect", "position", "alwaysRender", "design", "size", "value", "visible", "onKeyDown", "aria-label"]; import { Children, forwardRef, useEffect, useRef, useState } from 'react'; import cx from 'classnames'; import PropTypes from 'prop-types'; import useDebounce from '@s-ui/react-hooks/lib/useDebounce'; import useMergeRefs from '@s-ui/react-hooks/lib/useMergeRefs'; import { BASE_CLASS, CLASS_HIDDEN, DEBOUNCE_TIME, DESIGNS, moleculeDropdownListSelectHandler, POSITIONS, SIZES } from './config.js'; import ExtendedChildren from './ExtendedChildren.js'; import { jsx as _jsx } from "react/jsx-runtime"; var MoleculeDropdownList = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) { var _cx; var children = _ref.children, onSelect = _ref.onSelect, _ref$position = _ref.position, position = _ref$position === void 0 ? POSITIONS.BOTTOM : _ref$position, _ref$alwaysRender = _ref.alwaysRender, alwaysRender = _ref$alwaysRender === void 0 ? true : _ref$alwaysRender, _ref$design = _ref.design, design = _ref$design === void 0 ? DESIGNS.SOLID : _ref$design, _ref$size = _ref.size, size = _ref$size === void 0 ? SIZES.SMALL : _ref$size, value = _ref.value, visible = _ref.visible, onKeyDown = _ref.onKeyDown, ariaLabel = _ref['aria-label'], props = _objectWithoutPropertiesLoose(_ref, _excluded); var refDropdownList = useRef(); var ref = useMergeRefs(refDropdownList, forwardedRef); var _useState = useState(''), typedWord = _useState[0], setTypedWord = _useState[1]; var debouncedTypedWord = useDebounce(typedWord, DEBOUNCE_TIME); var classNames = cx(BASE_CLASS, BASE_CLASS + "--position-" + position, BASE_CLASS + "--design-" + design, BASE_CLASS + "--size-" + size, (_cx = {}, _cx[CLASS_HIDDEN] = !visible, _cx)); var getFocusedOptionIndex = function getFocusedOptionIndex(options) { var currentElementFocused = document.activeElement; return Array.from(options).reduce(function (focusedOptionIndex, option, index) { if (option === currentElementFocused) focusedOptionIndex = index; return focusedOptionIndex; }, 0); }; var handleKeyDown = function handleKeyDown(event) { var key = event.key; var options = refDropdownList.current.children; var numOptions = options.length; var index = getFocusedOptionIndex(options); if (key === 'ArrowDown' || key === 'ArrowUp') { if (index >= 0 || index <= numOptions) { if (position === POSITIONS.TOP) { if (key === 'ArrowDown' && index > 0) options[index - 1].focus(); if (key === 'ArrowUp' && index < numOptions - 1) options[index + 1].focus(); } else { if (key === 'ArrowDown' && index < numOptions - 1) options[index + 1].focus(); if (key === 'ArrowUp' && index > 0) options[index - 1].focus(); } } } else { setTypedWord(function (value) { return value + key.toLowerCase(); }); var word = typedWord + key.toLowerCase(); var optionToFocusOn = Array.from(options).find(function (option, i) { return i >= index && option.innerText.toLowerCase().indexOf(word) === 0; }) || Array.from(options).find(function (option) { return option.innerText.toLowerCase().indexOf(word) === 0; }); optionToFocusOn && optionToFocusOn.focus(); } typeof onKeyDown === 'function' && onKeyDown(event); }; // When DEBOUNCE_TIME reset typed word useEffect(function () { setTypedWord(''); }, [debouncedTypedWord]); if (!visible && !alwaysRender) return null; return /*#__PURE__*/_jsx("ul", { ref: ref, tabIndex: 0, onKeyDown: handleKeyDown, className: classNames, role: "listbox", "aria-label": ariaLabel, children: Children.toArray(children).filter(Boolean).map(function (child, index) { return /*#__PURE__*/_jsx(ExtendedChildren, _extends({ value: value, onSelect: onSelect }, props, { children: child }), index); }) }); }); MoleculeDropdownList.displayName = 'MoleculeDropdownList'; export default MoleculeDropdownList; export { DESIGNS as moleculeDropdownListDesigns }; export { SIZES as moleculeDropdownListSizes }; export { POSITIONS as moleculeDropdownListPositions }; export { moleculeDropdownListSelectHandler };