UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

69 lines (68 loc) 3.67 kB
'use client'; import { jsx as _jsx } from "react/jsx-runtime"; import * as React from 'react'; import { useSelect } from "../../hooks/index.js"; import { useForkRef } from "../../hooks/useForkRef/useForkRef.js"; import { Button } from "../Button/index.js"; import { block } from "../utils/cn.js"; import { filterDOMProps } from "../utils/filterDOMProps.js"; import { usePaletteGrid } from "./hooks.js"; import { getPaletteRows } from "./utils.js"; import "./Palette.css"; const b = block('palette'); export const Palette = React.forwardRef(function Palette(props, ref) { const { size = 'm', multiple = true, options = [], columns = 6, disabled, style, className, rowClassName, optionClassName, qa, onFocus, onBlur, } = props; const [focusedOptionIndex, setFocusedOptionIndex] = React.useState(undefined); const focusedOption = focusedOptionIndex === undefined ? undefined : options[focusedOptionIndex]; const innerRef = React.useRef(null); const handleRef = useForkRef(ref, innerRef); const { value, handleSelection } = useSelect({ value: props.value, defaultValue: props.defaultValue, multiple, onUpdate: props.onUpdate, }); const rows = React.useMemo(() => getPaletteRows(options, columns), [columns, options]); const focusOnOptionWithIndex = React.useCallback((index) => { if (!innerRef.current) return; const $options = Array.from(innerRef.current.querySelectorAll(`.${b('option')}`)); if (!$options[index]) return; $options[index].focus(); setFocusedOptionIndex(index); }, []); const tryToFocus = (newIndex) => { if (newIndex === focusedOptionIndex || newIndex < 0 || newIndex >= options.length) { return; } focusOnOptionWithIndex(newIndex); }; const gridProps = usePaletteGrid({ disabled, onFocus: (event) => { focusOnOptionWithIndex(0); onFocus?.(event); }, onBlur: (event) => { setFocusedOptionIndex(undefined); onBlur?.(event); }, whenFocused: focusedOptionIndex !== undefined && focusedOption ? { selectItem: () => handleSelection(focusedOption), nextItem: () => tryToFocus(focusedOptionIndex + 1), previousItem: () => tryToFocus(focusedOptionIndex - 1), nextRow: () => tryToFocus(focusedOptionIndex + columns), previousRow: () => tryToFocus(focusedOptionIndex - columns), } : undefined, }); return (_jsx("div", { ...filterDOMProps(props, { labelable: true }), ...gridProps, ref: handleRef, className: b({ size }, className), style: style, "data-qa": qa, children: rows.map((row, rowNumber) => (_jsx("div", { className: b('row', rowClassName), role: "row", children: row.map((option) => { const isSelected = Boolean(value.includes(option.value)); const focused = option === focusedOption; return (_jsx("div", { role: "gridcell", "aria-selected": focused ? 'true' : undefined, "aria-readonly": option.disabled, children: _jsx(Button, { className: b('option', optionClassName), tabIndex: -1, style: style, disabled: disabled || option.disabled, title: option.title, view: isSelected ? 'normal' : 'flat', selected: isSelected, value: option.value, size: size, onClick: () => handleSelection(option), children: _jsx(Button.Icon, { children: option.content ?? option.value }) }) }, option.value)); }) }, `row-${rowNumber}`))) })); }); Palette.displayName = 'Palette'; //# sourceMappingURL=Palette.js.map