UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

423 lines (419 loc) • 14.5 kB
"use client"; const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs'); const require_children = require('../../utils/children.cjs'); const require_context = require('../../utils/context.cjs'); const require_dom = require('../../utils/dom.cjs'); const require_effect = require('../../utils/effect.cjs'); const require_ref = require('../../utils/ref.cjs'); const require_utils_index = require('../../utils/index.cjs'); const require_environment_provider = require('../../core/system/environment-provider.cjs'); const require_hooks_use_descendants_index = require('../use-descendants/index.cjs'); const require_use_disclosure = require('../use-disclosure/use-disclosure.cjs'); const require_use_popover = require('../../components/popover/use-popover.cjs'); let react = require("react"); react = require_rolldown_runtime.__toESM(react); let react_jsx_runtime = require("react/jsx-runtime"); react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime); let scroll_into_view_if_needed = require("scroll-into-view-if-needed"); scroll_into_view_if_needed = require_rolldown_runtime.__toESM(scroll_into_view_if_needed); //#region src/hooks/use-combobox/index.tsx const createComboboxItem = (children, { Group, Label, Option }) => { return require_children.getValidChildren(children).filter(({ type }) => require_children.isSomeElement(type, Option) || require_children.isSomeElement(type, Group)).map(({ type, props }) => { if (require_children.isSomeElement(type, Option)) return { ...props, label: props.children }; else { const validChildren = require_children.getValidChildren(props.children); const label = require_children.findChild(validChildren, Label); return { ...props, items: validChildren.filter(({ type: type$1 }) => require_children.isSomeElement(type$1, Option)).map(({ props: props$1 }) => ({ ...props$1, label: props$1.children })), label: label?.props.children ?? props.label }; } }); }; const createComboboxChildren = (items, { Empty, Group, Option }) => { return items.map((item, index) => { if ("data-empty" in item && Empty) { const { label,...rest } = item; return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Empty, { ...rest, children: label }, index); } else if ("items" in item) { const { items: items$1 = [], label,...rest } = item; return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Group, { label, ...rest, children: items$1.map(({ label: label$1,...rest$1 }, index$1) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Option, { ...rest$1, children: label$1 }, index$1)) }, index); } else { const { label,...rest } = item; return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Option, { ...rest, children: label }, index); } }); }; const { DescendantsContext: ComboboxDescendantsContext, useDescendant: useComboboxDescendant, useDescendantRegister: useComboboxDescendantRegister, useDescendants: useComboboxDescendants } = require_hooks_use_descendants_index.createDescendants(); const [ComboboxContext, useComboboxContext] = require_context.createContext({ name: "ComboboxContext" }); const [ComboboxGroupContext, useComboboxGroupContext] = require_context.createContext({ name: "ComboboxGroupContext" }); const useCombobox = (props = {}) => { const [popoverProps, { "aria-label": ariaLabelProp, "aria-labelledby": ariaLabelledbyProp, closeOnSelect: closeOnSelectProp = true, defaultOpen, disabled, initialFocusValue, open: openProp, openOnClick = true, openOnEnter = true, openOnSpace = true, readOnly, selectFocusRef, selectOnSpace = true, onChange: onChangeProp, onClose: onCloseProp, onOpen: onOpenProp,...rest }] = require_use_popover.usePopoverProps(props, [ "disabled", "open", "defaultOpen", "onOpen", "onClose", "openOnClick" ]); const { getWindow } = require_environment_provider.useEnvironment(); const interactive = !(readOnly || disabled); const triggerRef = (0, react.useRef)(null); const contentRef = (0, react.useRef)(null); const contentId = (0, react.useId)(); const descendants = useComboboxDescendants(); const { open, onClose, onOpen } = require_use_disclosure.useDisclosure({ defaultOpen, open: openProp, onClose: onCloseProp, onOpen: onOpenProp }); const activeDescendant = (0, react.useRef)(null); const mergedPopoverProps = (0, react.useMemo)(() => ({ autoFocus: false, matchWidth: true, openOnClick: false, ...popoverProps, disabled: !interactive, open, onClose, onOpen }), [ interactive, onClose, onOpen, open, popoverProps ]); const onSelect = (0, react.useCallback)((value, closeOnSelect = closeOnSelectProp) => { (selectFocusRef ?? triggerRef).current?.focus(); if (!interactive || (0, require_utils_index.utils_exports.isUndefined)(value)) return; onChangeProp?.(value); if (!closeOnSelect) return; onClose(); }, [ closeOnSelectProp, interactive, onChangeProp, onClose, selectFocusRef ]); const onScrollIntoView = (0, react.useCallback)((descendant, block = "start") => { if (!contentRef.current || !descendant) return; const style = getWindow()?.getComputedStyle(contentRef.current); const padding = block === "start" ? style?.paddingBlockStart : style?.paddingBlockEnd; const value = parseInt(padding ?? "0px"); (0, scroll_into_view_if_needed.default)(descendant.node, { behavior: (actions) => actions.forEach(({ el, top }) => { el.scrollTop = block === "start" ? top - value : top + value; }), block, boundary: contentRef.current, inline: "nearest", scrollMode: "if-needed" }); }, [getWindow]); const onActiveDescendant = (0, react.useCallback)((descendant) => { if (!triggerRef.current || !descendant || disabled) return; triggerRef.current.setAttribute("aria-activedescendant", descendant.id); activeDescendant.current = descendant; descendants.active(descendant); }, [descendants, disabled]); const onOpenWithActiveDescendant = (0, react.useCallback)((getFallbackDescendant, block = "start") => { onOpen(); setTimeout(() => { if (!initialFocusValue) { const descendant = getFallbackDescendant(); onActiveDescendant(descendant); onScrollIntoView(descendant, block); } else { const descendant = descendants.values().find(({ value }) => initialFocusValue === value) ?? getFallbackDescendant(); onActiveDescendant(descendant); onScrollIntoView(descendant, block); } }); }, [ descendants, initialFocusValue, onActiveDescendant, onOpen, onScrollIntoView ]); const onClick = (0, react.useCallback)((ev) => { if (disabled) return; ev.preventDefault(); if (!open) { if (openOnClick) onOpenWithActiveDescendant(descendants.enabledFirstValue); } else onClose(); }, [ descendants, disabled, onClose, onOpenWithActiveDescendant, open, openOnClick ]); const onKeyDown = (0, react.useCallback)((ev) => { if (disabled || require_dom.isComposing(ev)) return; require_dom.runKeyAction(ev, { ArrowDown: (ev$1) => { ev$1.preventDefault(); if (!open) onOpenWithActiveDescendant(descendants.enabledFirstValue); else if (activeDescendant.current) { const descendant = descendants.enabledNextValue(activeDescendant.current); onActiveDescendant(descendant); onScrollIntoView(descendant, descendant?.recurred ? "start" : "end"); } else { const descendant = descendants.enabledFirstValue(); onActiveDescendant(descendant); onScrollIntoView(descendant); } }, ArrowUp: (ev$1) => { ev$1.preventDefault(); if (!open) onOpenWithActiveDescendant(descendants.enabledLastValue, "end"); else if (activeDescendant.current) { const descendant = descendants.enabledPrevValue(activeDescendant.current); onActiveDescendant(descendant); onScrollIntoView(descendant, descendant?.recurred ? "end" : "start"); } else { const descendant = descendants.enabledLastValue(); onActiveDescendant(descendant); onScrollIntoView(descendant, "end"); } }, End: (ev$1) => { ev$1.preventDefault(); if (!open) return; const descendant = descendants.enabledLastValue(); onActiveDescendant(descendant); onScrollIntoView(descendant, "end"); }, Enter: (ev$1) => { if (!open) { if (!openOnEnter) return; ev$1.preventDefault(); onOpenWithActiveDescendant(descendants.enabledFirstValue); } else { if (!activeDescendant.current) return; ev$1.preventDefault(); const { closeOnSelect, value } = activeDescendant.current; onSelect(value, closeOnSelect); } }, Home: (ev$1) => { if (!open) return; ev$1.preventDefault(); const descendant = descendants.enabledFirstValue(); onActiveDescendant(descendant); onScrollIntoView(descendant); }, Space: (ev$1) => { if (!open) { if (!openOnSpace) return; ev$1.preventDefault(); onOpenWithActiveDescendant(descendants.enabledFirstValue); } else { if (!activeDescendant.current || !selectOnSpace) return; ev$1.preventDefault(); const { closeOnSelect, value } = activeDescendant.current; onSelect(value, closeOnSelect); } } }, { preventDefault: false }); }, [ disabled, open, onOpenWithActiveDescendant, descendants, onActiveDescendant, onScrollIntoView, openOnEnter, onSelect, openOnSpace, selectOnSpace ]); require_effect.useUpdateEffect(() => { if (open) return; activeDescendant.current = null; }, [open]); const getTriggerProps = (0, react.useCallback)(({ ref, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby,...props$1 } = {}) => ({ "aria-controls": open ? contentId : void 0, "aria-disabled": (0, require_utils_index.utils_exports.ariaAttr)(!interactive), "aria-expanded": open, "aria-haspopup": "listbox", "aria-label": ariaLabel || ariaLabelProp, "aria-labelledby": (0, require_utils_index.utils_exports.cx)(ariaLabelledby, ariaLabelledbyProp), "data-disabled": (0, require_utils_index.utils_exports.dataAttr)(disabled), "data-readonly": (0, require_utils_index.utils_exports.dataAttr)(readOnly), role: "combobox", tabIndex: interactive ? 0 : -1, ...rest, ...props$1, ref: require_ref.mergeRefs(ref, rest.ref, triggerRef), onClick: (0, require_utils_index.utils_exports.handlerAll)(props$1.onClick, rest.onClick, onClick), onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onKeyDown, rest.onKeyDown, onKeyDown) }), [ open, contentId, interactive, ariaLabelledbyProp, disabled, readOnly, ariaLabelProp, rest, onClick, onKeyDown ]); return { activeDescendant, descendants, interactive, open, getContentProps: (0, react.useCallback)(({ ref,...props$1 } = {}) => ({ id: contentId, role: "listbox", ...props$1, ref: require_ref.mergeRefs(ref, contentRef), onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onKeyDown) }), [contentId]), getSeparatorProps: (0, react.useCallback)((props$1) => ({ role: "separator", ...props$1 }), []), getTriggerProps, popoverProps: mergedPopoverProps, onActiveDescendant, onClose, onOpen, onOpenWithActiveDescendant, onScrollIntoView, onSelect }; }; const useComboboxGroup = ({ "aria-labelledby": ariaLabelledbyProp,...rest } = {}) => { const labelId = (0, react.useId)(); return { getGroupProps: (0, react.useCallback)(({ "aria-labelledby": ariaLabelledby,...props } = {}) => ({ "aria-labelledby": (0, require_utils_index.utils_exports.cx)(ariaLabelledbyProp, ariaLabelledby, labelId), role: "group", ...rest, ...props }), [ ariaLabelledbyProp, labelId, rest ]), getLabelProps: (0, react.useCallback)((props) => ({ id: labelId, role: "presentation", ...props }), [labelId]) }; }; const useComboboxItem = ({ id, "aria-disabled": ariaDisabled, "data-disabled": dataDisabled, closeOnSelect, disabled = false, selected = false, value,...rest } = {}) => { const uuid = (0, react.useId)(); const itemRef = (0, react.useRef)(null); const { onActiveDescendant, onClose, onSelect } = useComboboxContext(); id ??= uuid; const { descendants, register } = useComboboxDescendant({ id, closeOnSelect, disabled, value }); const onActive = (0, react.useCallback)(() => { if (disabled) return; onActiveDescendant(descendants.value(itemRef.current)); }, [ descendants, disabled, onActiveDescendant ]); const onClick = (0, react.useCallback)((ev) => { ev.preventDefault(); if (disabled) return; onSelect(value, closeOnSelect); }, [ closeOnSelect, disabled, onSelect, value ]); const getItemProps = (0, react.useCallback)(({ ref,...props } = {}) => ({ id, "aria-disabled": ariaDisabled ?? (0, require_utils_index.utils_exports.ariaAttr)(disabled), "aria-selected": selected, "data-disabled": dataDisabled ?? (0, require_utils_index.utils_exports.dataAttr)(disabled), "data-selected": (0, require_utils_index.utils_exports.dataAttr)(selected), "data-value": value, role: "option", tabIndex: -1, ...rest, ...props, ref: require_ref.mergeRefs(ref, rest.ref, itemRef, register), onClick: (0, require_utils_index.utils_exports.handlerAll)(props.onClick, rest.onClick, onClick), onMouseMove: (0, require_utils_index.utils_exports.handlerAll)(props.onMouseMove, rest.onMouseMove, onActive) }), [ id, ariaDisabled, disabled, selected, dataDisabled, value, rest, register, onClick, onActive ]); return { descendants, disabled, selected, getIndicatorProps: (0, react.useCallback)(({ style,...props } = {}) => ({ style: { opacity: selected ? 1 : 0, ...style }, ...props }), [selected]), getItemProps, onActiveDescendant, onClose }; }; //#endregion exports.ComboboxContext = ComboboxContext; exports.ComboboxDescendantsContext = ComboboxDescendantsContext; exports.ComboboxGroupContext = ComboboxGroupContext; exports.createComboboxChildren = createComboboxChildren; exports.createComboboxItem = createComboboxItem; exports.useCombobox = useCombobox; exports.useComboboxContext = useComboboxContext; exports.useComboboxDescendant = useComboboxDescendant; exports.useComboboxDescendantRegister = useComboboxDescendantRegister; exports.useComboboxDescendants = useComboboxDescendants; exports.useComboboxGroup = useComboboxGroup; exports.useComboboxGroupContext = useComboboxGroupContext; exports.useComboboxItem = useComboboxItem; //# sourceMappingURL=index.cjs.map