UNPKG

@ariakit/react-core

Version:

Ariakit React core

145 lines (142 loc) 4.7 kB
"use client"; import { SelectHeadingContext, SelectScopedContextProvider, useSelectContext } from "./QI6TYHPV.js"; import { useCompositeTypeahead } from "./WXLNFAIL.js"; import { isHidden } from "./HAX24JB7.js"; import { useComposite } from "./E7PWFDGB.js"; import { createElement, createHook, forwardRef } from "./ILRXHV7V.js"; import { useAttribute, useBooleanEvent, useEvent, useId, useMergeRefs, useTransactionState, useWrapElement } from "./K2XTQB3X.js"; // src/select/select-list.tsx import { isSelfTarget } from "@ariakit/core/utils/events"; import { invariant } from "@ariakit/core/utils/misc"; import { createContext, useContext, useEffect, useMemo, useState } from "react"; import { jsx } from "react/jsx-runtime"; var TagName = "div"; var SelectListContext = createContext(null); var useSelectList = createHook( function useSelectList2({ store, resetOnEscape = true, hideOnEnter = true, focusOnMove = true, composite, alwaysVisible, ...props }) { const context = useSelectContext(); store = store || context; invariant( store, process.env.NODE_ENV !== "production" && "SelectList must receive a `store` prop or be wrapped in a SelectProvider component." ); const id = useId(props.id); const value = store.useState("value"); const multiSelectable = Array.isArray(value); const [defaultValue, setDefaultValue] = useState(value); const mounted = store.useState("mounted"); useEffect(() => { if (mounted) return; setDefaultValue(value); }, [mounted, value]); resetOnEscape = resetOnEscape && !multiSelectable; const onKeyDownProp = props.onKeyDown; const resetOnEscapeProp = useBooleanEvent(resetOnEscape); const hideOnEnterProp = useBooleanEvent(hideOnEnter); const onKeyDown = useEvent((event) => { onKeyDownProp == null ? void 0 : onKeyDownProp(event); if (event.defaultPrevented) return; if (event.key === "Escape" && resetOnEscapeProp(event)) { store == null ? void 0 : store.setValue(defaultValue); } if (event.key === " " || event.key === "Enter") { if (isSelfTarget(event) && hideOnEnterProp(event)) { event.preventDefault(); store == null ? void 0 : store.hide(); } } }); const headingContext = useContext(SelectHeadingContext); const headingState = useState(); const [headingId, setHeadingId] = headingContext || headingState; const headingContextValue = useMemo( () => [headingId, setHeadingId], [headingId] ); const [childStore, setChildStore] = useState(null); const setStore = useContext(SelectListContext); useEffect(() => { if (!setStore) return; setStore(store); return () => setStore(null); }, [setStore, store]); props = useWrapElement( props, (element2) => /* @__PURE__ */ jsx(SelectScopedContextProvider, { value: store, children: /* @__PURE__ */ jsx(SelectListContext.Provider, { value: setChildStore, children: /* @__PURE__ */ jsx(SelectHeadingContext.Provider, { value: headingContextValue, children: element2 }) }) }), [store, headingContextValue] ); const hasCombobox = !!store.combobox; composite = composite != null ? composite : !hasCombobox && childStore !== store; const [element, setElement] = useTransactionState( composite ? store.setListElement : null ); const role = useAttribute(element, "role", props.role); const isCompositeRole = role === "listbox" || role === "menu" || role === "tree" || role === "grid"; const ariaMultiSelectable = composite || isCompositeRole ? multiSelectable || void 0 : void 0; const hidden = isHidden(mounted, props.hidden, alwaysVisible); const style = hidden ? { ...props.style, display: "none" } : props.style; if (composite) { props = { role: "listbox", "aria-multiselectable": ariaMultiSelectable, ...props }; } const labelId = store.useState( (state) => { var _a; return headingId || ((_a = state.labelElement) == null ? void 0 : _a.id); } ); props = { id, "aria-labelledby": labelId, hidden, ...props, ref: useMergeRefs(setElement, props.ref), style, onKeyDown }; props = useComposite({ store, ...props, composite }); props = useCompositeTypeahead({ store, typeahead: !hasCombobox, ...props }); return props; } ); var SelectList = forwardRef(function SelectList2(props) { const htmlProps = useSelectList(props); return createElement(TagName, htmlProps); }); export { useSelectList, SelectList };