@penaprieto/design-system
Version:
Multi-brand React design system with design tokens from Figma
96 lines (95 loc) • 4.61 kB
JavaScript
;
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;