UNPKG

@penaprieto/design-system

Version:

Multi-brand React design system with design tokens from Figma

96 lines (95 loc) 4.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Dropdown = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); require("./Dropdown.css"); const Dropdown = ({ options, selectedId, defaultSelectedId, disabled = false, onChange, className = '', id, ...rest }) => { const isControlled = selectedId !== undefined; const [internalSelectedId, setInternalSelectedId] = (0, react_1.useState)(defaultSelectedId); const currentSelectedId = isControlled ? selectedId : internalSelectedId; const findInitialFocusedIndex = () => { const selectedIndex = options.findIndex((o) => o.id === (currentSelectedId !== null && currentSelectedId !== void 0 ? currentSelectedId : defaultSelectedId) && !o.disabled); if (selectedIndex >= 0) return selectedIndex; const firstEnabled = options.findIndex((o) => !o.disabled); return firstEnabled >= 0 ? firstEnabled : 0; }; const [focusedIndex, setFocusedIndex] = (0, react_1.useState)(() => findInitialFocusedIndex()); (0, react_1.useEffect)(() => { // Si cambian las opciones o el seleccionado desde fuera, recalculamos el foco inicial setFocusedIndex(findInitialFocusedIndex()); // eslint-disable-next-line react-hooks/exhaustive-deps }, [options.length, currentSelectedId]); const handleSelect = (option, index) => { if (disabled || option.disabled) return; if (!isControlled) { setInternalSelectedId(option.id); } setFocusedIndex(index); onChange === null || onChange === void 0 ? void 0 : onChange(option.id, option); }; const handleKeyDown = (event) => { var _a; if (disabled || options.length === 0) return; const key = event.key; const count = options.length; if (key === 'ArrowDown' || key === 'ArrowUp') { event.preventDefault(); const direction = key === 'ArrowDown' ? 1 : -1; let newIndex = focusedIndex; for (let i = 0; i < count; i++) { newIndex = (newIndex + direction + count) % count; if (!((_a = options[newIndex]) === null || _a === void 0 ? void 0 : _a.disabled)) break; } setFocusedIndex(newIndex); return; } if (key === 'Home') { event.preventDefault(); const firstEnabled = options.findIndex((o) => !o.disabled); if (firstEnabled >= 0) setFocusedIndex(firstEnabled); return; } if (key === 'End') { event.preventDefault(); const lastEnabledIndex = [...options].reverse().findIndex((o) => !o.disabled); if (lastEnabledIndex >= 0) setFocusedIndex(options.length - 1 - lastEnabledIndex); return; } if (key === 'Enter' || key === ' ') { event.preventDefault(); const option = options[focusedIndex]; if (option && !option.disabled) { handleSelect(option, focusedIndex); } } }; const rootClassName = [ 'ds-dropdown', disabled && 'ds-dropdown--disabled', className, ] .filter(Boolean) .join(' '); return ((0, jsx_runtime_1.jsx)("div", { id: id, className: rootClassName, "aria-disabled": disabled || undefined, ...rest, children: (0, jsx_runtime_1.jsx)("ul", { className: "ds-dropdown__list", role: "listbox", tabIndex: disabled || options.length === 0 ? -1 : 0, onKeyDown: handleKeyDown, children: options.map((option, index) => { const selected = option.id === currentSelectedId; const optionDisabled = disabled || option.disabled; const isFocused = index === focusedIndex; const optionClassName = [ 'ds-dropdown__option', selected && 'ds-dropdown__option--selected', optionDisabled && 'ds-dropdown__option--disabled', isFocused && !optionDisabled && 'ds-dropdown__option--focused', ] .filter(Boolean) .join(' '); return ((0, jsx_runtime_1.jsx)("li", { role: "option", "aria-selected": selected, "aria-disabled": optionDisabled || undefined, className: optionClassName, onClick: () => handleSelect(option, index), children: option.label }, option.id)); }) }) })); }; exports.Dropdown = Dropdown;