UNPKG

@engie-group/fluid-design-system-react

Version:

Fluid Design System React

76 lines (73 loc) 4.82 kB
import { jsx, jsxs } from 'react/jsx-runtime'; import React__default, { useId, useMemo, useRef, useCallback } from 'react'; import { useStateControl, useInert } from '../../../utils/hook.js'; import { labelFromChildren } from '../../../utils/label-from-children.js'; import { Utils } from '../../../utils/util.js'; import { NJFormItem } from '../../form-item/NJFormItem.js'; import { NJMenuAnchor } from '../../menu/anchor/NJMenuAnchor.js'; import { NJMenuDropdown } from '../../menu/dropdown/NJMenuDropdown.js'; import { NJMenuGroup } from '../../menu/group/NJMenuGroup.js'; import '../../menu/item/NJMenuItem.js'; import { NJMenuRoot } from '../../menu/root/NJMenuRoot.js'; import { NJMenuSelection } from '../../menu/selection/NJMenuSelection.js'; import '../../menu/NJMenuContext.js'; import '../../menu/NJMenuItemContext.js'; import '../../menu/NJMenuSelectionContext.js'; const NJSelectRoot = React__default.forwardRef((props, forwardedRef) => { const { id: baseId, name, placeholder, form, isRequired, isDisabled, readOnly, iconName, value: controlledValue, initialValue, onChange, children, label, buttonDefaultValueLabel, listNavigationLabel, className, ...htmlProps } = props; const id = baseId ?? useId(); const items = React__default.Children.map(children, (child, index) => { if (React__default.isValidElement(child)) { return { label: child.props.label ?? labelFromChildren(child), value: child.props.value, index }; } return { label: labelFromChildren(child), value: undefined, index }; }); const optionsByIndex = new Map(items?.map((item) => [item.index, item])); const [value, setValue] = useStateControl(initialValue, controlledValue); const [isOpen, setIsOpen] = React__default.useState(false); const selectedOption = useMemo(() => Array.from(optionsByIndex.values()).find((option) => option.value === undefined ? option.label === value : option.value === value), [value, optionsByIndex]); const rootEl = useRef(null); const buttonEl = useRef(null); useInert(rootEl, isDisabled || readOnly); const inputClass = Utils.classNames(props.labelKind === 'static' ? 'nj-form-item--static' : null, 'nj-form-item--select', 'nj-form-item--custom-list', { ['nj-form-item--open']: isOpen }, className); const handleChange = useCallback((selectedIndexes) => { if (selectedIndexes.length === 0) { setValue(undefined); onChange?.(undefined); return; } const option = optionsByIndex.get(selectedIndexes[0]); if (!option) { setValue(undefined); onChange?.(undefined); return; } if (option.value === null) { setValue(null); onChange?.(null); return; } if (option.value === undefined) { const labelValue = option.label || ''; setValue(labelValue); onChange?.(labelValue); return; } setValue(option.value); onChange?.(option.value); }, [onChange, optionsByIndex]); if (initialValue && controlledValue) { throw new Error('NJSelect: initialValue and value cannot be used together, the component is either controlled or uncontrolled'); } return (jsx(NJMenuRoot, { floatingRole: "select", onOpen: (isOpen) => setIsOpen(isOpen), children: jsx(NJMenuSelection, { selectedIndexes: selectedOption ? [selectedOption.index] : [], onSelection: handleChange, children: jsxs(NJFormItem, { isMultiline: false, label: label, id: id, onChange: undefined, isSelect: true, className: inputClass, iconName: iconName ?? 'keyboard_arrow_down', iconClassName: "nj-form-item__icon", labelClassName: "nj-form-item__label", ref: rootEl, children: [jsx("input", { "data-child-name": "inputField", type: "text", id: id, ref: forwardedRef, name: name, value: selectedOption?.label || '', disabled: isDisabled, required: isRequired, "aria-hidden": true, placeholder: placeholder || ' ', form: form, tabIndex: -1, className: "nj-form-item__field", readOnly: true }), jsxs("div", { "data-child-name": "additionalContent", children: [jsx("p", { id: `${id}-instructions`, hidden: true, children: listNavigationLabel }), jsx(NJMenuAnchor, { children: jsx("button", { ...htmlProps, type: "button", "aria-label": `${label} - ${value || buttonDefaultValueLabel}`, className: "nj-form-item__custom-list-button", ref: buttonEl, "aria-haspopup": "listbox", "aria-describedby": `${id}-subscript ${id}-instructions` }) }), jsx(NJMenuDropdown, { scrollable: true, children: jsx(NJMenuGroup, { children: children }) })] })] }) }) })); }); NJSelectRoot.displayName = 'NJSelectRoot'; export { NJSelectRoot };