@s-ui/react-molecule-dropdown-list
Version:
`MoleculeDropdownList` is a composition of DropdownOptions
100 lines (99 loc) • 4.5 kB
JavaScript
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 };