@bazza-ui/react 0.0.0-snapshot-20260205122957

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/internal/popup-menu/index.ts","../../../src/internal/popup-menu/contexts/component-name-context.ts","../../../src/internal/popup-menu/contexts/focus-owner-context.ts","../../../src/internal/popup-menu/contexts/open-chain-context.ts","../../../src/internal/popup-menu/contexts/popup-menu-context.ts","../../../src/internal/popup-menu/contexts/popup-surface-id-context.ts","../../../src/internal/popup-menu/contexts/submenu-context.ts","../../../src/internal/popup-menu/hooks/use-aim-guard.tsx","../../../src/internal/popup-menu/store/FocusOwnerStore.ts","../../../src/internal/popup-menu/store/OpenChainStore.ts","../../../src/internal/popup-menu/utils/aim-guard.ts","../../../src/internal/popup-menu/utils/use-mouse-trail.ts","../../../src/internal/popup-menu/hooks/use-popup-menu-root.ts","../../../src/utils/events/reason-parts.ts","../../../src/utils/events/create-event-details.ts","../../../src/internal/listbox/contexts/group-context.ts","../../../src/internal/listbox/contexts/item-context.ts","../../../src/internal/listbox/contexts/listbox-context.ts","../../../src/internal/listbox/contexts/row-width-context.ts","../../../src/internal/listbox/contexts/surface-context.ts","../../../src/internal/listbox/hooks/use-listbox-item.ts","../../../src/internal/listbox/utils/normalize.ts","../../../src/internal/listbox/hooks/use-listbox-keyboard.ts","../../../src/internal/listbox/hooks/use-sticky-row-width.ts","../../../src/internal/listbox/store/ListboxStore.ts","../../../src/internal/listbox/utils/command-score.ts","../../../src/internal/popup-menu/components/arrow/arrow.data-attrs.ts","../../../src/internal/popup-menu/components/arrow/arrow.tsx","../../../src/internal/popup-menu/components/backdrop/backdrop.data-attrs.ts","../../../src/internal/popup-menu/components/backdrop/backdrop.tsx","../../../src/internal/popup-menu/components/popup/popup.data-attrs.ts","../../../src/internal/popup-menu/components/popup/popup.tsx","../../../src/combobox/contexts/combobox-context.ts","../../../src/internal/popup-menu/components/portal/portal.tsx","../../../src/internal/popup-menu/components/positioner/positioner.css-vars.ts","../../../src/internal/popup-menu/components/positioner/positioner.data-attrs.ts","../../../src/internal/popup-menu/components/positioner/positioner.tsx","../../../src/internal/popup-menu/components/providers.tsx","../../../src/internal/popup-menu/hooks/use-popup-menu-item.ts","../../../src/internal/popup-menu/hooks/use-popup-menu-keyboard.ts","../../../src/internal/popup-menu/components/icon/icon.data-attrs.ts","../../../src/internal/popup-menu/components/icon/icon.tsx","../../../src/utils/resolve-value-label.ts","../../../src/internal/popup-menu/components/empty/empty.tsx","../../../src/internal/popup-menu/components/input/input.tsx","../../../src/internal/popup-menu/components/list/list.tsx","../../../src/internal/popup-menu/components/list/list.css-vars.ts","../../../src/internal/popup-menu/components/list/list.data-attrs.ts","../../../src/internal/popup-menu/components/scroll-arrow/scroll-arrow.data-attrs.ts","../../../src/internal/popup-menu/components/scroll-arrow/scroll-arrow.tsx","../../../src/internal/popup-menu/components/surface/surface.tsx","../../../src/internal/popup-menu/components/checkbox-item/checkbox-item.tsx","../../../src/internal/popup-menu/components/checkbox-item/checkbox-item.data-attrs.ts","../../../src/internal/popup-menu/components/checkbox-item/checkbox-item-context.ts","../../../src/internal/popup-menu/components/checkbox-item/checkbox-item-indicator.tsx","../../../src/internal/popup-menu/components/item/item.tsx","../../../src/internal/popup-menu/components/item/item.data-attrs.ts","../../../src/internal/popup-menu/components/radio-group/radio-group.tsx","../../../src/internal/popup-menu/components/radio-group/radio-group.data-attrs.ts","../../../src/internal/popup-menu/components/radio-group/radio-group-context.ts","../../../src/internal/popup-menu/components/radio-group/radio-group-value.tsx","../../../src/internal/popup-menu/components/radio-item/radio-item.tsx","../../../src/internal/popup-menu/components/radio-item/radio-item.data-attrs.ts","../../../src/internal/popup-menu/components/radio-item/radio-item-context.ts","../../../src/internal/popup-menu/components/radio-item/radio-item-indicator.tsx","../../../src/internal/popup-menu/components/group/group.tsx","../../../src/internal/popup-menu/components/group-label/group-label.tsx","../../../src/internal/popup-menu/components/separator/separator.tsx","../../../src/internal/popup-menu/components/shortcut/shortcut.tsx","../../../src/internal/popup-menu/components/shortcut/shortcut.data-attrs.ts","../../../src/internal/popup-menu/components/submenu-root/submenu-root.tsx","../../../src/internal/popup-menu/components/submenu-trigger/submenu-trigger.tsx","../../../src/internal/popup-menu/components/submenu-trigger/submenu-trigger-indicator.tsx","../../../src/internal/popup-menu/components/submenu-trigger/submenu-trigger.data-attrs.ts","../../../src/internal/popup-menu/deep-search/async-coordinator.tsx","../../../src/internal/popup-menu/deep-search/context.ts","../../../src/internal/popup-menu/deep-search/data-list.tsx","../../../src/internal/popup-menu/deep-search/types.ts","../../../src/internal/popup-menu/deep-search/utils.ts","../../../src/internal/popup-menu/deep-search/data-surface.tsx"],"sourcesContent":["// ============================================================================\n// Internal Popup Menu Package\n// ============================================================================\n// Shared behavior for popup-based menus with submenus.\n// Used by: DropdownMenu, ContextMenu\n\n// Contexts\nexport type { ComponentName } from './contexts/component-name-context.js'\nexport {\n ComponentNameContext,\n getSlotAttribute,\n useComponentName,\n useMaybeComponentName,\n} from './contexts/component-name-context.js'\nexport {\n FocusOwnerContext,\n useFocusOwner,\n useMaybeFocusOwner,\n} from './contexts/focus-owner-context.js'\nexport {\n OpenChainContext,\n useMaybeOpenChain,\n useOpenChain,\n} from './contexts/open-chain-context.js'\nexport type {\n PopupMenuContextValue,\n VirtualAnchor,\n VirtualItem,\n VirtualizationConfig,\n} from './contexts/popup-menu-context.js'\n// Core Context\nexport {\n PopupMenuContext,\n useMaybePopupMenuContext,\n usePopupMenuContext,\n} from './contexts/popup-menu-context.js'\nexport {\n PopupSurfaceIdContext,\n usePopupSurfaceId,\n} from './contexts/popup-surface-id-context.js'\nexport type { SubmenuContextValue } from './contexts/submenu-context.js'\nexport {\n SubmenuContext,\n useMaybeSubmenuContext,\n useSubmenuContext,\n} from './contexts/submenu-context.js'\nexport type {\n AimGuardContextValue,\n AimGuardProviderProps,\n} from './hooks/use-aim-guard.js'\n// Hooks\nexport {\n AimGuardCtx,\n AimGuardProvider,\n useAimGuard,\n} from './hooks/use-aim-guard.js'\nexport type { FocusOwnerState } from './store/FocusOwnerStore.js'\n// Stores\nexport { FocusOwnerStore } from './store/FocusOwnerStore.js'\nexport type { OpenChainState } from './store/OpenChainStore.js'\nexport { OpenChainStore } from './store/OpenChainStore.js'\nexport type { AnchorSide } from './utils/aim-guard.js'\n// Utils\nexport {\n getSmoothedHeading,\n resolveAnchorSide,\n willHitSubmenu,\n} from './utils/aim-guard.js'\n\nexport { useMouseTrail } from './utils/use-mouse-trail.js'\n\n// ============================================================================\n// Shared Hooks\n// ============================================================================\n\nexport type {\n UsePopupMenuRootParams,\n UsePopupMenuRootReturn,\n} from './hooks/use-popup-menu-root.js'\nexport { usePopupMenuRoot } from './hooks/use-popup-menu-root.js'\n\n// ============================================================================\n// Shared Components\n// ============================================================================\n\nexport { PopupMenuArrowDataAttributes } from './components/arrow/arrow.data-attrs.js'\nexport type { PopupMenuArrowProps } from './components/arrow/arrow.js'\nexport { PopupMenuArrow } from './components/arrow/arrow.js'\nexport { PopupMenuBackdropDataAttributes } from './components/backdrop/backdrop.data-attrs.js'\nexport type { PopupMenuBackdropProps } from './components/backdrop/backdrop.js'\nexport { PopupMenuBackdrop } from './components/backdrop/backdrop.js'\nexport { PopupMenuPopupDataAttributes } from './components/popup/popup.data-attrs.js'\nexport type {\n PopupMenuPopupProps,\n PopupMenuPopupState,\n} from './components/popup/popup.js'\nexport { PopupMenuPopup } from './components/popup/popup.js'\nexport type { PopupMenuPortalProps } from './components/portal/portal.js'\nexport { PopupMenuPortal } from './components/portal/portal.js'\nexport { PopupMenuPositionerCssVars } from './components/positioner/positioner.css-vars.js'\nexport { PopupMenuPositionerDataAttributes } from './components/positioner/positioner.data-attrs.js'\nexport type {\n PopupMenuPositionerAlign,\n PopupMenuPositionerProps,\n} from './components/positioner/positioner.js'\nexport { PopupMenuPositioner } from './components/positioner/positioner.js'\nexport type { PopupMenuProvidersProps } from './components/providers.js'\nexport { PopupMenuProviders } from './components/providers.js'\n\n// ============================================================================\n// Item Hooks\n// ============================================================================\n\nexport type {\n UsePopupMenuItemParams,\n UsePopupMenuItemReturn,\n} from './hooks/use-popup-menu-item.js'\nexport { usePopupMenuItem } from './hooks/use-popup-menu-item.js'\nexport type {\n UsePopupMenuKeyboardParams,\n UsePopupMenuKeyboardReturn,\n} from './hooks/use-popup-menu-keyboard.js'\nexport { usePopupMenuKeyboard } from './hooks/use-popup-menu-keyboard.js'\n\n// ============================================================================\n// Trigger Components\n// ============================================================================\n\nexport { PopupMenuIconDataAttributes } from './components/icon/icon.data-attrs.js'\nexport type {\n PopupMenuIconProps,\n PopupMenuIconState,\n} from './components/icon/icon.js'\nexport { PopupMenuIcon } from './components/icon/icon.js'\n\n// ============================================================================\n// Content Components\n// ============================================================================\n\nexport type {\n PopupMenuEmptyProps,\n PopupMenuEmptyState,\n} from './components/empty/empty.js'\nexport { PopupMenuEmpty } from './components/empty/empty.js'\nexport type {\n PopupMenuInputProps,\n PopupMenuInputState,\n} from './components/input/input.js'\nexport { PopupMenuInput } from './components/input/input.js'\nexport type {\n PopupMenuListChildrenState,\n PopupMenuListProps,\n PopupMenuListState,\n} from './components/list/list.js'\nexport {\n PopupMenuList,\n PopupMenuListCssVars,\n PopupMenuListDataAttributes,\n} from './components/list/list.js'\nexport { PopupMenuScrollArrowDataAttributes } from './components/scroll-arrow/scroll-arrow.data-attrs.js'\nexport type {\n PopupMenuScrollArrowProps,\n PopupMenuScrollArrowState,\n PopupMenuScrollDownArrowProps,\n PopupMenuScrollUpArrowProps,\n} from './components/scroll-arrow/scroll-arrow.js'\nexport {\n PopupMenuScrollArrow,\n PopupMenuScrollDownArrow,\n PopupMenuScrollUpArrow,\n} from './components/scroll-arrow/scroll-arrow.js'\nexport type {\n PopupMenuSurfaceProps,\n PopupMenuSurfaceState,\n} from './components/surface/surface.js'\nexport { PopupMenuSurface } from './components/surface/surface.js'\n\n// ============================================================================\n// Item Components\n// ============================================================================\n\nexport type {\n PopupMenuCheckboxItemProps,\n PopupMenuCheckboxItemState,\n} from './components/checkbox-item/checkbox-item.js'\nexport {\n PopupMenuCheckboxItem,\n PopupMenuCheckboxItemDataAttributes,\n} from './components/checkbox-item/checkbox-item.js'\nexport type { CheckboxItemContextValue } from './components/checkbox-item/checkbox-item-context.js'\nexport {\n CheckboxItemContext,\n useCheckboxItemContext,\n} from './components/checkbox-item/checkbox-item-context.js'\nexport type {\n PopupMenuCheckboxItemIndicatorProps,\n PopupMenuCheckboxItemIndicatorState,\n} from './components/checkbox-item/checkbox-item-indicator.js'\nexport { PopupMenuCheckboxItemIndicator } from './components/checkbox-item/checkbox-item-indicator.js'\nexport type {\n PopupMenuItemProps,\n PopupMenuItemState,\n} from './components/item/item.js'\nexport {\n PopupMenuItem,\n PopupMenuItemDataAttributes,\n} from './components/item/item.js'\nexport type {\n PopupMenuRadioGroupProps,\n PopupMenuRadioGroupState,\n} from './components/radio-group/radio-group.js'\nexport {\n PopupMenuRadioGroup,\n PopupMenuRadioGroupDataAttributes,\n} from './components/radio-group/radio-group.js'\nexport type { RadioGroupContextValue } from './components/radio-group/radio-group-context.js'\nexport {\n RadioGroupContext,\n useRadioGroupContext,\n} from './components/radio-group/radio-group-context.js'\nexport type { PopupMenuRadioGroupValueProps } from './components/radio-group/radio-group-value.js'\nexport { PopupMenuRadioGroupValue } from './components/radio-group/radio-group-value.js'\nexport type {\n PopupMenuRadioItemProps,\n PopupMenuRadioItemState,\n} from './components/radio-item/radio-item.js'\nexport {\n PopupMenuRadioItem,\n PopupMenuRadioItemDataAttributes,\n} from './components/radio-item/radio-item.js'\nexport type { RadioItemContextValue } from './components/radio-item/radio-item-context.js'\nexport {\n RadioItemContext,\n useRadioItemContext,\n} from './components/radio-item/radio-item-context.js'\nexport type {\n PopupMenuRadioItemIndicatorProps,\n PopupMenuRadioItemIndicatorState,\n} from './components/radio-item/radio-item-indicator.js'\nexport { PopupMenuRadioItemIndicator } from './components/radio-item/radio-item-indicator.js'\n\n// ============================================================================\n// Structure Components\n// ============================================================================\n\nexport type {\n PopupMenuGroupProps,\n PopupMenuGroupState,\n} from './components/group/group.js'\nexport { PopupMenuGroup } from './components/group/group.js'\nexport type {\n PopupMenuGroupLabelProps,\n PopupMenuGroupLabelState,\n} from './components/group-label/group-label.js'\nexport { PopupMenuGroupLabel } from './components/group-label/group-label.js'\nexport type {\n PopupMenuSeparatorProps,\n PopupMenuSeparatorState,\n} from './components/separator/separator.js'\nexport { PopupMenuSeparator } from './components/separator/separator.js'\nexport type {\n PopupMenuShortcutProps,\n PopupMenuShortcutState,\n} from './components/shortcut/shortcut.js'\nexport {\n PopupMenuShortcut,\n PopupMenuShortcutDataAttributes,\n} from './components/shortcut/shortcut.js'\n\n// ============================================================================\n// Submenu Components\n// ============================================================================\n\nexport type { PopupMenuSubmenuRootProps } from './components/submenu-root/submenu-root.js'\nexport { PopupMenuSubmenuRoot } from './components/submenu-root/submenu-root.js'\nexport type {\n PopupMenuSubmenuTriggerProps,\n PopupMenuSubmenuTriggerState,\n} from './components/submenu-trigger/submenu-trigger.js'\nexport { PopupMenuSubmenuTrigger } from './components/submenu-trigger/submenu-trigger.js'\nexport type {\n PopupMenuSubmenuTriggerIndicatorProps,\n PopupMenuSubmenuTriggerIndicatorState,\n} from './components/submenu-trigger/submenu-trigger-indicator.js'\nexport {\n PopupMenuSubmenuTriggerDataAttributes,\n PopupMenuSubmenuTriggerIndicator,\n} from './components/submenu-trigger/submenu-trigger-indicator.js'\n\n// ============================================================================\n// Deep Search (Data-First API)\n// ============================================================================\n\n// Async Coordinator\nexport type {\n AsyncMenuCoordinatorValue,\n AsyncMenuState,\n} from './deep-search/async-coordinator.js'\nexport {\n AsyncMenuCoordinatorContext,\n AsyncMenuCoordinatorProvider,\n useAsyncMenuCoordinator,\n useMaybeAsyncMenuCoordinator,\n} from './deep-search/async-coordinator.js'\n// Context\nexport type {\n DataSurfaceContextValue,\n RenderNodeFn,\n} from './deep-search/context.js'\nexport {\n DataSurfaceContext,\n useDataSurfaceContext,\n useMaybeDataSurfaceContext,\n} from './deep-search/context.js'\nexport type { PopupMenuDataInputProps } from './deep-search/data-input.js'\nexport { PopupMenuDataInput } from './deep-search/data-input.js'\nexport type { PopupMenuDataListProps } from './deep-search/data-list.js'\nexport { PopupMenuDataList } from './deep-search/data-list.js'\n// Components\nexport type { PopupMenuDataSurfaceProps } from './deep-search/data-surface.js'\nexport { PopupMenuDataSurface } from './deep-search/data-surface.js'\n// Types\nexport type {\n // Async types\n AsyncLoaderConfig,\n AsyncLoaderResult,\n AsyncNodesConfig,\n AsyncRenderState,\n AsyncState,\n // ID generation types\n BreadcrumbNode,\n // Node types\n CheckboxItemDef,\n CheckboxItemRenderParams,\n CheckboxItemRenderProps,\n DataListChildrenState,\n DataListProps,\n DataSurfaceProps,\n DeepSearchConfig,\n DisplayGroupNode,\n DisplayNode,\n DisplayRadioGroupNode,\n DisplayRowNode,\n DisplaySeparatorNode,\n GroupBehavior,\n GroupDef,\n GroupRenderContext,\n GroupRenderParams,\n ItemDef,\n ItemRenderParams,\n ItemRenderProps,\n LoaderComponentProps,\n NodeDef,\n QueryAsyncNodesConfig,\n QueryDependentLoaderConfig,\n RadioGroupBehavior,\n RadioGroupDef,\n RadioGroupRenderParams,\n RadioGroupRenderProps,\n RadioItemDef,\n RadioItemRenderParams,\n RadioItemRenderProps,\n RowRenderContext,\n ScoredNode,\n SeparatorDef,\n SeparatorRenderParams,\n StaticAsyncNodesConfig,\n StaticLoaderConfig,\n SubmenuDef,\n SubmenuRenderParams,\n SubmenuRenderProps,\n} from './deep-search/types.js'\nexport {\n defineRadioGroup,\n isDisplayGroupNode,\n isDisplayRadioGroupNode,\n isDisplayRowNode,\n isDisplaySeparatorNode,\n} from './deep-search/types.js'\n\n// Utilities\nexport type {\n AsyncSubmenuInfo,\n FilterNodesOptions,\n} from './deep-search/utils.js'\nexport {\n buildDisplayRowNodes,\n collectAsyncSubmenus,\n deduplicateNodes,\n defaultGetQualifiedRowId,\n filterNodes,\n flattenNodes,\n getBrowseNodesFlatten,\n getBrowseNodesPreserve,\n getFirstNavigableId,\n getNavigableIds,\n isCheckboxItemDef,\n isGroupDef,\n isItemDef,\n isRadioGroupDef,\n isRadioItemDef,\n isSeparatorDef,\n isSubmenuDef,\n mergeAsyncNodesIntoTree,\n mergeSubmenuNodes,\n partitionByKind,\n scoreNodes,\n shouldIncludeInDeepSearch,\n shouldLoadEagerly,\n sortByScore,\n} from './deep-search/utils.js'\n","'use client'\n\nimport * as React from 'react'\n\n/**\n * Component name used for generating bazzaui-* slot attributes.\n * E.g., 'dropdown-menu', 'context-menu', 'select', 'combobox'\n */\nexport type ComponentName =\n | 'dropdown-menu'\n | 'context-menu'\n | 'select'\n | 'combobox'\n\nexport const ComponentNameContext = React.createContext<ComponentName | null>(\n null,\n)\n\n/**\n * Returns the component name from context.\n * Throws if used outside of a component that provides the context.\n */\nexport function useComponentName(): ComponentName {\n const context = React.useContext(ComponentNameContext)\n if (context === null) {\n throw new Error(\n 'useComponentName must be used within a ComponentNameContext.Provider',\n )\n }\n return context\n}\n\n/**\n * Returns the component name from context, or null if not available.\n * Useful for internal components that may be used outside the popup-menu context.\n */\nexport function useMaybeComponentName(): ComponentName | null {\n return React.useContext(ComponentNameContext)\n}\n\n/**\n * Helper to generate a bazzaui slot attribute value.\n * @param componentName The component name (e.g., 'dropdown-menu')\n * @param partName The part name (e.g., 'trigger', 'item')\n * @returns The slot attribute value (e.g., 'bazzaui-dropdown-menu-trigger')\n */\nexport function getSlotAttribute(\n componentName: ComponentName | null,\n partName: string,\n): string | undefined {\n if (!componentName) return undefined\n return `bazzaui-${componentName}-${partName}`\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { FocusOwnerStore } from '../store/FocusOwnerStore.js'\n\n// ============================================================================\n// Focus Owner Context\n// ============================================================================\n\nconst FocusOwnerContext = React.createContext<FocusOwnerStore | null>(null)\n\nexport function useFocusOwner(): FocusOwnerStore {\n const context = React.useContext(FocusOwnerContext)\n if (!context) {\n throw new Error(\n 'FocusOwner components must be used within a FocusOwnerProvider',\n )\n }\n return context\n}\n\nexport function useMaybeFocusOwner(): FocusOwnerStore | null {\n return React.useContext(FocusOwnerContext)\n}\n\nexport { FocusOwnerContext }\n","'use client'\n\nimport * as React from 'react'\nimport type { OpenChainStore } from '../store/OpenChainStore.js'\n\n// ============================================================================\n// Open Chain Context\n// ============================================================================\n\nconst OpenChainContext = React.createContext<OpenChainStore | null>(null)\n\nexport function useOpenChain(): OpenChainStore {\n const context = React.useContext(OpenChainContext)\n if (!context) {\n throw new Error(\n 'OpenChain components must be used within an OpenChainProvider',\n )\n }\n return context\n}\n\nexport function useMaybeOpenChain(): OpenChainStore | null {\n return React.useContext(OpenChainContext)\n}\n\nexport { OpenChainContext }\n","'use client'\n\nimport * as React from 'react'\nimport type {\n ListboxStore,\n VirtualItem,\n} from '../../listbox/store/ListboxStore.js'\nimport type { GetQualifiedRowIdFn } from '../deep-search/types.js'\nimport type {\n HighlightChangeEventDetails,\n PopupMenuOpenChangeReason,\n} from '../events.js'\n\n// ============================================================================\n// Popup Menu Context\n// ============================================================================\n// Shared root-level context for popup menus (DropdownMenu, ContextMenu).\n// Provides core menu functionality to all child components.\n\n/**\n * Virtual anchor for positioning the menu at a specific point.\n * Used by ContextMenu to position at cursor location.\n */\nexport interface VirtualAnchor {\n getBoundingClientRect(): DOMRect\n}\n\n/**\n * Virtualization configuration passed from Root/Submenu to Surface.\n */\nexport interface VirtualizationConfig {\n /** Whether virtualization mode is enabled */\n virtualized: boolean\n /** Pre-registered items for virtualization */\n items: VirtualItem[]\n /**\n * Callback when highlighted item changes (for scroll sync).\n * The third parameter contains event details including the reason for the change.\n */\n onHighlightChange?: (\n id: string | null,\n index: number,\n eventDetails: HighlightChangeEventDetails,\n ) => void\n}\n\n/**\n * Shared context value for popup menus.\n * Both DropdownMenu.Root and ContextMenu.Root provide this context.\n */\nexport interface PopupMenuContextValue {\n /** The Listbox store instance */\n store: ListboxStore\n /** Nesting depth: 0 = root menu, 1+ = submenu */\n depth: number\n /** Close the entire menu tree (deepest submenu to root, sequentially) */\n closeAll: (reason?: PopupMenuOpenChangeReason, event?: Event) => void\n /** Register a surface (submenu) for closeAll tracking. Returns unregister function. */\n registerSurface: (\n depth: number,\n setOpen: (open: boolean) => void,\n ) => () => void\n /** Virtualization configuration (if enabled) */\n virtualization?: VirtualizationConfig\n /**\n * Virtual anchor for positioning.\n * Used by ContextMenu to position at cursor location.\n * DropdownMenu uses the Popover's anchor (trigger button) instead.\n */\n virtualAnchor?: VirtualAnchor\n /**\n * Type of menu for positioning logic.\n * - 'dropdown': positions relative to trigger button\n * - 'context': positions at cursor with fixed positioning\n */\n menuType: 'dropdown' | 'context'\n /**\n * When to close the menu on outside interactions.\n * - 'pointerdown': Close immediately when pointer is pressed outside (default)\n * - 'click': Close when a full click (pointerdown + pointerup) occurs outside\n * @default 'pointerdown'\n */\n closeOnOutsidePress: 'click' | 'pointerdown'\n /**\n * Function to generate qualified unique IDs for rows.\n * Defined once at the root level and applied to all surfaces (root and submenus).\n * If not provided, uses the default implementation.\n */\n getQualifiedRowId?: GetQualifiedRowIdFn\n}\n\nconst PopupMenuContext = React.createContext<PopupMenuContextValue | null>(null)\n\n/**\n * Hook to access the popup menu context.\n * Throws if used outside a popup menu.\n */\nexport function usePopupMenuContext(): PopupMenuContextValue {\n const context = React.useContext(PopupMenuContext)\n if (!context) {\n throw new Error(\n 'PopupMenu components must be used within a PopupMenu.Root or ContextMenu.Root',\n )\n }\n return context\n}\n\n/**\n * Hook to optionally access the popup menu context.\n * Returns null if used outside a popup menu.\n */\nexport function useMaybePopupMenuContext(): PopupMenuContextValue | null {\n return React.useContext(PopupMenuContext)\n}\n\nexport { PopupMenuContext }\n\n// Re-export for convenience\nexport type { VirtualItem }\n","'use client'\n\nimport * as React from 'react'\n\n// ============================================================================\n// Popup Surface ID Context\n// ============================================================================\n\n/**\n * Context for passing surfaceId from Popup to Surface.\n * This ensures Popup and Surface share the same ID for data attribute tracking.\n *\n * For root menus, Popup generates the ID and provides it via this context.\n * For submenus, the ID comes from SubmenuContext.childSurfaceId instead.\n */\nconst PopupSurfaceIdContext = React.createContext<string | null>(null)\n\nexport function usePopupSurfaceId(): string | null {\n return React.useContext(PopupSurfaceIdContext)\n}\n\nexport { PopupSurfaceIdContext }\n","'use client'\n\nimport * as React from 'react'\n\nexport interface SubmenuContextValue {\n /** Whether the submenu is open */\n open: boolean\n /** Set the submenu open state */\n setOpen: (open: boolean) => void\n /** Reference to the trigger element */\n triggerRef: React.RefObject<HTMLElement | null>\n /** Reference to the submenu content element (for aim guard rect calculations) */\n contentRef: React.RefObject<HTMLElement | null>\n /** Surface ID of the parent menu (for keyboard navigation back) */\n parentSurfaceId: string\n /** Surface ID of this submenu (for keyboard navigation into) */\n childSurfaceId: string\n /**\n * Whether pressing Escape in this submenu closes the entire menu from the root.\n * When true, Escape closes the entire menu tree.\n * When false, Escape only closes this submenu and moves focus to the parent.\n * @default true\n */\n closeRootOnEsc: boolean\n}\n\nconst SubmenuContext = React.createContext<SubmenuContextValue | null>(null)\n\nexport function useSubmenuContext(): SubmenuContextValue {\n const context = React.useContext(SubmenuContext)\n if (!context) {\n throw new Error('SubmenuTrigger must be used within a Submenu')\n }\n return context\n}\n\nexport function useMaybeSubmenuContext(): SubmenuContextValue | null {\n return React.useContext(SubmenuContext)\n}\n\nexport { SubmenuContext }\n","'use client'\n\nimport * as React from 'react'\n\nexport interface AimGuardContextValue {\n aimGuardActive: boolean\n guardedTriggerId: string | null\n guardedDepth: number | null\n guardedSubmenuSurfaceId: string | null\n activateAimGuard: (\n triggerId: string,\n depth: number,\n submenuSurfaceId: string,\n timeoutMs?: number,\n ) => void\n clearAimGuard: () => void\n aimGuardActiveRef: React.RefObject<boolean>\n guardedTriggerIdRef: React.RefObject<string | null>\n guardedDepthRef: React.RefObject<number | null>\n guardedSubmenuSurfaceIdRef: React.RefObject<string | null>\n isGuardBlocking: (rowId: string) => boolean\n}\n\nconst AimGuardCtx = React.createContext<AimGuardContextValue>({\n aimGuardActive: false,\n guardedTriggerId: null,\n guardedDepth: null,\n guardedSubmenuSurfaceId: null,\n activateAimGuard: () => {},\n clearAimGuard: () => {},\n aimGuardActiveRef: { current: false },\n guardedTriggerIdRef: { current: null },\n guardedDepthRef: { current: null },\n guardedSubmenuSurfaceIdRef: { current: null },\n isGuardBlocking: () => false,\n})\n\nexport const useAimGuard = () => React.useContext(AimGuardCtx)\n\nexport interface AimGuardProviderProps {\n children: React.ReactNode\n}\n\n/**\n * Provides aim guard for safe polygon navigation.\n * Prevents accidental submenu closures when users move diagonally toward an open submenu.\n */\nexport function AimGuardProvider({ children }: AimGuardProviderProps) {\n const [aimGuardActive, setAimGuardActive] = React.useState(false)\n const [guardedTriggerId, setGuardedTriggerId] = React.useState<string | null>(\n null,\n )\n const [guardedDepth, setGuardedDepth] = React.useState<number | null>(null)\n const [guardedSubmenuSurfaceId, setGuardedSubmenuSurfaceId] = React.useState<\n string | null\n >(null)\n const aimGuardActiveRef = React.useRef(false)\n const guardedTriggerIdRef = React.useRef<string | null>(null)\n const guardedDepthRef = React.useRef<number | null>(null)\n const guardedSubmenuSurfaceIdRef = React.useRef<string | null>(null)\n\n React.useEffect(() => {\n aimGuardActiveRef.current = aimGuardActive\n }, [aimGuardActive])\n\n React.useEffect(() => {\n guardedTriggerIdRef.current = guardedTriggerId\n }, [guardedTriggerId])\n\n React.useEffect(() => {\n guardedDepthRef.current = guardedDepth\n }, [guardedDepth])\n\n React.useEffect(() => {\n guardedSubmenuSurfaceIdRef.current = guardedSubmenuSurfaceId\n }, [guardedSubmenuSurfaceId])\n\n const guardTimerRef = React.useRef<number | null>(null)\n\n const clearAimGuard = React.useCallback(() => {\n if (guardTimerRef.current) {\n window.clearTimeout(guardTimerRef.current)\n guardTimerRef.current = null\n }\n aimGuardActiveRef.current = false\n guardedTriggerIdRef.current = null\n guardedDepthRef.current = null\n guardedSubmenuSurfaceIdRef.current = null\n setAimGuardActive(false)\n setGuardedTriggerId(null)\n setGuardedDepth(null)\n setGuardedSubmenuSurfaceId(null)\n }, [])\n\n const activateAimGuard = React.useCallback(\n (\n triggerId: string,\n depth: number,\n submenuSurfaceId: string,\n timeoutMs = 450,\n ) => {\n aimGuardActiveRef.current = true\n guardedTriggerIdRef.current = triggerId\n guardedDepthRef.current = depth\n guardedSubmenuSurfaceIdRef.current = submenuSurfaceId\n setGuardedTriggerId(triggerId)\n setGuardedDepth(depth)\n setGuardedSubmenuSurfaceId(submenuSurfaceId)\n setAimGuardActive(true)\n if (guardTimerRef.current) window.clearTimeout(guardTimerRef.current)\n guardTimerRef.current = window.setTimeout(() => {\n aimGuardActiveRef.current = false\n guardedTriggerIdRef.current = null\n guardedDepthRef.current = null\n guardedSubmenuSurfaceIdRef.current = null\n setAimGuardActive(false)\n setGuardedTriggerId(null)\n setGuardedDepth(null)\n setGuardedSubmenuSurfaceId(null)\n guardTimerRef.current = null\n }, timeoutMs) as unknown as number\n },\n [],\n )\n\n const isGuardBlocking = React.useCallback(\n (rowId: string) =>\n aimGuardActiveRef.current && guardedTriggerIdRef.current !== rowId,\n [],\n )\n\n const value = React.useMemo(\n () => ({\n aimGuardActive,\n guardedTriggerId,\n guardedDepth,\n guardedSubmenuSurfaceId,\n activateAimGuard,\n clearAimGuard,\n aimGuardActiveRef,\n guardedTriggerIdRef,\n guardedDepthRef,\n guardedSubmenuSurfaceIdRef,\n isGuardBlocking,\n }),\n [\n aimGuardActive,\n guardedTriggerId,\n guardedDepth,\n guardedSubmenuSurfaceId,\n activateAimGuard,\n clearAimGuard,\n isGuardBlocking,\n ],\n )\n\n return <AimGuardCtx.Provider value={value}>{children}</AimGuardCtx.Provider>\n}\n\nexport { AimGuardCtx }\n","import { createSelector, ReactStore } from '@base-ui/utils/store'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FocusOwnerState {\n /** Which surface currently owns focus (surfaceId or null) */\n ownerId: string | null\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\nconst selectors = {\n ownerId: createSelector((state: FocusOwnerState) => state.ownerId),\n isOwner: createSelector(\n (state: FocusOwnerState, surfaceId: string) => state.ownerId === surfaceId,\n ),\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\n/**\n * Tracks which menu surface owns DOM focus.\n * Single instance per menu tree (created at root, shared via context).\n *\n * Used by: DropdownMenu, ContextMenu\n * Not used by: Select, CommandMenu (single surface)\n */\nexport class FocusOwnerStore extends ReactStore<\n FocusOwnerState,\n {},\n typeof selectors\n> {\n constructor() {\n super({ ownerId: null }, {}, selectors)\n }\n\n /**\n * Set the owner surface ID.\n * Call this when focus should transfer to a new surface.\n */\n setOwnerId(id: string | null) {\n this.set('ownerId', id)\n }\n\n /**\n * Clear the owner (set to null).\n * Call this when the menu tree closes.\n */\n clearOwner() {\n this.set('ownerId', null)\n }\n}\n\nexport type { FocusOwnerState as State }\n","import { createSelector, ReactStore } from '@base-ui/utils/store'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface OpenChainState {\n /**\n * Ordered array of surface IDs for submenus that are currently open.\n * The last element is the most recently opened (deepest in chain).\n */\n chain: string[]\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\nconst selectors = {\n isOpen: createSelector((state: OpenChainState, surfaceId: string) =>\n state.chain.includes(surfaceId),\n ),\n isLast: createSelector(\n (state: OpenChainState, surfaceId: string) =>\n state.chain.length > 0 &&\n state.chain[state.chain.length - 1] === surfaceId,\n ),\n /**\n * Returns true if there's an open submenu below the given depth.\n * - Root (depth 0): true if any submenu is open\n * - Submenu at depth N: true if a deeper submenu is open\n */\n hasOpenSubmenu: createSelector(\n (state: OpenChainState, depth: number) => state.chain.length > depth,\n ),\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\n/**\n * Tracks which submenu surfaces are currently open in order.\n * Used to show backdrops for all open menus in the chain.\n * Single instance per menu tree (created at root, shared via context).\n *\n * Used by: DropdownMenu, ContextMenu\n * Not used by: Select, CommandMenu (no submenus)\n */\nexport class OpenChainStore extends ReactStore<\n OpenChainState,\n {},\n typeof selectors\n> {\n constructor() {\n super({ chain: [] }, {}, selectors)\n }\n\n /**\n * Mark a surface as open (adds to end of chain).\n */\n open(surfaceId: string) {\n // Don't add duplicates\n if (this.state.chain.includes(surfaceId)) return\n\n const newChain = [...this.state.chain, surfaceId]\n this.set('chain', newChain)\n }\n\n /**\n * Mark a surface as closed (removes from chain).\n */\n close(surfaceId: string) {\n const newChain = this.state.chain.filter((id) => id !== surfaceId)\n this.set('chain', newChain)\n }\n\n /**\n * Clear all open surfaces (menu tree closed).\n */\n clear() {\n this.set('chain', [])\n }\n}\n\nexport type { OpenChainState as State }\n","export type AnchorSide = 'left' | 'right'\n\n/**\n * Determines which side of the submenu the trigger is anchored to.\n * Used to know which direction the user should be moving toward.\n */\nexport function resolveAnchorSide(\n rect: DOMRect,\n tRect: DOMRect | null,\n mx: number,\n): AnchorSide {\n if (tRect) {\n const tx = (tRect.left + tRect.right) / 2\n const dL = Math.abs(tx - rect.left)\n const dR = Math.abs(tx - rect.right)\n return dL <= dR ? 'left' : 'right'\n }\n return mx < rect.left ? 'left' : 'right'\n}\n\n/**\n * Calculates a smoothed heading vector from the mouse trail.\n * If movement is too slow, infers direction toward the submenu center.\n */\nexport function getSmoothedHeading(\n trail: [number, number][],\n exitX: number,\n exitY: number,\n anchor: AnchorSide,\n tRect: DOMRect | null,\n rect: DOMRect,\n): { dx: number; dy: number } {\n let dx = 0\n let dy = 0\n const n = Math.min(Math.max(trail.length - 1, 0), 4)\n for (let i = trail.length - n - 1; i < trail.length - 1; i++) {\n if (i < 0) continue\n const [x1, y1] = trail[i]!\n const [x2, y2] = trail[i + 1]!\n dx += x2 - x1\n dy += y2 - y1\n }\n const mag = Math.hypot(dx, dy)\n if (mag < 0.5) {\n const tx = tRect ? (tRect.left + tRect.right) / 2 : exitX\n const ty = tRect ? (tRect.top + tRect.bottom) / 2 : exitY\n const edgeX = anchor === 'right' ? rect.left : rect.right\n const edgeCy = (rect.top + rect.bottom) / 2\n dx = edgeX - tx\n dy = edgeCy - ty\n }\n return { dx, dy }\n}\n\n/**\n * Tests if the user's trajectory will intersect the submenu's safe zone.\n * Returns true if the user is aiming toward the submenu.\n */\nexport function willHitSubmenu(\n exitX: number,\n exitY: number,\n heading: { dx: number; dy: number },\n rect: DOMRect,\n anchor: AnchorSide,\n triggerRect: DOMRect | null,\n): boolean {\n const { dx, dy } = heading\n if (Math.abs(dx) < 0.01) return false\n if (anchor === 'left' && dx <= 0) return false\n if (anchor === 'right' && dx >= 0) return false\n const edgeX = anchor === 'left' ? rect.left : rect.right\n const t = (edgeX - exitX) / dx\n if (t <= 0) return false\n const yAtEdge = exitY + t * dy\n const baseBand = triggerRect ? triggerRect.height * 0.75 : 28\n const extra = Math.max(12, Math.min(36, baseBand))\n const top = rect.top - extra * 0.25\n const bottom = rect.bottom + extra * 0.25\n return yAtEdge >= top && yAtEdge <= bottom\n}\n","import * as React from 'react'\n\n/**\n * Keeps track of the last N mouse positions without causing re-renders.\n * Used for calculating mouse trajectory in aim guard.\n */\nexport function useMouseTrail(n = 4) {\n const trailRef = React.useRef<[number, number][]>([])\n\n React.useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const a = trailRef.current\n a.push([e.clientX, e.clientY])\n if (a.length > n) a.shift()\n }\n window.addEventListener('pointermove', onMove, { passive: true })\n return () => window.removeEventListener('pointermove', onMove)\n }, [n])\n\n return trailRef\n}\n","'use client'\n\nimport * as React from 'react'\nimport type {\n ChangeEventDetails,\n GenericEventDetails,\n} from '../../../utils/events/index.js'\nimport {\n createChangeEventDetails,\n REASONS,\n} from '../../../utils/events/index.js'\nimport { ListboxStore, type VirtualItem } from '../../listbox/index.js'\nimport type { VirtualizationConfig } from '../contexts/popup-menu-context.js'\nimport type {\n HighlightChangeReason,\n PopupMenuOpenChangeReason,\n} from '../events.js'\nimport { FocusOwnerStore } from '../store/FocusOwnerStore.js'\nimport { OpenChainStore } from '../store/OpenChainStore.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UsePopupMenuRootParams {\n /**\n * Callback when the open state changes.\n * The second parameter contains event details including the reason for the change.\n */\n onOpenChange?: (\n open: boolean,\n eventDetails: ChangeEventDetails<string>,\n ) => void\n\n /**\n * Whether the menu is initially open.\n * @default false\n */\n defaultOpen?: boolean\n\n /**\n * Whether virtualization mode is enabled.\n * @default false\n */\n virtualized?: boolean\n\n /**\n * Pre-registered items for virtualization.\n */\n items?: VirtualItem[]\n\n /**\n * Callback when the highlighted item changes.\n * The third parameter contains event details including the reason for the change.\n */\n onHighlightChange?: (\n id: string | null,\n index: number,\n eventDetails: GenericEventDetails<string, { index: number }>,\n ) => void\n\n /**\n * When to close the menu on outside interactions.\n * - 'pointerdown': Close immediately when pointer is pressed outside (default)\n * - 'click': Close when a full click (pointerdown + pointerup) occurs outside\n * @default 'pointerdown'\n */\n closeOnOutsidePress?: 'click' | 'pointerdown'\n}\n\nexport interface UsePopupMenuRootReturn {\n /** The Listbox store instance */\n store: ListboxStore\n /** The FocusOwner store instance */\n focusOwnerStore: FocusOwnerStore\n /** The OpenChain store instance */\n openChainStore: OpenChainStore\n /** Register a surface (submenu) for closeAll tracking */\n registerSurface: (\n depth: number,\n setOpen: (open: boolean) => void,\n ) => () => void\n /** Close the entire menu tree */\n closeAll: (reason?: PopupMenuOpenChangeReason, event?: Event) => void\n /** Virtualization configuration (if enabled) */\n virtualization: VirtualizationConfig | undefined\n /** Handle open state change (updates store and clears stores on close) */\n handleOpenChange: (\n open: boolean,\n reason?: PopupMenuOpenChangeReason,\n event?: Event,\n ) => void\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook that creates and manages the core stores and utilities for popup menus.\n * Used by both DropdownMenu.Root and ContextMenu.Root.\n *\n * Provides:\n * - ListboxStore for item management\n * - FocusOwnerStore for focus tracking across submenus\n * - OpenChainStore for tracking open submenu chain\n * - Surface registry for closeAll functionality\n */\nexport function usePopupMenuRoot(\n params: UsePopupMenuRootParams = {},\n): UsePopupMenuRootReturn {\n const {\n onOpenChange,\n defaultOpen = false,\n virtualized = false,\n items: itemsProp,\n onHighlightChange,\n closeOnOutsidePress = 'pointerdown',\n } = params\n\n // Track outside pointer events to distinguish outside-press from focus-out\n // When a pointerdown happens outside the menu, we store it so that if a\n // focus-out close happens immediately after, we can treat it as outside-press\n const outsidePointerEventRef = React.useRef<PointerEvent | null>(null)\n\n // Create stable callback wrapper for onOpenChange that converts focus-out to outside-press\n // when the close was triggered by a pointer event outside the menu\n const stableOnOpenChange = React.useCallback(\n (open: boolean, eventDetails: ChangeEventDetails<string>) => {\n // If closing due to focus-out but we have a stored outside pointer event,\n // convert the reason to outside-press for better cancel() support\n if (\n !open &&\n eventDetails.reason === REASONS.focusOut &&\n outsidePointerEventRef.current\n ) {\n const pointerEvent = outsidePointerEventRef.current\n outsidePointerEventRef.current = null\n\n // Create new event details with outside-press reason and the pointer event\n const convertedDetails = createChangeEventDetails(\n REASONS.outsidePress,\n pointerEvent,\n )\n\n onOpenChange?.(open, convertedDetails)\n\n // If the converted callback canceled, also cancel the original\n if (convertedDetails.isCanceled) {\n eventDetails.cancel()\n }\n return\n }\n\n // Clear the pointer event ref if we're not using it\n outsidePointerEventRef.current = null\n\n onOpenChange?.(open, eventDetails)\n },\n [onOpenChange],\n )\n\n // Create the store instance\n const store = ListboxStore.useStore(\n undefined,\n { open: defaultOpen },\n {\n onOpenChange: stableOnOpenChange,\n },\n )\n\n // Get current open state for the pointer event listener\n const isOpen = store.useState('open')\n\n // Create focus owner store (single instance for entire menu tree)\n const focusOwnerStoreRef = React.useRef<FocusOwnerStore | null>(null)\n if (!focusOwnerStoreRef.current) {\n focusOwnerStoreRef.current = new FocusOwnerStore()\n }\n const focusOwnerStore = focusOwnerStoreRef.current\n\n // Create open chain store (single instance for entire menu tree)\n const openChainStoreRef = React.useRef<OpenChainStore | null>(null)\n if (!openChainStoreRef.current) {\n openChainStoreRef.current = new OpenChainStore()\n }\n const openChainStore = openChainStoreRef.current\n\n // Registry for tracking open submenus (for closeAll)\n type SurfaceEntry = { depth: number; setOpen: (open: boolean) => void }\n const surfaceRegistryRef = React.useRef<Map<string, SurfaceEntry>>(new Map())\n\n // Register a surface (submenu) for closeAll tracking\n const registerSurface = React.useCallback(\n (depth: number, setOpen: (open: boolean) => void) => {\n const id = Math.random().toString(36).slice(2)\n surfaceRegistryRef.current.set(id, { depth, setOpen })\n return () => {\n surfaceRegistryRef.current.delete(id)\n }\n },\n [],\n )\n\n // Close the entire menu tree from deepest submenu to root\n const closeAll = React.useCallback(\n (reason: PopupMenuOpenChangeReason = REASONS.itemPress, event?: Event) => {\n // Sort surfaces by depth (deepest first)\n const surfaces = [...surfaceRegistryRef.current.values()].sort(\n (a, b) => b.depth - a.depth,\n )\n\n // Close each submenu from deepest to shallowest\n for (const surface of surfaces) {\n surface.setOpen(false)\n }\n\n // Finally close the root\n store.setOpen(false, reason, event)\n\n // Clear focus ownership and open chain\n focusOwnerStore.clearOwner()\n openChainStore.clear()\n },\n [store, focusOwnerStore, openChainStore],\n )\n\n // Ref to hold closeAll for use in the pointerdown effect\n const closeAllRef = React.useRef(closeAll)\n closeAllRef.current = closeAll\n\n // Listen for pointerdown events on document to detect outside clicks\n // This is a single listener at the root level that handles the entire menu tree.\n // Behavior depends on closeOnOutsidePress:\n // - 'pointerdown': Close immediately when pointer is pressed outside\n // - 'click': Store event and convert focus-out to outside-press reason\n React.useEffect(() => {\n if (!isOpen) {\n outsidePointerEventRef.current = null\n return\n }\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Element | null\n if (!target) return\n\n // Check if the pointerdown is inside any part of the menu tree or its triggers\n // base-ui sets data-open on popups and data-popup-open on triggers\n const isInsidePopup = target.closest('[data-open]') !== null\n const isInsideTrigger = target.closest('[data-popup-open]') !== null\n const isInside = isInsidePopup || isInsideTrigger\n\n if (closeOnOutsidePress === 'pointerdown' && !isInside) {\n // Close entire menu tree immediately on pointerdown outside\n closeAllRef.current(REASONS.outsidePress, event)\n } else {\n // Store the event for focus-out-to-outside-press conversion\n outsidePointerEventRef.current = event\n }\n }\n\n // Use capture phase to see the event before any stopPropagation\n document.addEventListener('pointerdown', handlePointerDown, true)\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown, true)\n outsidePointerEventRef.current = null\n }\n }, [isOpen, closeOnOutsidePress])\n\n // Handle open state change\n const handleOpenChange = React.useCallback(\n (\n newOpen: boolean,\n reason: PopupMenuOpenChangeReason = REASONS.none,\n event?: Event,\n ) => {\n store.setOpen(newOpen, reason, event)\n // Clear focus ownership and open chain when menu closes\n if (!newOpen) {\n focusOwnerStore.clearOwner()\n openChainStore.clear()\n }\n },\n [store, focusOwnerStore, openChainStore],\n )\n\n // Memoize virtualization config\n const virtualization = React.useMemo(() => {\n if (!virtualized) return undefined\n return {\n virtualized: true as const,\n items: itemsProp ?? [],\n onHighlightChange,\n }\n }, [virtualized, itemsProp, onHighlightChange])\n\n return {\n store,\n focusOwnerStore,\n openChainStore,\n registerSurface,\n closeAll,\n virtualization,\n handleOpenChange,\n }\n}\n","// ============================================================================\n// Event Reason Constants\n// ============================================================================\n// Centralized reason constants for all UI event handlers.\n// These provide type-safe reasons for WHY a state change occurred.\n\n// Trigger interactions\nexport const triggerPress = 'trigger-press' as const\nexport const triggerHover = 'trigger-hover' as const\nexport const triggerFocus = 'trigger-focus' as const\nexport const triggerContextMenu = 'trigger-context-menu' as const\n\n// Dismissal reasons\nexport const escapeKey = 'escape-key' as const\nexport const outsidePress = 'outside-press' as const\nexport const focusOut = 'focus-out' as const\n\n// Item interactions\nexport const itemPress = 'item-press' as const\nexport const itemKeyboardSelect = 'item-keyboard-select' as const\nexport const closePress = 'close-press' as const\n\n// Input interactions (Combobox)\nexport const inputChange = 'input-change' as const\nexport const inputClear = 'input-clear' as const\nexport const clearPress = 'clear-press' as const\n\n// Navigation\nexport const listNavigation = 'list-navigation' as const\n\n// Submenu/menu management\nexport const submenuTrigger = 'submenu-trigger' as const\nexport const siblingOpen = 'sibling-open' as const\n\n// Highlight changes\nexport const pointer = 'pointer' as const\nexport const keyboard = 'keyboard' as const\nexport const auto = 'auto' as const\n\n// Programmatic/other\nexport const imperativeAction = 'imperative-action' as const\nexport const none = 'none' as const\n","import { REASONS } from './reasons.js'\n\n// ============================================================================\n// Reason to Native Event Type Mapping\n// ============================================================================\n\n/**\n * Maps event reason strings to their corresponding native DOM event types.\n * This provides type-safe access to the native event based on the reason.\n */\ninterface ReasonToEventMap {\n [REASONS.none]: Event\n\n // Trigger interactions\n [REASONS.triggerPress]: MouseEvent | PointerEvent | TouchEvent | KeyboardEvent\n [REASONS.triggerHover]: MouseEvent | PointerEvent\n [REASONS.triggerFocus]: FocusEvent\n [REASONS.triggerContextMenu]: MouseEvent\n\n // Dismissal reasons\n [REASONS.escapeKey]: KeyboardEvent\n [REASONS.outsidePress]: MouseEvent | PointerEvent | TouchEvent\n [REASONS.focusOut]: FocusEvent | KeyboardEvent\n\n // Item interactions\n [REASONS.itemPress]: MouseEvent | PointerEvent | KeyboardEvent\n [REASONS.itemKeyboardSelect]: KeyboardEvent\n [REASONS.closePress]: MouseEvent | PointerEvent | KeyboardEvent\n\n // Input interactions\n [REASONS.inputChange]: InputEvent | Event\n [REASONS.inputClear]: InputEvent | FocusEvent | Event\n [REASONS.clearPress]: MouseEvent | PointerEvent | KeyboardEvent\n\n // Navigation\n [REASONS.listNavigation]: KeyboardEvent\n\n // Submenu/menu management\n [REASONS.submenuTrigger]: MouseEvent | PointerEvent | KeyboardEvent\n [REASONS.siblingOpen]: Event\n\n // Highlight changes\n [REASONS.pointer]: MouseEvent | PointerEvent\n [REASONS.keyboard]: KeyboardEvent\n\n // Programmatic\n [REASONS.imperativeAction]: Event\n}\n\n/**\n * Maps a reason string to the corresponding native event type.\n * Falls back to `Event` for unknown reasons.\n */\nexport type ReasonToEvent<Reason extends string> =\n Reason extends keyof ReasonToEventMap ? ReasonToEventMap[Reason] : Event\n\n// ============================================================================\n// Change Event Details\n// ============================================================================\n\n/**\n * Details object passed to change event handlers (onOpenChange, onValueChange, etc.)\n *\n * @template Reason - The union of allowed reason strings for this event\n * @template CustomProperties - Additional component-specific properties\n */\nexport interface ChangeEventDetails<\n Reason extends string,\n CustomProperties extends object = {},\n> {\n /**\n * The reason why this state change occurred.\n * Use this to conditionally handle different scenarios.\n *\n * @example\n * ```tsx\n * onOpenChange={(open, details) => {\n * if (details.reason === 'escape-key') {\n * // Handle escape key differently\n * }\n * }}\n * ```\n */\n reason: Reason\n\n /**\n * The native DOM event that triggered this change.\n * May be a synthetic event in some cases.\n */\n event: ReasonToEvent<Reason>\n\n /**\n * Cancels the state change.\n * When called, the component's internal state will not update.\n *\n * @example\n * ```tsx\n * onOpenChange={(open, details) => {\n * if (!open && details.reason === 'outside-press') {\n * details.cancel() // Prevent closing on outside press\n * }\n * }}\n * ```\n */\n cancel: () => void\n\n /**\n * Allows the native event to propagate.\n * By default, some events (like Escape key) stop propagation\n * to prevent parent popups from closing simultaneously.\n */\n allowPropagation: () => void\n\n /**\n * Whether `cancel()` has been called.\n */\n readonly isCanceled: boolean\n\n /**\n * Whether `allowPropagation()` has been called.\n */\n readonly isPropagationAllowed: boolean\n\n /**\n * The element that triggered this event, if applicable.\n */\n trigger: Element | undefined\n}\n\n/**\n * Creates a change event details object.\n *\n * @param reason - The reason for the state change\n * @param event - The native DOM event (optional)\n * @param trigger - The element that triggered the event (optional)\n * @param customProperties - Additional component-specific properties (optional)\n */\nexport function createChangeEventDetails<\n Reason extends string,\n CustomProperties extends object = {},\n>(\n reason: Reason,\n event?: ReasonToEvent<Reason> | Event,\n trigger?: Element,\n customProperties?: CustomProperties,\n): ChangeEventDetails<Reason, CustomProperties> {\n let canceled = false\n let propagationAllowed = false\n\n const details: ChangeEventDetails<Reason, CustomProperties> = {\n reason,\n event: (event ?? new Event('ui-event')) as ReasonToEvent<Reason>,\n cancel() {\n canceled = true\n },\n allowPropagation() {\n propagationAllowed = true\n },\n get isCanceled() {\n return canceled\n },\n get isPropagationAllowed() {\n return propagationAllowed\n },\n trigger,\n ...(customProperties as CustomProperties),\n }\n\n return details\n}\n\n// ============================================================================\n// Generic Event Details (for non-change events)\n// ============================================================================\n\n/**\n * Details object for generic events that don't support cancellation.\n * Used for events like onHighlightChange where cancellation doesn't make sense.\n *\n * @template Reason - The union of allowed reason strings for this event\n * @template CustomProperties - Additional component-specific properties\n */\nexport interface GenericEventDetails<\n Reason extends string,\n CustomProperties extends object = {},\n> {\n /**\n * The reason why this event occurred.\n */\n reason: Reason\n\n /**\n * The native DOM event that triggered this event.\n */\n event: ReasonToEvent<Reason>\n}\n\n/**\n * Creates a generic event details object (without cancel/propagation methods).\n */\nexport function createGenericEventDetails<\n Reason extends string,\n CustomProperties extends object = {},\n>(\n reason: Reason,\n event?: ReasonToEvent<Reason> | Event,\n customProperties?: CustomProperties,\n): GenericEventDetails<Reason, CustomProperties> {\n return {\n reason,\n event: (event ?? new Event('ui-event')) as ReasonToEvent<Reason>,\n ...(customProperties as CustomProperties),\n }\n}\n","'use client'\n\nimport * as React from 'react'\n\n// ============================================================================\n// Group Context (for items to know their parent group)\n// ============================================================================\n\nexport interface GroupContextValue {\n groupId: string\n}\n\nconst GroupContext = React.createContext<GroupContextValue | null>(null)\n\nexport function useGroupContext(): GroupContextValue | null {\n return React.useContext(GroupContext)\n}\n\nexport { GroupContext }\n","'use client'\n\nimport * as React from 'react'\n\n// ============================================================================\n// Item Context (for child components like indicators to access item state)\n// ============================================================================\n\nexport interface ItemContextValue {\n /** Unique ID for this item (for DOM id attribute) */\n id: string\n /** Whether the item is highlighted */\n highlighted: boolean\n /** Whether the item is disabled */\n disabled: boolean\n /** Keyboard shortcut for this item */\n shortcut?: string\n}\n\nconst ItemContext = React.createContext<ItemContextValue | null>(null)\n\nexport function useItemContext(): ItemContextValue {\n const context = React.useContext(ItemContext)\n if (!context) {\n throw new Error('Item child components must be used within an Item')\n }\n return context\n}\n\nexport function useMaybeItemContext(): ItemContextValue | null {\n return React.useContext(ItemContext)\n}\n\nexport { ItemContext }\n","'use client'\n\nimport * as React from 'react'\nimport type { HighlightChangeEventDetails } from '../../popup-menu/events.js'\nimport type { ListboxStore, VirtualItem } from '../store/ListboxStore.js'\n\n/**\n * Virtualization configuration passed from Root/Submenu to Surface.\n */\nexport interface VirtualizationConfig {\n /** Whether virtualization mode is enabled */\n virtualized: boolean\n /** Pre-registered items for virtualization */\n items: VirtualItem[]\n /**\n * Callback when highlighted item changes (for scroll sync).\n * The third parameter contains event details including the reason for the change.\n */\n onHighlightChange?: (\n id: string | null,\n index: number,\n eventDetails: HighlightChangeEventDetails,\n ) => void\n}\n\nexport interface ListboxContextValue {\n /** The Listbox store instance */\n store: ListboxStore\n /** Nesting depth: 0 = root menu, 1+ = submenu */\n depth: number\n /** Close the entire menu tree (deepest submenu to root, sequentially) */\n closeAll: () => void\n /** Register a surface (submenu) for closeAll tracking. Returns unregister function. */\n registerSurface: (\n depth: number,\n setOpen: (open: boolean) => void,\n ) => () => void\n /** Virtualization configuration (if enabled) */\n virtualization?: VirtualizationConfig\n}\n\nconst ListboxContext = React.createContext<ListboxContextValue | null>(null)\n\nexport function useListboxContext(): ListboxContextValue {\n const context = React.useContext(ListboxContext)\n if (!context) {\n throw new Error('Listbox components must be used within a Listbox provider')\n }\n return context\n}\n\nexport function useMaybeListboxContext(): ListboxContextValue | null {\n return React.useContext(ListboxContext)\n}\n\nexport { ListboxContext }\n","'use client'\n\nimport * as React from 'react'\n\n/**\n * Context value for row width measurement.\n * Provided by List when `measureRowWidth` is enabled.\n */\nexport interface RowWidthContextValue {\n /**\n * Queue a row element for width measurement.\n * Call this when a row mounts or becomes visible.\n *\n * @param element - The DOM element to measure\n * @param id - Unique identifier for this row (used to avoid re-measuring)\n */\n queueMeasurement: (element: HTMLElement, id: string) => void\n}\n\n/**\n * Context for row width measurement.\n * Items use this to self-register for measurement.\n */\nexport const RowWidthContext = React.createContext<RowWidthContextValue | null>(\n null,\n)\n\nif (process.env.NODE_ENV !== 'production') {\n RowWidthContext.displayName = 'RowWidthContext'\n}\n\n/**\n * Hook to get the row width context.\n * Throws an error if used outside of a List with `measureRowWidth` enabled.\n */\nexport function useRowWidthContext(): RowWidthContextValue {\n const context = React.useContext(RowWidthContext)\n if (!context) {\n throw new Error(\n 'useRowWidthContext must be used within a List with measureRowWidth enabled',\n )\n }\n return context\n}\n\n/**\n * Hook to optionally get the row width context.\n * Returns null if not within a List with `measureRowWidth` enabled.\n * This is the preferred hook for items that should work both with and without measurement.\n */\nexport function useMaybeRowWidthContext(): RowWidthContextValue | null {\n return React.useContext(RowWidthContext)\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { ListboxStore } from '../store/ListboxStore.js'\n\n// Re-export types from the store for convenience\nexport type {\n FilterFn,\n ItemRegistration,\n} from '../store/ListboxStore.js'\n\n// ============================================================================\n// Surface Context\n// ============================================================================\n\nexport interface SurfaceContextValue {\n /** The Listbox store instance */\n store: ListboxStore\n /** Unique identifier for this surface */\n surfaceId: string\n}\n\nconst SurfaceContext = React.createContext<SurfaceContextValue | null>(null)\n\nexport function useSurfaceContext(): SurfaceContextValue {\n const context = React.useContext(SurfaceContext)\n if (!context) {\n throw new Error('Listbox components must be used within a Surface provider')\n }\n return context\n}\n\nexport function useMaybeSurfaceContext(): SurfaceContextValue | null {\n return React.useContext(SurfaceContext)\n}\n\nexport { SurfaceContext }\n","'use client'\n\nimport * as React from 'react'\nimport { useGroupContext } from '../contexts/group-context.js'\nimport type { ItemContextValue } from '../contexts/item-context.js'\nimport { useListboxContext } from '../contexts/listbox-context.js'\nimport { useMaybeRowWidthContext } from '../contexts/row-width-context.js'\nimport { useSurfaceContext } from '../contexts/surface-context.js'\nimport { normalizeValue } from '../utils/normalize.js'\n\n/**\n * Aim guard refs for submenu navigation.\n * Optional - only needed for popup menus with submenus.\n */\nexport interface AimGuardRefs {\n /** Whether aim guard is currently active */\n aimGuardActiveRef: React.RefObject<boolean>\n /** The depth at which aim guard is active (null when not guarding) */\n guardedDepthRef: React.RefObject<number | null>\n}\n\n/**\n * Parameters for the useListboxItem hook.\n */\nexport interface UseListboxItemParams {\n /**\n * Explicit unique identifier for this item in the store.\n * Takes highest priority for item registration.\n * Used by data-first APIs to ensure consistent IDs.\n */\n id?: string\n\n /**\n * Unique value for this item used as identifier and for filtering.\n * If not provided, will be inferred from textContent.\n * Used for registration when `id` is not provided.\n */\n value?: string\n\n /**\n * Additional keywords to match against when filtering.\n * Useful for aliases or synonyms.\n */\n keywords?: string[]\n\n /**\n * Whether this item is disabled.\n * Disabled items are not selectable and are skipped during keyboard navigation.\n */\n disabled?: boolean\n\n /**\n * Whether to force render this item regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n /**\n * Keyboard shortcut to trigger this item.\n * When the menu is focused and the user presses this key, the item will be selected.\n * Should be a single character (e.g., \"1\", \"a\", etc.).\n */\n shortcut?: string\n\n /**\n * Whether this item is a submenu trigger (for store registration).\n * @default false\n */\n isSubmenuTrigger?: boolean\n\n /**\n * Callback when this item is selected (via click or Enter key).\n * For simple items, pass this directly. For checkbox/radio items,\n * use registerSelect() to register a dynamic handler.\n */\n onSelect?: () => void\n\n /**\n * Whether selecting this item should close the menu.\n * @default true\n */\n closeOnClick?: boolean\n\n /**\n * Callback invoked after selection occurs (via click).\n * Called with the item's ID. The consumer handles any\n * post-selection behavior like closing menus.\n */\n onAfterSelect?: (itemId: string) => void\n\n /**\n * Children (used for text content inference when value is not provided).\n */\n children?: React.ReactNode\n\n /**\n * Optional aim guard refs for popup menu navigation.\n * When provided, pointer move events will respect the aim guard.\n */\n aimGuard?: AimGuardRefs\n}\n\n/**\n * Return value from the useListboxItem hook.\n */\nexport interface UseListboxItemReturn {\n /** Unique ID for this item (DOM ID for aria-activedescendant) */\n id: string\n\n /**\n * Store identifier for this item.\n * Use this when calling store methods like setHighlightedId, registerSubmenuOpen, etc.\n * This is the `value` prop (or inferred from textContent).\n */\n storeId: string\n\n /** Ref to attach to the item element */\n ref: React.RefObject<HTMLDivElement | null>\n\n /** Whether item is currently highlighted */\n isHighlighted: boolean\n\n /** Whether item should be rendered (passes filter) */\n isVisible: boolean\n\n /** Context value to provide to children via ItemContext.Provider */\n contextValue: ItemContextValue\n\n /**\n * Event handlers to spread on the element.\n * These handle click, pointer move, and pointer down events.\n */\n handlers: {\n onClick: React.MouseEventHandler<HTMLDivElement>\n onPointerMove: React.PointerEventHandler<HTMLDivElement>\n onPointerDown: React.PointerEventHandler<HTMLDivElement>\n }\n\n /**\n * Register a custom onSelect handler.\n * This is useful for checkbox/radio items where the select behavior\n * needs to be customized (e.g., toggle checked state).\n * Returns an unregister function.\n */\n registerSelect: (handler: (() => void) | undefined) => () => void\n}\n\n/**\n * Hook that provides all shared logic for navigatable/highlightable listbox items.\n *\n * This hook handles:\n * - Item registration with the listbox store\n * - Highlight state management (keyboard and pointer)\n * - Filter/search visibility\n * - Scroll into view on keyboard navigation\n * - Click, pointer move, and pointer down event handlers\n * - Optional aim guard integration (for submenu navigation)\n *\n * @example\n * ```tsx\n * function CustomItem(props) {\n * const item = useListboxItem({\n * value: props.value,\n * disabled: props.disabled,\n * onSelect: props.onSelect,\n * })\n *\n * if (!item.isVisible) return null\n *\n * return (\n * <ItemContext.Provider value={item.contextValue}>\n * <div\n * ref={item.ref}\n * {...item.handlers}\n * data-highlighted={item.isHighlighted || undefined}\n * >\n * {props.children}\n * </div>\n * </ItemContext.Provider>\n * )\n * }\n * ```\n */\nexport function useListboxItem(\n params: UseListboxItemParams,\n): UseListboxItemReturn {\n const {\n id: idProp,\n value: valueProp,\n keywords,\n disabled = false,\n forceMount = false,\n shortcut,\n isSubmenuTrigger = false,\n onSelect,\n closeOnClick = true,\n onAfterSelect,\n children,\n aimGuard,\n } = params\n\n const { store } = useSurfaceContext()\n const groupContext = useGroupContext()\n const { depth } = useListboxContext()\n\n const ref = React.useRef<HTMLDivElement>(null)\n\n // Infer value from textContent if not provided\n const [inferredValue, setInferredValue] = React.useState<string>('')\n\n React.useLayoutEffect(() => {\n if (idProp === undefined && valueProp === undefined && ref.current) {\n const textContent = ref.current.textContent?.trim() ?? ''\n setInferredValue(textContent)\n }\n }, [idProp, valueProp, children])\n\n // Registration ID priority: id prop > value prop > textContent inference\n // This ensures data-first APIs can provide explicit IDs that match their internal tracking\n // Note: valueProp is normalized (trimmed) to match cmdk's behavior\n const registrationId = idProp ?? (normalizeValue(valueProp) || inferredValue)\n\n // Generate a stable ID for DOM id attribute (aria-activedescendant, etc.)\n // When id prop is provided (data-first APIs), use it directly for DOM ID\n // This ensures aria-activedescendant works correctly with composite IDs\n const generatedDomId = React.useId()\n const domId = idProp ?? `item-${generatedDomId}`\n\n // Stabilize keywords to prevent infinite loops when passed as inline arrays\n // We use JSON.stringify to compare by value rather than reference\n // Keywords are also normalized (trimmed) to match cmdk's behavior\n const normalizedKeywords = keywords\n ?.map((k) => normalizeValue(k))\n .filter(Boolean)\n const keywordsKey = normalizedKeywords\n ? JSON.stringify(normalizedKeywords)\n : undefined\n\n // Register item with store (using registrationId as the unique identifier)\n React.useEffect(() => {\n if (!registrationId && !forceMount) return\n\n const unregister = store.registerItem(registrationId, {\n value: registrationId,\n keywords: normalizedKeywords,\n groupId: groupContext?.groupId,\n disabled,\n isSubmenuTrigger,\n shortcut,\n closeOnClick,\n })\n\n return unregister\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keywordsKey is a stable representation of keywords\n }, [\n registrationId,\n keywordsKey,\n groupContext?.groupId,\n disabled,\n isSubmenuTrigger,\n shortcut,\n closeOnClick,\n store,\n forceMount,\n ])\n\n // Register DOM ref with store for scroll behavior\n React.useEffect(() => {\n if (!registrationId) return\n return store.registerItemRef(registrationId, ref)\n }, [registrationId, store])\n\n // Register for row width measurement if enabled\n const rowWidthContext = useMaybeRowWidthContext()\n\n React.useLayoutEffect(() => {\n if (rowWidthContext && ref.current && registrationId) {\n rowWidthContext.queueMeasurement(ref.current, registrationId)\n }\n }, [rowWidthContext, registrationId])\n\n // Register onSelect handler if provided directly\n React.useEffect(() => {\n if (!onSelect || !registrationId) return\n return store.registerItemSelect(registrationId, onSelect)\n }, [registrationId, onSelect, store])\n\n // Use selectors to get derived state (using registrationId as identifier)\n const search = store.useState('search')\n const isHighlighted = store.useState('isHighlighted', registrationId)\n const score = store.useState('getItemScore', registrationId)\n\n // Check if filtering is disabled (consumer handles filtering externally)\n const filterDisabled = store.isFilterDisabled()\n\n // Determine visibility based on filter score\n // When filterDisabled, consumer handles filtering so all items are visible\n const hasSearch = search.length > 0\n const isVisible = forceMount || filterDisabled || !hasSearch || score > 0\n\n // Note: Scroll behavior is now handled by the store's setHighlightedId method.\n // It uses the registered DOM refs to call scrollIntoView when the element exists,\n // or falls back to onHighlightChange for virtualizer sync.\n\n // Event handlers\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (event.defaultPrevented) return\n if (disabled) return\n if (!registrationId) return\n\n event.preventDefault()\n\n // Call the registered onSelect handler via store\n const registeredHandler = store.context.itemSelects.get(registrationId)\n registeredHandler?.()\n\n // Notify consumer that selection occurred (for closing menus, etc.)\n onAfterSelect?.(registrationId)\n },\n [disabled, store, registrationId, onAfterSelect],\n )\n\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n event.preventDefault()\n },\n [],\n )\n\n const handlePointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (event.defaultPrevented) return\n if (disabled) return\n if (!registrationId) return\n\n // Don't highlight if aim guard is active at this depth (user is moving toward submenu)\n // Only block highlighting in the same menu where the trigger is located\n if (aimGuard) {\n const { aimGuardActiveRef, guardedDepthRef } = aimGuard\n if (aimGuardActiveRef.current && guardedDepthRef.current === depth)\n return\n }\n\n // Check if pointer has actually moved - prevents phantom highlights when\n // content shifts under a stationary pointer (e.g., search results changing)\n if (!store.shouldAllowPointerHighlight(event.clientX, event.clientY)) {\n return\n }\n\n // Highlight on hover (using registrationId as identifier)\n store.setHighlightedId(registrationId)\n },\n [disabled, aimGuard, depth, store, registrationId],\n )\n\n // Context value for child components\n const contextValue: ItemContextValue = React.useMemo(\n () => ({\n id: domId,\n highlighted: isHighlighted,\n disabled,\n shortcut,\n }),\n [domId, isHighlighted, disabled, shortcut],\n )\n\n // Register a custom select handler (for checkbox/radio items)\n const registerSelect = React.useCallback(\n (handler: (() => void) | undefined) => {\n if (!registrationId) return () => {}\n return store.registerItemSelect(registrationId, handler)\n },\n [store, registrationId],\n )\n\n const handlers = React.useMemo(\n () => ({\n onClick: handleClick,\n onPointerMove: handlePointerMove,\n onPointerDown: handlePointerDown,\n }),\n [handleClick, handlePointerMove, handlePointerDown],\n )\n\n return {\n id: domId,\n storeId: registrationId,\n ref,\n isHighlighted,\n isVisible,\n contextValue,\n handlers,\n registerSelect,\n }\n}\n","/**\n * Normalizes a value string for use in filtering and identification.\n * Trims leading/trailing whitespace to match cmdk's behavior.\n *\n * @param value - The value to normalize\n * @returns The trimmed value, or empty string if value is nullish\n */\nexport function normalizeValue(value: string | undefined | null): string {\n return value?.trim() ?? ''\n}\n\n/**\n * Converts a value string to a URL-safe slug for use in IDs.\n * - Trims whitespace\n * - Converts to lowercase\n * - Replaces spaces with hyphens\n * - Removes non-alphanumeric characters (except hyphens)\n * - Collapses multiple hyphens into one\n * - Removes leading/trailing hyphens\n *\n * @example\n * slugify(\"User Settings\") // \"user-settings\"\n * slugify(\" Hello World! \") // \"hello-world\"\n * slugify(\"Café & Co.\") // \"caf-co\"\n *\n * @param value - The value to slugify\n * @returns The slugified value, or empty string if value is nullish\n */\nexport function slugify(value: string | undefined | null): string {\n if (!value) return ''\n\n return (\n value\n .trim()\n .toLowerCase()\n // Replace spaces with hyphens\n .replace(/\\s+/g, '-')\n // Remove non-alphanumeric characters (except hyphens)\n .replace(/[^a-z0-9-]/g, '')\n // Collapse multiple hyphens into one\n .replace(/-+/g, '-')\n // Remove leading/trailing hyphens\n .replace(/^-|-$/g, '')\n )\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { ListboxStore } from '../store/ListboxStore.js'\n\n/**\n * Focus owner interface for keyboard handling.\n * Optional - only needed for popup menus with multiple surfaces.\n */\nexport interface FocusOwnerInterface {\n /** Check if a surface is the current owner */\n useState: (selector: 'isOwner', surfaceId: string) => boolean\n /** Set the owner surface ID */\n setOwnerId: (id: string | null) => void\n}\n\n/**\n * Submenu context interface for keyboard handling.\n * Optional - only needed for popup menus with submenus.\n */\nexport interface SubmenuInterface {\n /** Close this submenu */\n setOpen: (open: boolean) => void\n /** Parent surface ID for focus transfer */\n parentSurfaceId: string\n /** Whether Escape closes the root menu or just this submenu */\n closeRootOnEsc?: boolean\n}\n\nexport interface UseListboxKeyboardParams {\n /** The Listbox store instance */\n store: ListboxStore\n /** Unique identifier for this surface */\n surfaceId: string\n /** Whether keyboard handling is enabled */\n enabled: boolean\n /** User's onKeyDown handler to compose with */\n onKeyDown?: React.KeyboardEventHandler\n /**\n * Callback when an item is selected via keyboard (Enter or shortcut).\n * Called with selection details. The consumer handles any\n * post-selection behavior like closing menus.\n */\n onSelect?: (details: { itemId: string | null; closeOnClick: boolean }) => void\n /**\n * Callback to close the entire menu tree from the root.\n * Used when Escape is pressed and closeRootOnEsc is true (default).\n */\n closeAll: () => void\n\n // Optional popup-menu features\n\n /** The FocusOwner store for managing focus ownership (optional) */\n focusOwner?: FocusOwnerInterface\n /** Menu depth (0 for root, >0 for submenus) - defaults to 0 */\n depth?: number\n /** Submenu context for ArrowLeft navigation back to parent (optional) */\n submenuContext?: SubmenuInterface | null\n /**\n * Whether to enable type-to-search behavior.\n * When true, printable characters will activate the input and set pending search.\n * Used by List when hideUntilActive is enabled and input is not yet active.\n * @default false\n */\n enableTypeToSearch?: boolean\n /**\n * Whether to skip the focus owner check.\n * When true, keyboard handling will work based on `enabled` prop alone,\n * ignoring focus ownership. Useful for Combobox where the input is outside\n * the Surface but should still handle keyboard navigation.\n * @default false\n */\n skipFocusOwnerCheck?: boolean\n}\n\nexport interface UseListboxKeyboardReturn {\n /** Keyboard event handler to attach to the element */\n handleKeyDown: React.KeyboardEventHandler\n}\n\n/**\n * Centralized keyboard navigation hook for listbox-like components.\n * Handles arrow navigation, vim bindings, submenu open/close, and selection.\n *\n * This hook can be used standalone (for simple listboxes like Select/Command)\n * or with focus owner and submenu support (for popup menus with nested menus).\n */\nexport function useListboxKeyboard(\n params: UseListboxKeyboardParams,\n): UseListboxKeyboardReturn {\n const {\n store,\n surfaceId,\n enabled,\n onKeyDown,\n onSelect,\n closeAll,\n focusOwner,\n depth = 0,\n submenuContext,\n enableTypeToSearch = false,\n skipFocusOwnerCheck = false,\n } = params\n\n // Subscribe to focus ownership if available\n const focusOwnerIsOwner = focusOwner?.useState('isOwner', surfaceId) ?? true\n // Skip this check for Combobox where input is outside Surface\n const isOwner = skipFocusOwnerCheck ? true : focusOwnerIsOwner\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent) => {\n // Call user's handler first\n onKeyDown?.(event)\n\n if (event.defaultPrevented) return\n\n // Only handle keyboard if enabled and this surface owns focus\n if (!enabled) return\n if (!isOwner) return\n\n // Check for IME composition\n if (event.nativeEvent.isComposing || event.keyCode === 229) return\n\n // Type-to-search: detect printable characters when enabled\n // Note: Shortcuts take priority over type-to-search, so we check for shortcuts first\n if (enableTypeToSearch) {\n const hideUntilActive = store.context.hideUntilActive\n const inputActive = store.state.inputActive\n\n if (hideUntilActive && !inputActive) {\n const isPrintable =\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey\n\n if (isPrintable) {\n // Check if this key is a registered shortcut first\n const shortcutItemId = store.context.shortcuts.get(\n event.key.toLowerCase(),\n )\n if (shortcutItemId && store.selectByShortcut(event.key)) {\n event.preventDefault()\n const item = store.context.items.get(shortcutItemId)\n onSelect?.({\n itemId: shortcutItemId,\n closeOnClick: item?.closeOnClick ?? true,\n })\n return\n }\n\n // No shortcut match, trigger type-to-search\n event.preventDefault()\n store.setPendingSearch(event.key)\n store.setInputActive(true)\n return\n }\n }\n }\n\n switch (event.key) {\n case 'ArrowDown': {\n event.preventDefault()\n store.highlightNext()\n break\n }\n case 'ArrowUp': {\n event.preventDefault()\n store.highlightPrev()\n break\n }\n case 'n': {\n // Ctrl+N - next item (vim binding)\n if (event.ctrlKey) {\n event.preventDefault()\n store.highlightNext()\n }\n break\n }\n case 'p': {\n // Ctrl+P - previous item (vim binding)\n if (event.ctrlKey) {\n event.preventDefault()\n store.highlightPrev()\n }\n break\n }\n case 'ArrowRight': {\n // Open submenu if highlighted item is a submenu trigger\n // Note: Focus transfer is handled by SubmenuTrigger's registerSubmenuOpen callback\n if (store.isHighlightedSubmenuTrigger()) {\n event.preventDefault()\n store.openSubmenuForHighlighted()\n }\n break\n }\n case 'l': {\n // Ctrl+L - open submenu (vim binding)\n // Note: Focus transfer is handled by SubmenuTrigger's registerSubmenuOpen callback\n if (event.ctrlKey && store.isHighlightedSubmenuTrigger()) {\n event.preventDefault()\n store.openSubmenuForHighlighted()\n }\n break\n }\n case 'ArrowLeft': {\n // Close submenu and return to parent (only if in a submenu)\n if (depth > 0 && submenuContext && focusOwner) {\n event.preventDefault()\n submenuContext.setOpen(false)\n // Transfer focus back to parent surface\n focusOwner.setOwnerId(submenuContext.parentSurfaceId)\n }\n break\n }\n case 'h': {\n // Ctrl+H - close submenu (vim binding)\n if (event.ctrlKey && depth > 0 && submenuContext && focusOwner) {\n event.preventDefault()\n submenuContext.setOpen(false)\n // Transfer focus back to parent surface\n focusOwner.setOwnerId(submenuContext.parentSurfaceId)\n }\n break\n }\n case 'Enter': {\n event.preventDefault()\n const selectedId = store.state.highlightedId\n const item = store.getHighlightedItem()\n store.selectHighlighted()\n onSelect?.({\n itemId: selectedId,\n closeOnClick: item?.closeOnClick ?? true,\n })\n break\n }\n case 'Home': {\n // Highlight first item\n event.preventDefault()\n store.setHighlightedId(null)\n store.highlightNext()\n break\n }\n case 'End': {\n // Highlight last item\n event.preventDefault()\n store.setHighlightedId(null)\n store.highlightPrev()\n break\n }\n case 'Escape': {\n // Handle Escape based on depth and closeRootOnEsc setting\n if (depth === 0) {\n // Root menu: let parent component handle it normally\n // (closes the menu and returns focus to trigger)\n break\n }\n\n // In a submenu: always prevent default to avoid parent's focus restoration\n event.preventDefault()\n event.stopPropagation()\n\n if (submenuContext?.closeRootOnEsc !== false) {\n // closeRootOnEsc is true (default): close entire menu tree\n closeAll()\n } else {\n // closeRootOnEsc is false: close only this submenu\n submenuContext.setOpen(false)\n // Transfer focus back to parent surface\n if (focusOwner) {\n focusOwner.setOwnerId(submenuContext.parentSurfaceId)\n }\n }\n break\n }\n default: {\n // Handle single-character shortcuts (only when not typing in search input)\n // Shortcuts are disabled when there's an active search to avoid conflicts\n const hasActiveSearch = store.state.search.length > 0\n const isPrintable =\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey\n\n if (isPrintable && !hasActiveSearch) {\n const itemId = store.context.shortcuts.get(event.key.toLowerCase())\n if (itemId && store.selectByShortcut(event.key)) {\n event.preventDefault()\n const item = store.context.items.get(itemId)\n onSelect?.({\n itemId,\n closeOnClick: item?.closeOnClick ?? true,\n })\n }\n }\n break\n }\n }\n },\n [\n onKeyDown,\n enabled,\n isOwner,\n enableTypeToSearch,\n store,\n depth,\n submenuContext,\n focusOwner,\n onSelect,\n closeAll,\n ],\n )\n\n return { handleKeyDown }\n}\n","'use client'\n\nimport * as React from 'react'\n\n// Debug flag - set to true to enable console logging\nconst DEBUG_ROW_WIDTH = false\n\n// Debug flag - when true, keeps measurement styles applied (doesn't reset them)\n// This lets you visually inspect what elements look like during measurement\nconst DEBUG_FREEZE_MEASUREMENT = false\n\nfunction debugLog(...args: unknown[]) {\n if (DEBUG_ROW_WIDTH) {\n console.log('[useStickyRowWidth]', ...args)\n }\n}\n\nfunction px(n: number) {\n return `${Math.ceil(n)}px`\n}\n\ninterface MeasurementEntry {\n element: HTMLElement\n id: string\n}\n\nexport interface UseStickyRowWidthOptions {\n /**\n * Ref to the list container element.\n * Used to measure row widths and as a fallback target for the CSS variable.\n */\n listRef: React.RefObject<HTMLElement | null>\n /**\n * Optional ref to the element where `--row-width` CSS variable should be applied.\n * If not provided, uses the listRef element.\n * Useful for applying the variable to a parent Popup element.\n */\n targetRef?: React.RefObject<HTMLElement | null>\n /**\n * Optional maximum width cap in pixels.\n * The measured width will never exceed this value.\n */\n maxWidth?: number\n /**\n * Whether measurement is enabled.\n * @default true\n */\n enabled?: boolean\n}\n\nexport interface UseStickyRowWidthReturn {\n /**\n * Queue a row element for measurement.\n * The element's natural width will be measured and tracked.\n * Call this when a row mounts or becomes visible.\n */\n queueMeasurement: (element: HTMLElement, id: string) => void\n /**\n * Reset all measurements.\n * Call this when the menu closes to start fresh on next open.\n */\n resetMeasurements: () => void\n}\n\n/**\n * Hook that measures row widths and maintains a sticky maximum width.\n *\n * This is useful for virtualized lists where the popup width should adapt\n * to the content but never shrink as the user scrolls through items.\n *\n * The hook:\n * 1. Measures each row's natural width (using `max-content`)\n * 2. Tracks the maximum width seen across all rows\n * 3. Applies `--row-width` CSS variable to the list element\n * 4. Only grows the width, never shrinks (until reset)\n *\n * @example\n * ```tsx\n * const { queueMeasurement, resetMeasurements } = useStickyRowWidth({\n * listRef: myListRef,\n * maxWidth: 500,\n * })\n *\n * // Queue items for measurement\n * useLayoutEffect(() => {\n * if (itemRef.current) {\n * queueMeasurement(itemRef.current, itemId)\n * }\n * }, [itemId])\n *\n * // Reset on menu close\n * useEffect(() => {\n * if (!isOpen) {\n * resetMeasurements()\n * }\n * }, [isOpen])\n * ```\n */\nexport function useStickyRowWidth(\n options: UseStickyRowWidthOptions,\n): UseStickyRowWidthReturn {\n const { listRef, targetRef, maxWidth, enabled = true } = options\n\n // The element where CSS variable is applied (targetRef if provided, else listRef)\n const getTargetElement = React.useCallback(() => {\n return targetRef?.current ?? listRef.current\n }, [targetRef, listRef])\n\n // Track the maximum width seen so far\n const maxSeenRef = React.useRef(0)\n\n // RAF scheduler state\n const readQueue = React.useRef<MeasurementEntry[]>([])\n const writeQueue = React.useRef<Array<() => void>>([])\n const scheduled = React.useRef(false)\n const measuredIds = React.useRef<Set<string>>(new Set())\n\n /**\n * Apply the `--row-width` CSS variable to the target element.\n */\n const applyVar = React.useCallback(\n (width: number) => {\n const el = getTargetElement()\n if (!el) return\n\n // Apply hard cap if specified\n const capped = maxWidth !== undefined ? Math.min(width, maxWidth) : width\n\n debugLog('--row-width updated:', {\n rawWidth: width,\n cappedWidth: capped,\n cssValue: px(capped),\n maxWidthCap: maxWidth,\n targetElement:\n el.tagName +\n (el.className ? `.${el.className.split(' ').join('.')}` : ''),\n })\n\n el.style.setProperty('--row-width', px(capped))\n },\n [getTargetElement, maxWidth],\n )\n\n /**\n * RAF scheduler: batch reads, then batch writes.\n * This avoids layout thrashing by separating measurement from application.\n */\n const schedule = React.useCallback(() => {\n if (scheduled.current) return\n scheduled.current = true\n\n requestAnimationFrame(() => {\n // === READ PHASE: Measure all queued rows at once ===\n const measurements = readQueue.current\n let maxWidth = maxSeenRef.current\n let foundNewMax = false\n\n if (measurements.length > 0) {\n debugLog('Measuring batch of', measurements.length, 'rows')\n\n for (const { element, id } of measurements) {\n // Skip if already measured\n if (measuredIds.current.has(id)) continue\n\n // Skip if element is no longer in the DOM (unmounted before RAF fired)\n if (!element.isConnected) {\n debugLog('Row skipped (unmounted):', { id })\n continue\n }\n\n // Read natural width without interleaving writes\n const prevWidth = element.style.width\n const prevMaxWidth = element.style.maxWidth\n\n // Add data-measuring attribute so CSS can remove constraints on descendants\n element.setAttribute('data-measuring', '')\n\n // Temporarily remove max-width constraint to get true natural width\n element.style.maxWidth = 'none'\n element.style.width = 'max-content'\n\n const w = Math.max(element.scrollWidth, element.offsetWidth) + 1\n\n // Log computed styles to debug constraint issues\n const computed = getComputedStyle(element)\n debugLog('Row measurement details:', {\n id,\n measuredWidth: w,\n scrollWidth: element.scrollWidth,\n offsetWidth: element.offsetWidth,\n computedWidth: computed.width,\n computedMaxWidth: computed.maxWidth,\n inlineMaxWidth: prevMaxWidth,\n textContent: element.textContent?.slice(0, 50),\n })\n\n // Reset styles unless DEBUG_FREEZE_MEASUREMENT is enabled\n if (!DEBUG_FREEZE_MEASUREMENT) {\n element.style.width = prevWidth\n element.style.maxWidth = prevMaxWidth\n element.removeAttribute('data-measuring')\n }\n\n // Debug: if width is suspiciously small, log more info\n if (w <= 1) {\n const rect = element.getBoundingClientRect()\n const computed = getComputedStyle(element)\n debugLog('Row skipped (0-width, will retry):', {\n id,\n width: w,\n scrollWidth: element.scrollWidth,\n offsetWidth: element.offsetWidth,\n boundingRect: { width: rect.width, height: rect.height },\n display: computed.display,\n visibility: computed.visibility,\n innerHTML: element.innerHTML.slice(0, 100),\n isConnected: element.isConnected,\n parentElement: element.parentElement?.tagName,\n })\n // Don't mark as measured - element was likely unmounted/replaced\n // before we could measure it. It will be re-queued when it re-mounts.\n continue\n }\n\n debugLog('Row measured:', {\n id,\n width: w,\n currentMax: maxWidth,\n isNewMax: w > maxWidth,\n })\n\n if (w > maxWidth) {\n maxWidth = w\n foundNewMax = true\n }\n\n measuredIds.current.add(id)\n }\n\n readQueue.current = []\n }\n\n // === WRITE PHASE: Apply styles after all reads complete ===\n if (foundNewMax) {\n debugLog('New max width found:', {\n previousMax: maxSeenRef.current,\n newMax: maxWidth,\n totalMeasured: measuredIds.current.size,\n })\n maxSeenRef.current = maxWidth\n writeQueue.current.push(() => applyVar(maxWidth))\n }\n\n for (const write of writeQueue.current) {\n write()\n }\n writeQueue.current = []\n scheduled.current = false\n })\n }, [applyVar])\n\n /**\n * Queue a row element for measurement.\n */\n const queueMeasurement = React.useCallback(\n (element: HTMLElement, id: string) => {\n if (!enabled) {\n debugLog('queueMeasurement skipped (disabled):', id)\n return\n }\n\n // Skip if already measured\n if (measuredIds.current.has(id)) {\n debugLog('queueMeasurement skipped (already measured):', id)\n return\n }\n\n debugLog('queueMeasurement:', {\n id,\n queueSize: readQueue.current.length + 1,\n element: element.tagName,\n })\n\n // Add to read queue\n readQueue.current.push({ element, id })\n schedule()\n },\n [enabled, schedule],\n )\n\n /**\n * Reset all measurements.\n * This clears the tracked IDs and resets the max width.\n */\n const resetMeasurements = React.useCallback(() => {\n const prevMax = maxSeenRef.current\n const prevCount = measuredIds.current.size\n\n measuredIds.current.clear()\n maxSeenRef.current = 0\n\n // Clear the CSS variable\n const el = getTargetElement()\n if (el) {\n el.style.removeProperty('--row-width')\n }\n\n debugLog('Measurements reset:', {\n previousMaxWidth: prevMax,\n previousMeasuredCount: prevCount,\n targetElement: el?.tagName,\n })\n }, [getTargetElement])\n\n // Re-apply the CSS variable when the target element resizes (e.g., viewport changes)\n // Use useEffect (not useLayoutEffect) to avoid conflicts with React's commit phase\n React.useEffect(() => {\n if (!enabled) return\n\n const container = getTargetElement()\n if (!container) return\n\n // ResizeObserver may not be available in some environments (SSR, older browsers, tests)\n if (typeof ResizeObserver === 'undefined') return\n\n let rafId: number | null = null\n\n const ro = new ResizeObserver((entries) => {\n // Defer to next frame to avoid flushSync conflicts during React's commit phase\n // This prevents errors when virtualizers or other components use flushSync\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n }\n rafId = requestAnimationFrame(() => {\n rafId = null\n if (maxSeenRef.current > 0) {\n debugLog('ResizeObserver triggered re-apply:', {\n currentMax: maxSeenRef.current,\n containerSize: entries[0]?.contentRect,\n })\n applyVar(maxSeenRef.current)\n }\n })\n })\n ro.observe(container)\n\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId)\n }\n ro.disconnect()\n }\n }, [getTargetElement, enabled, applyVar])\n\n return { queueMeasurement, resetMeasurements }\n}\n","import { createSelector, ReactStore } from '@base-ui/utils/store'\nimport { useRefWithInit } from '@base-ui/utils/useRefWithInit'\nimport {\n type ChangeEventDetails,\n createChangeEventDetails,\n createGenericEventDetails,\n type GenericEventDetails,\n REASONS,\n} from '../../../utils/events/index.js'\nimport type {\n HighlightChangeEventDetails,\n HighlightChangeReason,\n PopupMenuOpenChangeEventDetails,\n PopupMenuOpenChangeReason,\n} from '../../popup-menu/events.js'\nimport { commandScore } from '../utils/command-score.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type FilterFn = (\n value: string,\n search: string,\n keywords?: string[],\n) => number\n\nexport interface ItemRegistration {\n value: string\n keywords?: string[]\n groupId?: string\n disabled?: boolean\n /** Whether this item is a submenu trigger */\n isSubmenuTrigger?: boolean\n /** Single character keyboard shortcut to trigger this item */\n shortcut?: string\n /** Whether selecting this item should close the menu (default: true) */\n closeOnClick?: boolean\n}\n\n/**\n * Pre-registered item for virtualization.\n * This allows the store to know about all items even when they're not mounted.\n * The `value` field serves as both the unique identifier and the filtering value.\n */\nexport interface VirtualItem {\n /** Value used as unique identifier and for filtering/matching */\n value: string\n /** Additional keywords for filtering */\n keywords?: string[]\n /** Whether the item is disabled */\n disabled?: boolean\n}\n\nexport type HighlightSource = 'keyboard' | 'pointer' | 'auto' | null\n\n/**\n * Refs for DOM elements used for scroll behavior.\n * These are stored outside of reactive state to avoid unnecessary re-renders.\n */\nexport interface DOMRefs {\n /** Ref to the list/scroll container element */\n listRef: React.RefObject<HTMLElement | null>\n /** Map of item ID to ref for the item's DOM element */\n itemRefs: Map<string, React.RefObject<HTMLElement | null>>\n}\n\nexport interface ListboxState {\n /** Whether the listbox is open */\n open: boolean\n /** Current search query */\n search: string\n /** Currently highlighted item ID */\n highlightedId: string | null\n /** Source of the current highlight (keyboard or pointer) */\n highlightSource: HighlightSource\n /** Whether an Input is present in the Surface */\n hasInput: boolean\n /** Whether the input is currently active (rendered) when hideUntilActive mode is used */\n inputActive: boolean\n /** Pending search character typed before input was active */\n pendingSearch: string\n /** Filtered results: item ID to score */\n filteredItems: Map<string, number>\n /** Groups that have at least one visible item */\n visibleGroups: Set<string>\n /** Count of visible items */\n filteredCount: number\n /** Counter to trigger re-filtering when items change */\n filterTrigger: number\n /** Whether virtualization mode is enabled */\n virtualized: boolean\n /** Count of virtual items (from items prop) */\n virtualItemsCount: number\n}\n\nexport interface ListboxContext {\n /** Filter function or false to disable filtering */\n filter: FilterFn | false\n /** Whether to loop navigation */\n loop: boolean\n /**\n * Controls auto-highlighting behavior when the menu opens.\n * - `true`: highlight the first item (default)\n * - `false`: don't auto-highlight any item\n * - `string`: highlight the item with this specific value\n */\n autoHighlightFirst: boolean | string\n /**\n * Whether to clear search on close.\n * - `true`: clear immediately when menu closes (default)\n * - `false`: preserve search when menu closes\n * - `'after-exit'`: clear after exit animation completes (requires Surface to call clearSearch)\n */\n clearSearchOnClose: boolean | 'after-exit'\n /** Whether hideUntilActive mode is enabled */\n hideUntilActive: boolean\n /** ID for the list element (for aria-activedescendant) */\n listId: string\n /** ID for the input element */\n inputId: string\n /** Map of item ID to registration data */\n readonly items: Map<string, ItemRegistration>\n /** Map of group ID to set of item IDs */\n readonly groups: Map<string, Set<string>>\n /** Map of item ID to onSelect callback */\n readonly itemSelects: Map<string, () => void>\n /** Map of submenu trigger ID to open callback */\n readonly submenuOpens: Map<string, () => void>\n /** Map of submenu trigger ID to close callback */\n readonly submenuCloses: Map<string, () => void>\n /** Map of shortcut key to item ID */\n readonly shortcuts: Map<string, string>\n /**\n * Callback when open state changes.\n * The second parameter contains event details including the reason for the change.\n */\n onOpenChange: (\n open: boolean,\n eventDetails: PopupMenuOpenChangeEventDetails,\n ) => void\n /** Callback when search state changes */\n onSearchChange: ((search: string) => void) | undefined\n /**\n * Pre-registered items for virtualization.\n * When provided, navigation uses this array order instead of DOM registration order.\n */\n virtualItems: VirtualItem[]\n /**\n * Consumer-provided ordered list of item values when filter={false}.\n * Used to determine correct navigation/highlight order when consumer handles filtering externally.\n * Must always be provided when filter={false}.\n */\n orderedItems: string[]\n /**\n * Callback when highlighted item changes and needs scroll sync.\n * Called only when the item is not in the DOM (virtualized out of view).\n * Useful for synchronizing with virtualizers (scrollToIndex).\n * The third parameter contains event details including the reason for the change.\n */\n onHighlightChange:\n | ((\n id: string | null,\n index: number,\n eventDetails: HighlightChangeEventDetails,\n ) => void)\n | undefined\n /**\n * DOM refs for scroll behavior.\n * Stored in context (not state) to avoid re-renders.\n */\n refs: DOMRefs\n /**\n * Callback when menu close animation completes.\n * Used for resetting row width measurements.\n */\n onCloseComplete?: () => void\n /**\n * Last known pointer position for detecting actual pointer movement.\n * Used to prevent \"phantom\" highlights when content shifts under a stationary pointer.\n */\n lastPointerPosition: { x: number; y: number } | null\n}\n\n/**\n * Options for the validateHighlight method.\n */\ninterface ValidateHighlightOptions {\n /**\n * Force highlighting the first item, even if current highlight is valid.\n * Used when the list order changes (e.g., after filtering).\n */\n forceFirst?: boolean\n /**\n * The newly computed filteredItems map. If not provided, uses state.filteredItems.\n * This is needed when calling from recomputeFilteredItems before state is updated.\n */\n filteredItems?: Map<string, number>\n /**\n * The new search query that corresponds to filteredItems.\n * Used together with prevSearch to detect when search is cleared.\n */\n newSearch?: string\n /**\n * The previous search query before the change.\n * Used together with newSearch to detect when search is cleared.\n */\n prevSearch?: string\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\nconst selectors = {\n open: createSelector((state: ListboxState) => state.open),\n search: createSelector((state: ListboxState) => state.search),\n highlightedId: createSelector((state: ListboxState) => state.highlightedId),\n highlightSource: createSelector(\n (state: ListboxState) => state.highlightSource,\n ),\n hasInput: createSelector((state: ListboxState) => state.hasInput),\n inputActive: createSelector((state: ListboxState) => state.inputActive),\n pendingSearch: createSelector((state: ListboxState) => state.pendingSearch),\n filteredCount: createSelector((state: ListboxState) => state.filteredCount),\n filteredItems: createSelector((state: ListboxState) => state.filteredItems),\n visibleGroups: createSelector((state: ListboxState) => state.visibleGroups),\n virtualized: createSelector((state: ListboxState) => state.virtualized),\n\n isHighlighted: createSelector(\n (state: ListboxState, itemId: string) => state.highlightedId === itemId,\n ),\n\n isGroupVisible: createSelector(\n (state: ListboxState, groupId: string) =>\n state.search.length === 0 || state.visibleGroups.has(groupId),\n ),\n\n getItemScore: createSelector((state: ListboxState, itemId: string) => {\n if (state.search.length === 0) {\n return 1 // All items visible when no search\n }\n return state.filteredItems.get(itemId) ?? 0\n }),\n\n hasSearchWithNoResults: createSelector((state: ListboxState) => {\n // Must have an active search\n if (state.search.length === 0) return false\n\n // In virtualized mode with items prop, check virtualItemsCount\n // (filteredCount won't be accurate since items aren't registered in DOM)\n if (state.virtualized && state.virtualItemsCount >= 0) {\n return state.virtualItemsCount === 0\n }\n\n // Non-virtualized mode: check filteredCount from registered items\n return state.filteredCount === 0\n }),\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\n/**\n * Core store for listbox-like components.\n * Handles item registration, filtering, navigation, and highlight state.\n *\n * Used by: DropdownMenu, ContextMenu, Select, CommandMenu\n */\nexport class ListboxStore extends ReactStore<\n ListboxState,\n ListboxContext,\n typeof selectors\n> {\n constructor(\n initialState?: Partial<ListboxState>,\n context?: Partial<ListboxContext>,\n ) {\n const defaultContext: ListboxContext = {\n filter: commandScore,\n loop: true,\n autoHighlightFirst: true,\n clearSearchOnClose: true,\n hideUntilActive: false,\n listId: '',\n inputId: '',\n items: new Map(),\n groups: new Map(),\n itemSelects: new Map(),\n submenuOpens: new Map(),\n submenuCloses: new Map(),\n shortcuts: new Map(),\n onOpenChange: () => {},\n onSearchChange: undefined,\n virtualItems: [],\n orderedItems: [],\n onHighlightChange: undefined,\n refs: {\n listRef: { current: null },\n itemRefs: new Map(),\n },\n onCloseComplete: undefined,\n lastPointerPosition: null,\n }\n\n super(\n { ...createInitialState(), ...initialState },\n { ...defaultContext, ...context },\n selectors,\n )\n\n // Handle open/close\n this.observe('open', (open) => {\n if (open) {\n // Reset pointer position tracking on open to prevent phantom highlights\n this.resetPointerPosition()\n\n // Auto-highlight is now handled by applyAutoHighlight() called from Surface\n // after it has set the context. This ensures the correct value is used.\n // We only handle the simple boolean true case here for backwards compatibility\n // with components that don't use Surface (if any).\n const autoHighlight = this.context.autoHighlightFirst\n if (autoHighlight === true) {\n // Default: highlight first item\n this.highlightFirstItem()\n }\n // String values are handled by applyAutoHighlight() from Surface\n } else {\n // Clear search and highlight on close\n // When 'after-exit', search is cleared by Root after animation completes\n if (this.context.clearSearchOnClose === true) {\n this.setSearch('')\n }\n\n // When 'after-exit', also defer hiding the input until animation completes\n // This prevents the input from disappearing before the popup animates out\n const deferInputHide = this.context.clearSearchOnClose === 'after-exit'\n\n this.update({\n highlightedId: null,\n highlightSource: null,\n inputActive: deferInputHide ? this.state.inputActive : false,\n pendingSearch: '',\n })\n }\n })\n\n // Recompute filtered items when search changes (handles controlled search via useControlledProp)\n this.observe('search', (search, prevSearch) => {\n if (search !== prevSearch) {\n // Reset pointer position when search changes - content is about to shift\n // and we don't want stationary pointers to trigger phantom highlights\n this.resetPointerPosition()\n this.recomputeFilteredItems(prevSearch)\n }\n })\n }\n\n // ============================================================================\n // Actions\n // ============================================================================\n\n /**\n * Set the open state with event details.\n *\n * @param open - The new open state\n * @param reason - The reason for the state change (default: 'none')\n * @param event - The native DOM event that triggered the change (optional)\n */\n setOpen(\n open: boolean,\n reason: PopupMenuOpenChangeReason = REASONS.none,\n event?: Event,\n ) {\n const eventDetails = createChangeEventDetails(reason, event)\n\n // Call the user's callback first\n this.context.onOpenChange(open, eventDetails)\n\n // If the user canceled, don't update internal state\n if (eventDetails.isCanceled) {\n return\n }\n\n this.set('open', open)\n }\n\n setSearch(search: string) {\n this.set('search', search)\n this.context.onSearchChange?.(search)\n // Note: recomputeFilteredItems is called by the 'search' observer\n }\n\n setHighlightedId(id: string | null, cause: HighlightSource = 'pointer') {\n const prevId = this.state.highlightedId\n if (prevId === id) return\n\n // Close any open submenus that are not the newly highlighted item\n // This ensures only one submenu is open at a time in this menu\n this.closeSiblingSubmenus(id)\n\n this.update({ highlightedId: id, highlightSource: cause })\n\n // Always notify about highlight changes (for virtualization, analytics, etc.)\n this.notifyHighlightChange(id, cause)\n\n // Handle scroll behavior for keyboard navigation\n if (cause === 'keyboard' && id !== null) {\n this.scrollItemIntoView(id)\n }\n }\n\n /**\n * Notify listeners about highlight changes.\n * Called whenever highlightedId changes, regardless of virtualization or DOM state.\n * Useful for virtualization scroll sync, analytics, or any other tracking needs.\n *\n * @param id - The newly highlighted item ID (or null if cleared)\n * @param cause - What caused the highlight change\n */\n private notifyHighlightChange(id: string | null, cause: HighlightSource) {\n const { onHighlightChange } = this.context\n if (!onHighlightChange) return\n\n // Map cause to reason\n const reason: HighlightChangeReason =\n cause === 'keyboard'\n ? REASONS.keyboard\n : cause === 'pointer'\n ? REASONS.pointer\n : REASONS.auto\n\n // Get the index of the highlighted item\n const index =\n id === null\n ? -1\n : this.state.virtualized\n ? this.getVirtualItemIndex(id)\n : this.getVisibleItemIndex(id)\n\n const eventDetails = createGenericEventDetails(reason, undefined, { index })\n onHighlightChange(id, index, eventDetails)\n }\n\n /**\n * Scroll the highlighted item into view.\n * Uses native scrollIntoView if the element is in the DOM.\n * For virtualized lists, the onHighlightChange callback (called from setHighlightedId)\n * should handle scrolling via the virtualizer.\n *\n * @param id - The item ID to scroll into view\n */\n private scrollItemIntoView(id: string) {\n const { refs } = this.context\n const listEl = refs.listRef.current\n const itemRef = refs.itemRefs.get(id)\n const itemEl = itemRef?.current\n\n // If the item element exists and is inside the list, use native scrollIntoView\n if (itemEl && listEl) {\n try {\n const isInList = listEl.contains(itemEl)\n if (isInList) {\n itemEl.scrollIntoView({ block: 'nearest' })\n }\n } catch {\n // Ignore errors from scrollIntoView\n }\n }\n // For virtualized lists where the item is not in the DOM,\n // the onHighlightChange callback handles scroll via virtualizer\n }\n\n setHasInput(hasInput: boolean) {\n this.set('hasInput', hasInput)\n }\n\n setInputActive(active: boolean) {\n this.set('inputActive', active)\n }\n\n setPendingSearch(search: string) {\n this.set('pendingSearch', search)\n }\n\n setHideUntilActive(enabled: boolean) {\n this.context.hideUntilActive = enabled\n // If enabling and there's already search content, activate immediately\n if (enabled && this.state.search.length > 0) {\n this.setInputActive(true)\n }\n }\n\n setVirtualized(virtualized: boolean) {\n this.set('virtualized', virtualized)\n }\n\n setVirtualItems(items: VirtualItem[]) {\n const prevItems = this.context.virtualItems\n this.context.virtualItems = items\n\n // Update count in state for selectors to use\n this.set('virtualItemsCount', items.length)\n\n // Pre-register all virtual items so filtering works for unmounted items\n this.preRegisterVirtualItems()\n\n // Skip if items reference didn't change (same array)\n if (items === prevItems) {\n return\n }\n\n // Skip highlight validation if not in the right state\n if (!this.state.virtualized || !this.state.open || items.length === 0) {\n return\n }\n\n // Determine if we need to force highlight the first item\n const prevFirstItem = prevItems.find((item) => !item.disabled)\n const newFirstItem = items.find((item) => !item.disabled)\n const firstItemChanged = newFirstItem?.value !== prevFirstItem?.value\n\n // Validate and potentially update the highlight\n this.validateHighlight({ forceFirst: firstItemChanged })\n }\n\n /**\n * Set the consumer-provided ordered items.\n * Used when filter={false} and consumer controls item order/visibility.\n * Must always be provided when filter={false}.\n *\n * @param items - Array of item IDs in display order\n */\n setOrderedItems(items: string[]) {\n const prevItems = this.context.orderedItems\n this.context.orderedItems = items\n\n // Skip if items reference didn't change (same array)\n if (items === prevItems) {\n return\n }\n\n // Skip highlight update if not open\n if (!this.state.open) {\n return\n }\n\n // When ordered items change, highlight the first registered item\n // Use 'auto' source to indicate this is automatic (not user-initiated)\n // This prevents submenus from auto-opening\n if (items.length > 0) {\n const firstRegisteredItem = items.find((id) => this.context.items.has(id))\n if (firstRegisteredItem !== undefined) {\n this.setHighlightedId(firstRegisteredItem, 'auto')\n } else {\n this.setHighlightedId(null)\n }\n } else {\n this.setHighlightedId(null)\n }\n }\n\n /**\n * Try to auto-highlight when an item registers.\n * This handles the case where orderedItems was set before items mounted.\n * Only highlights if:\n * - filter={false} (using orderedItems)\n * - Menu is open\n * - No item is currently highlighted\n * - autoHighlightFirst is enabled\n * - The registering item is the first in orderedItems\n */\n private maybeAutoHighlightOnRegister(id: string) {\n if (this.context.filter !== false) {\n return\n }\n if (!this.state.open) {\n return\n }\n if (this.state.highlightedId !== null) {\n return\n }\n if (!this.context.autoHighlightFirst) {\n return\n }\n\n const orderedItems = this.context.orderedItems\n if (orderedItems.length === 0) {\n return\n }\n\n // Find the first item in orderedItems that is registered\n const firstRegisteredItem = orderedItems.find((itemId) =>\n this.context.items.has(itemId),\n )\n\n // Only highlight if this is the first registered item\n // Use 'auto' source to indicate this is automatic (not user-initiated)\n if (firstRegisteredItem === id) {\n this.setHighlightedId(id, 'auto')\n }\n }\n\n setOnHighlightChange(\n callback:\n | ((\n id: string | null,\n index: number,\n eventDetails: HighlightChangeEventDetails,\n ) => void)\n | undefined,\n ) {\n this.context.onHighlightChange = callback\n }\n\n // ============================================================================\n // DOM Refs Management\n // ============================================================================\n\n /**\n * Set the list element ref for scroll container detection.\n */\n setListRef(ref: React.RefObject<HTMLElement | null>) {\n this.context.refs.listRef = ref\n }\n\n /**\n * Register an item's DOM ref for scrollIntoView behavior.\n * Returns a cleanup function.\n */\n registerItemRef(\n id: string,\n ref: React.RefObject<HTMLElement | null>,\n ): () => void {\n this.context.refs.itemRefs.set(id, ref)\n return () => {\n this.context.refs.itemRefs.delete(id)\n }\n }\n\n // ============================================================================\n // Pointer Position Tracking\n // ============================================================================\n\n /**\n * Check if pointer has moved and should allow highlight.\n * This prevents \"phantom\" highlights when content shifts under a stationary pointer\n * (e.g., when search results change or menu items reorder).\n *\n * @param x - Current pointer X position\n * @param y - Current pointer Y position\n * @returns true if pointer has actually moved and highlight should be allowed\n */\n shouldAllowPointerHighlight(x: number, y: number): boolean {\n const last = this.context.lastPointerPosition\n if (last === null) {\n // First pointer event - record position and allow highlight\n this.context.lastPointerPosition = { x, y }\n return true\n }\n\n // Check if pointer has actually moved (with small tolerance for sub-pixel movements)\n const dx = Math.abs(x - last.x)\n const dy = Math.abs(y - last.y)\n const hasMoved = dx > 1 || dy > 1\n\n if (hasMoved) {\n // Update position and allow highlight\n this.context.lastPointerPosition = { x, y }\n return true\n }\n\n // Pointer hasn't moved - don't allow highlight\n return false\n }\n\n /**\n * Reset pointer position tracking.\n * Call this when the menu opens or content changes significantly.\n */\n resetPointerPosition() {\n this.context.lastPointerPosition = null\n }\n\n /**\n * Pre-register virtual items so they appear in filteredItems.\n * This allows filtering to work for items that aren't mounted yet.\n */\n private preRegisterVirtualItems() {\n const virtualItems = this.context.virtualItems\n if (virtualItems.length === 0) return\n\n // Register each virtual item (using value as the unique identifier)\n for (const item of virtualItems) {\n if (!this.context.items.has(item.value)) {\n this.context.items.set(item.value, {\n value: item.value,\n keywords: item.keywords,\n disabled: item.disabled,\n })\n }\n }\n\n // Recompute filtered items to include virtual items\n this.recomputeFilteredItems()\n }\n\n // ============================================================================\n // Item Registration\n // ============================================================================\n\n registerItem(id: string, registration: ItemRegistration): () => void {\n // Check if this item is already registered with the same properties\n // This optimization reduces unnecessary recomputation in virtualized mode\n const existing = this.context.items.get(id)\n const isSameRegistration =\n existing &&\n existing.value === registration.value &&\n existing.disabled === registration.disabled &&\n existing.groupId === registration.groupId &&\n existing.shortcut === registration.shortcut\n\n if (isSameRegistration) {\n // Item already registered with same properties, skip recompute\n return () => {\n // Only clean up if this item is still in the map\n // (another registration might have replaced it)\n if (this.context.items.get(id) === existing) {\n this.context.items.delete(id)\n this.context.itemSelects.delete(id)\n if (registration.groupId) {\n this.context.groups.get(registration.groupId)?.delete(id)\n }\n if (registration.shortcut) {\n this.context.shortcuts.delete(registration.shortcut.toLowerCase())\n }\n this.recomputeFilteredItems()\n }\n }\n }\n\n this.context.items.set(id, registration)\n\n // Add to group if specified\n if (registration.groupId) {\n const groupItems = this.context.groups.get(registration.groupId)\n if (groupItems) {\n groupItems.add(id)\n }\n }\n\n // Register shortcut if specified\n if (registration.shortcut) {\n const key = registration.shortcut.toLowerCase()\n this.context.shortcuts.set(key, id)\n }\n\n // Trigger recompute\n this.recomputeFilteredItems()\n\n // When filter={false} and we're open with no highlight, try to highlight\n // This handles the case where orderedItems was set before items mounted\n this.maybeAutoHighlightOnRegister(id)\n\n return () => {\n this.context.items.delete(id)\n this.context.itemSelects.delete(id)\n\n if (registration.groupId) {\n const groupItems = this.context.groups.get(registration.groupId)\n if (groupItems) {\n groupItems.delete(id)\n }\n }\n\n // Unregister shortcut\n if (registration.shortcut) {\n const key = registration.shortcut.toLowerCase()\n this.context.shortcuts.delete(key)\n }\n\n this.recomputeFilteredItems()\n }\n }\n\n registerGroup(id: string): () => void {\n this.context.groups.set(id, new Set())\n\n return () => {\n this.context.groups.delete(id)\n }\n }\n\n registerItemSelect(\n id: string,\n onSelect: (() => void) | undefined,\n ): () => void {\n if (onSelect) {\n this.context.itemSelects.set(id, onSelect)\n }\n return () => {\n this.context.itemSelects.delete(id)\n }\n }\n\n registerSubmenuOpen(\n id: string,\n onOpen: (() => void) | undefined,\n ): () => void {\n if (onOpen) {\n this.context.submenuOpens.set(id, onOpen)\n }\n return () => {\n this.context.submenuOpens.delete(id)\n }\n }\n\n registerSubmenuClose(\n id: string,\n onClose: (() => void) | undefined,\n ): () => void {\n if (onClose) {\n this.context.submenuCloses.set(id, onClose)\n }\n return () => {\n this.context.submenuCloses.delete(id)\n }\n }\n\n /**\n * Close all submenus except the one with the given ID.\n * Used when hovering over a new submenu trigger to close sibling submenus.\n */\n closeSiblingSubmenus(exceptId: string | null) {\n for (const [id, onClose] of this.context.submenuCloses) {\n if (id !== exceptId) {\n try {\n onClose()\n } catch {\n // Ignore errors from closing submenus\n }\n }\n }\n }\n\n // ============================================================================\n // Navigation\n // ============================================================================\n\n highlightNext() {\n const visibleIds = this.getVisibleItemIds()\n\n if (visibleIds.length === 0) return\n\n const currentIndex = this.state.highlightedId\n ? visibleIds.indexOf(this.state.highlightedId)\n : -1\n let nextIndex = currentIndex + 1\n\n if (nextIndex >= visibleIds.length) {\n nextIndex = this.context.loop ? 0 : visibleIds.length - 1\n }\n\n const nextId = visibleIds[nextIndex]\n\n if (nextId) {\n this.setHighlightedId(nextId, 'keyboard')\n }\n }\n\n highlightPrev() {\n const visibleIds = this.getVisibleItemIds()\n\n if (visibleIds.length === 0) return\n\n const currentIndex = this.state.highlightedId\n ? visibleIds.indexOf(this.state.highlightedId)\n : visibleIds.length\n let prevIndex = currentIndex - 1\n\n if (prevIndex < 0) {\n prevIndex = this.context.loop ? visibleIds.length - 1 : 0\n }\n\n const prevId = visibleIds[prevIndex]\n\n if (prevId) {\n this.setHighlightedId(prevId, 'keyboard')\n }\n }\n\n selectHighlighted() {\n if (this.state.highlightedId) {\n const onSelect = this.context.itemSelects.get(this.state.highlightedId)\n onSelect?.()\n }\n }\n\n /**\n * Select an item by its keyboard shortcut.\n * Returns true if an item was found and selected, false otherwise.\n */\n selectByShortcut(key: string): boolean {\n const itemId = this.context.shortcuts.get(key.toLowerCase())\n if (!itemId) return false\n\n const registration = this.context.items.get(itemId)\n if (!registration || registration.disabled) return false\n\n // Check if item is visible (passes filter)\n const score = this.state.filteredItems.get(itemId) ?? 0\n const isVisible = this.state.search.length === 0 || score > 0\n if (!isVisible) return false\n\n const onSelect = this.context.itemSelects.get(itemId)\n onSelect?.()\n return true\n }\n\n openSubmenuForHighlighted() {\n if (this.state.highlightedId) {\n const onOpen = this.context.submenuOpens.get(this.state.highlightedId)\n onOpen?.()\n }\n }\n\n isHighlightedSubmenuTrigger(): boolean {\n if (!this.state.highlightedId) return false\n return (\n this.context.items.get(this.state.highlightedId)?.isSubmenuTrigger ??\n false\n )\n }\n\n /**\n * Get the item registration for the highlighted item.\n * Returns undefined if no item is highlighted.\n */\n getHighlightedItem(): ItemRegistration | undefined {\n if (!this.state.highlightedId) return undefined\n return this.context.items.get(this.state.highlightedId)\n }\n\n clearSearch() {\n this.setSearch('')\n }\n\n highlightFirstItem() {\n const visibleIds = this.getVisibleItemIds()\n if (visibleIds.length > 0 && visibleIds[0]) {\n // Don't set a cause - auto-highlight shouldn't trigger scroll\n this.update({ highlightedId: visibleIds[0], highlightSource: null })\n } else {\n this.update({ highlightedId: null, highlightSource: null })\n }\n }\n\n /**\n * Apply auto-highlight based on the current context.autoHighlightFirst value.\n * Called by Surface after updating the context to ensure correct value is used.\n */\n applyAutoHighlight() {\n if (!this.state.open) return\n\n const autoHighlight = this.context.autoHighlightFirst\n if (autoHighlight === true) {\n this.highlightFirstItem()\n } else if (typeof autoHighlight === 'string') {\n this.highlightItemByValue(autoHighlight)\n }\n // If false, don't highlight anything\n }\n\n /**\n * Highlight a specific item by its value.\n * If the item is not visible or doesn't exist, falls back to highlighting the first item.\n * Scrolls the highlighted item into view.\n */\n highlightItemByValue(value: string) {\n const visibleIds = this.getVisibleItemIds()\n let highlightedId: string | null = null\n\n if (visibleIds.includes(value)) {\n // Item exists and is visible - highlight it\n highlightedId = value\n } else if (visibleIds.length > 0 && visibleIds[0]) {\n // Fall back to first item if specified value not found\n highlightedId = visibleIds[0]\n }\n\n this.update({ highlightedId, highlightSource: null })\n\n // Scroll the highlighted item into view\n // This is important when opening a combobox with a pre-selected value\n // that may be far down the list\n if (highlightedId) {\n // Use requestAnimationFrame to ensure the DOM has updated\n requestAnimationFrame(() => {\n this.scrollItemIntoView(highlightedId)\n })\n }\n }\n\n // ============================================================================\n // Internal Helpers\n // ============================================================================\n\n /**\n * Returns whether filtering is disabled (consumer handles filtering externally).\n */\n isFilterDisabled(): boolean {\n return this.context.filter === false\n }\n\n getVisibleItemIds(): string[] {\n const result: string[] = []\n const search = this.state.search\n const filteredItems = this.state.filteredItems\n const virtualItems = this.context.virtualItems\n const orderedItems = this.context.orderedItems\n\n // When virtualized with items, use the virtualItems order\n // This ensures navigation order matches the data array order\n if (this.state.virtualized && virtualItems.length > 0) {\n for (const item of virtualItems) {\n const score = filteredItems.get(item.value) ?? 0\n const isVisible = search.length === 0 || score > 0\n if (isVisible && !item.disabled) {\n result.push(item.value)\n }\n }\n return result\n }\n\n // When consumer provides ordered items (filter={false}), use that order\n // This ensures navigation matches the consumer's intended display order\n if (this.context.filter === false && orderedItems.length > 0) {\n // Track unregistered items for warning\n const unregisteredItems: string[] = []\n\n for (const itemId of orderedItems) {\n const registration = this.context.items.get(itemId)\n // Only include if registered (mounted) and not disabled\n if (registration && !registration.disabled) {\n result.push(itemId)\n } else if (!registration) {\n unregisteredItems.push(itemId)\n }\n }\n\n // Only warn about unregistered items if SOME items are registered\n // If no items are registered, we're likely in the initial mount phase\n // and items will register shortly via maybeAutoHighlightOnRegister\n if (\n process.env.NODE_ENV !== 'production' &&\n unregisteredItems.length > 0 &&\n result.length > 0\n ) {\n for (const itemId of unregisteredItems) {\n console.warn(\n `[ListboxStore] Item \"${itemId}\" is in orderedItems but not registered. ` +\n 'This may cause keyboard navigation to skip this item. ' +\n 'Make sure the render function passes the `id` prop: <Item {...props}>...</Item>',\n )\n }\n }\n\n return result\n }\n\n // Non-virtualized: use mounted items order\n this.context.items.forEach((registration, id) => {\n const score = filteredItems.get(id) ?? 0\n const isVisible = search.length === 0 || score > 0\n if (isVisible && !registration.disabled) {\n result.push(id)\n }\n })\n\n return result\n }\n\n /**\n * Get the index of an item in the visible items list.\n * Returns -1 if the item is not found or not visible.\n */\n getVisibleItemIndex(id: string): number {\n return this.getVisibleItemIds().indexOf(id)\n }\n\n /**\n * Get the index of an item in the virtualItems array.\n * This is used for virtualizer scrollToIndex which needs the raw array index,\n * not the filtered/visible index.\n * Returns -1 if not found or not in virtualized mode.\n */\n getVirtualItemIndex(value: string): number {\n if (!this.state.virtualized) return -1\n return this.context.virtualItems.findIndex((item) => item.value === value)\n }\n\n /**\n * Validates and updates the highlighted item.\n * This is the single source of truth for highlight management.\n *\n * @param options.forceFirst - Force highlight first item even if current is valid\n * @param options.filteredItems - Use this map instead of state (for mid-update calls)\n * @param options.newSearch - The search query for filteredItems (to detect search cleared)\n */\n private validateHighlight(\n options: ValidateHighlightOptions = {},\n ): string | null {\n const {\n forceFirst = false,\n filteredItems = this.state.filteredItems,\n newSearch,\n prevSearch: optionsPrevSearch,\n } = options\n\n // Determine if search changed (requires reset to first item)\n // Use prevSearch from options if provided (from observer), otherwise fall back to state\n const prevSearch =\n optionsPrevSearch !== undefined ? optionsPrevSearch : this.state.search\n const effectiveSearch = newSearch !== undefined ? newSearch : prevSearch\n const searchChanged = newSearch !== undefined && newSearch !== prevSearch\n\n // If not open or autoHighlightFirst disabled, don't change anything\n if (!this.state.open || !this.context.autoHighlightFirst) {\n return this.state.highlightedId\n }\n\n const currentHighlight = this.state.highlightedId\n const { filter } = this.context\n\n // If search changed, force reset to first item\n const shouldForceFirst = forceFirst || searchChanged\n\n // Check if current highlight is valid\n let isCurrentValid = false\n if (currentHighlight && !shouldForceFirst) {\n // Check if item exists and passes filter\n const score = filteredItems.get(currentHighlight) ?? 0\n const isVisible =\n effectiveSearch.length === 0 || filter === false || score > 0\n\n // Check if item is disabled\n const registration = this.context.items.get(currentHighlight)\n const virtualItem = this.context.virtualItems.find(\n (v) => v.value === currentHighlight,\n )\n const isDisabled =\n registration?.disabled ?? virtualItem?.disabled ?? false\n\n // Item must be registered (in items map) for non-virtualized mode\n const isRegistered = this.state.virtualized || registration !== undefined\n\n // In virtualized mode, item must also be in virtualItems array\n const inVirtualItems =\n !this.state.virtualized ||\n this.context.virtualItems.length === 0 ||\n virtualItem !== undefined\n\n isCurrentValid =\n isVisible && !isDisabled && isRegistered && inVirtualItems\n }\n\n // If current highlight is valid and we're not forcing first, keep it\n if (isCurrentValid) {\n return currentHighlight\n }\n\n // Find the first valid item to highlight\n let newHighlightId: string | null = null\n\n if (this.state.virtualized && this.context.virtualItems.length > 0) {\n // Virtualized mode: use virtualItems order\n for (const item of this.context.virtualItems) {\n const score = filteredItems.get(item.value) ?? 0\n const isVisible =\n effectiveSearch.length === 0 || filter === false || score > 0\n if (isVisible && !item.disabled) {\n newHighlightId = item.value\n break\n }\n }\n } else if (filter === false && this.context.orderedItems.length > 0) {\n // Consumer-controlled filtering: use orderedItems order\n for (const itemId of this.context.orderedItems) {\n const registration = this.context.items.get(itemId)\n // Only include if registered (mounted) and not disabled\n if (registration && !registration.disabled) {\n newHighlightId = itemId\n break\n }\n }\n } else {\n // Non-virtualized mode: use mounted items\n for (const [id, registration] of this.context.items) {\n const score = filteredItems.get(id) ?? 0\n const isVisible = effectiveSearch.length === 0 || score > 0\n if (isVisible && !registration.disabled) {\n newHighlightId = id\n break\n }\n }\n }\n\n // Only update if highlight actually changed\n if (newHighlightId !== currentHighlight) {\n this.update({\n highlightedId: newHighlightId,\n highlightSource: null, // Auto-highlight shouldn't trigger scroll\n })\n }\n\n return newHighlightId\n }\n\n private recomputeFilteredItems(prevSearch?: string) {\n const { filter } = this.context\n const search = this.state.search\n const items = this.context.items\n const groups = this.context.groups\n\n const filteredItems = new Map<string, number>()\n const visibleGroups = new Set<string>()\n let filteredCount = 0\n\n // If no search or filtering disabled, all items are visible\n if (!search || filter === false) {\n // When virtualized with consumer-side filtering (filter === false),\n // use virtualItems as the source of truth for what's visible.\n // This ensures the scores match the consumer's filtered array,\n // not just what's currently mounted.\n if (this.state.virtualized && this.context.virtualItems.length > 0) {\n for (const item of this.context.virtualItems) {\n filteredItems.set(item.value, 1)\n filteredCount++\n }\n } else {\n items.forEach((_, id) => {\n filteredItems.set(id, 1)\n filteredCount++\n })\n }\n groups.forEach((_, groupId) => {\n visibleGroups.add(groupId)\n })\n } else {\n // Apply filter function\n const filterFn = filter || commandScore\n items.forEach((registration, id) => {\n const score = filterFn(\n registration.value,\n search,\n registration.keywords,\n )\n filteredItems.set(id, score)\n if (score > 0) {\n filteredCount++\n if (registration.groupId) {\n visibleGroups.add(registration.groupId)\n }\n }\n })\n }\n\n // When filter={false}, consumer controls highlighting via setConsumerFilteredItems.\n // Don't call validateHighlight here because consumerFilteredItems hasn't been updated yet.\n // The highlight will be set when setConsumerFilteredItems is called from the Surface effect.\n if (filter === false) {\n this.update({\n filteredItems,\n visibleGroups,\n filteredCount,\n filterTrigger: this.state.filterTrigger + 1,\n // Don't change highlight - let setConsumerFilteredItems handle it\n })\n return\n }\n\n // Validate highlight using the newly computed filteredItems\n // We pass filteredItems, newSearch, and prevSearch here because we need to detect search cleared\n const highlightedId = this.validateHighlight({\n filteredItems,\n newSearch: search,\n prevSearch,\n })\n\n this.update({\n filteredItems,\n visibleGroups,\n filteredCount,\n filterTrigger: this.state.filterTrigger + 1,\n highlightedId,\n // Auto-highlight shouldn't trigger scroll\n highlightSource: null,\n })\n }\n\n // ============================================================================\n // Static Factory\n // ============================================================================\n\n static useStore(\n externalStore: ListboxStore | undefined,\n initialState?: Partial<ListboxState>,\n context?: Partial<ListboxContext>,\n ): ListboxStore {\n const store = useRefWithInit(() => {\n return externalStore ?? new ListboxStore(initialState, context)\n }).current\n\n return store\n }\n}\n\n// ============================================================================\n// Initial State Factory\n// ============================================================================\n\nfunction createInitialState(): ListboxState {\n return {\n open: false,\n search: '',\n highlightedId: null,\n highlightSource: null,\n hasInput: false,\n inputActive: false,\n pendingSearch: '',\n filteredItems: new Map(),\n visibleGroups: new Set(),\n filteredCount: 0,\n filterTrigger: 0,\n virtualized: false,\n virtualItemsCount: 0,\n }\n}\n\n// ============================================================================\n// Re-export types for convenience\n// ============================================================================\n\nexport type { ListboxState as State, ListboxContext as Context }\n","/**\n * Fuzzy matching algorithm for command palette-style filtering.\n * Vendored from cmdk (https://github.com/pacocoursey/cmdk)\n *\n * The scores are arranged so that a continuous match of characters will\n * result in a total score of 1.\n */\n\n// The best case: this character is a match, and either this is the start\n// of the string, or the previous character was also a match.\nconst SCORE_CONTINUE_MATCH = 1\n\n// A new match at the start of a word scores better than a new match\n// elsewhere as it's more likely that the user will type the starts\n// of fragments.\n// NOTE: We score word jumps between spaces slightly higher than slashes, brackets, hyphens, etc.\nconst SCORE_SPACE_WORD_JUMP = 0.9\nconst SCORE_NON_SPACE_WORD_JUMP = 0.8\n\n// Any other match isn't ideal, but we include it for completeness.\nconst SCORE_CHARACTER_JUMP = 0.17\n\n// If the user transposed two letters, it should be significantly penalized.\n// i.e. \"ouch\" is more likely than \"curtain\" when \"uc\" is typed.\nconst SCORE_TRANSPOSITION = 0.1\n\n// The goodness of a match should decay slightly with each missing character.\n// i.e. \"bad\" is more likely than \"bard\" when \"bd\" is typed.\n// This will not change the order of suggestions based on SCORE_* until\n// 100 characters are inserted between matches.\nconst PENALTY_SKIPPED = 0.999\n\n// The goodness of an exact-case match should be higher than a\n// case-insensitive match by a small amount.\n// i.e. \"HTML\" is more likely than \"haml\" when \"HM\" is typed.\n// This will not change the order of suggestions based on SCORE_* until\n// 1000 characters are inserted between matches.\nconst PENALTY_CASE_MISMATCH = 0.9999\n\n// Match higher for letters closer to the beginning of the word\nconst PENALTY_DISTANCE_FROM_START = 0.9\n\n// If the word has more characters than the user typed, it should\n// be penalised slightly.\n// i.e. \"html\" is more likely than \"html5\" if I type \"html\".\n// However, it may well be the case that there's a sensible secondary\n// ordering (like alphabetical) that it makes sense to rely on when\n// there are many prefix matches, so we don't make the penalty increase\n// with the number of tokens.\nconst PENALTY_NOT_COMPLETE = 0.99\n\nconst IS_GAP_REGEXP = /[\\\\/_+.#\"@[({&]/\nconst COUNT_GAPS_REGEXP = /[\\\\/_+.#\"@[({&]/g\nconst IS_SPACE_REGEXP = /[\\s-]/\nconst COUNT_SPACE_REGEXP = /[\\s-]/g\n\ntype MemoizedResults = Record<string, number>\n\nfunction commandScoreInner(\n string: string,\n abbreviation: string,\n lowerString: string,\n lowerAbbreviation: string,\n stringIndex: number,\n abbreviationIndex: number,\n memoizedResults: MemoizedResults,\n): number {\n if (abbreviationIndex === abbreviation.length) {\n if (stringIndex === string.length) {\n return SCORE_CONTINUE_MATCH\n }\n return PENALTY_NOT_COMPLETE\n }\n\n const memoizeKey = `${stringIndex},${abbreviationIndex}`\n if (memoizedResults[memoizeKey] !== undefined) {\n return memoizedResults[memoizeKey]\n }\n\n const abbreviationChar = lowerAbbreviation.charAt(abbreviationIndex)\n let index = lowerString.indexOf(abbreviationChar, stringIndex)\n let highScore = 0\n\n let score: number\n let transposedScore: number\n let wordBreaks: RegExpMatchArray | null\n let spaceBreaks: RegExpMatchArray | null\n\n while (index >= 0) {\n score = commandScoreInner(\n string,\n abbreviation,\n lowerString,\n lowerAbbreviation,\n index + 1,\n abbreviationIndex + 1,\n memoizedResults,\n )\n\n if (score > highScore) {\n if (index === stringIndex) {\n score *= SCORE_CONTINUE_MATCH\n } else if (IS_GAP_REGEXP.test(string.charAt(index - 1))) {\n score *= SCORE_NON_SPACE_WORD_JUMP\n wordBreaks = string\n .slice(stringIndex, index - 1)\n .match(COUNT_GAPS_REGEXP)\n if (wordBreaks && stringIndex > 0) {\n score *= PENALTY_SKIPPED ** wordBreaks.length\n }\n } else if (IS_SPACE_REGEXP.test(string.charAt(index - 1))) {\n score *= SCORE_SPACE_WORD_JUMP\n spaceBreaks = string\n .slice(stringIndex, index - 1)\n .match(COUNT_SPACE_REGEXP)\n if (spaceBreaks && stringIndex > 0) {\n score *= PENALTY_SKIPPED ** spaceBreaks.length\n }\n } else {\n score *= SCORE_CHARACTER_JUMP\n if (stringIndex > 0) {\n score *= PENALTY_SKIPPED ** (index - stringIndex)\n }\n }\n\n if (string.charAt(index) !== abbreviation.charAt(abbreviationIndex)) {\n score *= PENALTY_CASE_MISMATCH\n }\n }\n\n if (\n (score < SCORE_TRANSPOSITION &&\n lowerString.charAt(index - 1) ===\n lowerAbbreviation.charAt(abbreviationIndex + 1)) ||\n (lowerAbbreviation.charAt(abbreviationIndex + 1) ===\n lowerAbbreviation.charAt(abbreviationIndex) &&\n lowerString.charAt(index - 1) !==\n lowerAbbreviation.charAt(abbreviationIndex))\n ) {\n transposedScore = commandScoreInner(\n string,\n abbreviation,\n lowerString,\n lowerAbbreviation,\n index + 1,\n abbreviationIndex + 2,\n memoizedResults,\n )\n\n if (transposedScore * SCORE_TRANSPOSITION > score) {\n score = transposedScore * SCORE_TRANSPOSITION\n }\n }\n\n if (score > highScore) {\n highScore = score\n }\n\n index = lowerString.indexOf(abbreviationChar, index + 1)\n }\n\n memoizedResults[memoizeKey] = highScore\n return highScore\n}\n\nfunction formatInput(string: string): string {\n // Convert all valid space characters to space so they match each other\n return string.toLowerCase().replace(COUNT_SPACE_REGEXP, ' ')\n}\n\n/**\n * Calculates a fuzzy match score between a string and an abbreviation.\n *\n * @param string - The string to match against\n * @param abbreviation - The search query\n * @param keywords - Optional additional keywords to include in matching\n * @returns A score between 0 and 1, where 1 is a perfect match and 0 is no match\n */\nexport function commandScore(\n string: string,\n abbreviation: string,\n keywords?: string[],\n): number {\n if (!abbreviation) return 1\n if (!string) return 0\n\n // Combine string with keywords for matching\n const fullString =\n keywords && keywords.length > 0 ? `${string} ${keywords.join(' ')}` : string\n\n return commandScoreInner(\n fullString,\n abbreviation,\n formatInput(fullString),\n formatInput(abbreviation),\n 0,\n 0,\n {},\n )\n}\n\n/**\n * Default filter function for listbox items.\n * Returns a score > 0 for matches, 0 for non-matches.\n */\nexport const defaultFilter = commandScore\n","export enum PopupMenuArrowDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-arrow' | 'bazzaui-context-menu-arrow' | 'bazzaui-select-arrow' | 'bazzaui-combobox-arrow'}\n */\n slot = 'bazzaui-[component]-arrow',\n /**\n * Present when the popup menu is open.\n */\n open = 'data-open',\n /**\n * Present when the popup menu is closed.\n */\n closed = 'data-closed',\n /**\n * Indicates which side the popup is positioned relative to the trigger.\n * @type {'top' | 'bottom' | 'left' | 'right' | 'inline-end' | 'inline-start'}\n */\n side = 'data-side',\n /**\n * Indicates how the popup is aligned relative to specified side.\n * @type {'start' | 'center' | 'end'}\n */\n align = 'data-align',\n /**\n * Present when the arrow is not centered due to collision avoidance.\n */\n uncentered = 'data-uncentered',\n}\n","'use client'\n\nimport { Popover, type PopoverArrowProps } from '@base-ui/react/popover'\nimport * as React from 'react'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\n\nexport interface PopupMenuArrowProps extends PopoverArrowProps {}\n\n/**\n * An optional arrow element to render alongside the popup menu.\n * This can be used to help visually link the trigger with the popup.\n * Must be rendered inside `Popup`.\n * Renders a `<div>` element.\n */\nexport const PopupMenuArrow = React.forwardRef<\n HTMLDivElement,\n PopupMenuArrowProps\n>(function PopupMenuArrow(props, forwardedRef) {\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'arrow')\n\n return (\n <Popover.Arrow\n ref={forwardedRef}\n {...(slotAttr ? { [slotAttr]: '' } : {})}\n {...props}\n />\n )\n})\n\nexport namespace PopupMenuArrow {\n export type Props = PopupMenuArrowProps\n export type State = Popover.Arrow.State\n}\n","export enum PopupMenuBackdropDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-backdrop' | 'bazzaui-context-menu-backdrop' | 'bazzaui-select-backdrop' | 'bazzaui-combobox-backdrop'}\n */\n slot = 'bazzaui-[component]-backdrop',\n /**\n * Present when the popup menu is open.\n */\n open = 'data-open',\n /**\n * Present when the popup menu is closed.\n */\n closed = 'data-closed',\n /**\n * Present when the popup menu is animating in.\n */\n startingStyle = 'data-starting-style',\n /**\n * Present when the popup menu is animating out.\n */\n endingStyle = 'data-ending-style',\n}\n","'use client'\n\nimport { Popover, type PopoverBackdropProps } from '@base-ui/react/popover'\nimport * as React from 'react'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport {\n useFocusOwner,\n useMaybeSubmenuContext,\n useOpenChain,\n} from '../../index.js'\n\nexport interface PopupMenuBackdropProps extends PopoverBackdropProps {\n /**\n * Controls when the backdrop becomes visible for submenus.\n * - `\"focus\"`: Show when the submenu becomes the focus owner (prevents flicker on hover).\n * If a deeper submenu is open, the backdrop remains visible.\n * - `\"open\"`: Show as soon as the submenu opens, regardless of focus.\n *\n * @default \"focus\" for submenus, \"open\" for root menu\n */\n showOn?: 'focus' | 'open'\n}\n\n/**\n * An overlay displayed beneath the popup menu.\n *\n * For submenus with `showOn=\"focus\"` (default), the backdrop visibility follows these rules:\n * - If this submenu is at the end of the open chain (deepest), it must be\n * the focus owner to show the backdrop (prevents flicker on hover)\n * - If this submenu is in the chain but not at the end (has a deeper submenu open),\n * the backdrop remains visible\n *\n * With `showOn=\"open\"`, the backdrop shows as soon as the submenu opens.\n *\n * Renders a `<div>` element with `pointer-events: none`.\n */\nexport const PopupMenuBackdrop = React.forwardRef<\n HTMLDivElement,\n PopupMenuBackdrop.Props\n>(function PopupMenuBackdrop(props, forwardedRef) {\n const { showOn: showOnProp, ...rest } = props\n\n const submenuContext = useMaybeSubmenuContext()\n const openChainStore = useOpenChain()\n const focusOwnerStore = useFocusOwner()\n\n const isSubmenu = submenuContext !== null\n const surfaceId = submenuContext?.childSurfaceId ?? ''\n\n // Default: \"focus\" for submenus, \"open\" for root\n const showOn = showOnProp ?? (isSubmenu ? 'focus' : 'open')\n\n // Check if this surface is in the open chain\n const isInOpenChain = openChainStore.useState('isOpen', surfaceId)\n\n // Check if this surface is the last (deepest) in the chain\n const isLastInChain = openChainStore.useState('isLast', surfaceId)\n\n // Check if this surface is the focus owner\n const isFocusOwner = focusOwnerStore.useState('isOwner', surfaceId)\n\n // Determine visibility\n let shouldShow = true\n if (isSubmenu) {\n if (showOn === 'open') {\n // Show as soon as submenu is open\n shouldShow = isInOpenChain\n } else {\n // showOn === 'focus'\n if (isLastInChain) {\n // Deepest submenu: only show if we're the focus owner\n shouldShow = isFocusOwner\n } else {\n // Not the deepest: show if we're in the chain (a deeper submenu is open)\n shouldShow = isInOpenChain\n }\n }\n }\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'backdrop')\n\n if (!shouldShow) {\n return null\n }\n\n // Merge pointer-events: none into style to prevent backdrop from\n // intercepting pointer events meant for the menu\n const style: React.CSSProperties = {\n pointerEvents: 'none',\n ...rest.style,\n }\n\n return (\n <Popover.Backdrop\n ref={forwardedRef}\n {...(slotAttr ? { [slotAttr]: '' } : {})}\n {...rest}\n style={style}\n />\n )\n})\n\nexport namespace PopupMenuBackdrop {\n export type Props = PopupMenuBackdropProps\n export type State = Popover.Backdrop.State\n}\n","export enum PopupMenuPopupDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-popup' | 'bazzaui-context-menu-popup' | 'bazzaui-select-popup' | 'bazzaui-combobox-popup'}\n */\n slot = 'bazzaui-[component]-popup',\n /**\n * Present when the popup menu is open.\n */\n open = 'data-open',\n /**\n * Present when the popup menu is closed.\n */\n closed = 'data-closed',\n /**\n * Indicates which side the popup is positioned relative to the trigger.\n * @type {'top' | 'bottom' | 'left' | 'right'}\n */\n side = 'data-side',\n /**\n * Indicates how the popup is aligned relative to specified side.\n * @type {'start' | 'center' | 'end'}\n */\n align = 'data-align',\n /**\n * Present when the popup is animating in.\n */\n startingStyle = 'data-starting-style',\n /**\n * Present when the popup is animating out.\n */\n endingStyle = 'data-ending-style',\n /**\n * Present if animations should be instant.\n * @type {'click' | 'dismiss'}\n */\n instant = 'data-instant',\n /**\n * Present when this popup's surface is the focus owner.\n * Useful for styling the currently focused menu in a submenu chain.\n */\n focused = 'data-focused',\n /**\n * Present when this popup has an open submenu below it in the menu tree.\n * Useful for styling all parent menus in an open submenu chain.\n */\n hasOpenSubmenu = 'data-has-open-submenu',\n /**\n * Present when this popup is a submenu (not the root menu).\n * Useful for applying different styles to submenus vs root menus.\n */\n submenu = 'data-submenu',\n}\n","'use client'\n\nimport { Popover, type PopoverPopupProps } from '@base-ui/react/popover'\nimport * as React from 'react'\nimport { useMaybeComboboxContext } from '../../../../combobox/contexts/combobox-context.js'\nimport { POINTER_EVENT_DEBOUNCE_MS } from '../../constants.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { useFocusOwner } from '../../contexts/focus-owner-context.js'\nimport { useOpenChain } from '../../contexts/open-chain-context.js'\nimport { useMaybePopupMenuContext } from '../../contexts/popup-menu-context.js'\nimport { PopupSurfaceIdContext } from '../../contexts/popup-surface-id-context.js'\nimport { useMaybeSubmenuContext } from '../../contexts/submenu-context.js'\nimport { useAimGuard } from '../../hooks/use-aim-guard.js'\nimport { PopupMenuPopupDataAttributes } from './popup.data-attrs.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PopupMenuPopupState extends Popover.Popup.State {\n /**\n * Whether this popup is a submenu (not the root menu).\n */\n isSubmenu: boolean\n}\n\nexport interface PopupMenuPopupProps\n extends Omit<PopoverPopupProps, 'className'> {\n /**\n * CSS class applied to the element, or a function that\n * returns a class based on the component's state.\n */\n className?: string | ((state: PopupMenuPopupState) => string)\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * A container for the popup menu contents.\n * Wraps Popover.Popup with:\n * - Aim guard clearing when pointer enters submenu\n * - Focus ownership transfer when pointer enters submenu\n * - Auto-focus disabled for submenus (focus managed by FocusOwner system)\n *\n * Renders a `<div>` element.\n */\nexport const PopupMenuPopup = React.forwardRef<\n HTMLDivElement,\n PopupMenuPopup.Props\n>(function PopupMenuPopup(props, forwardedRef) {\n const { children, className: classNameProp, ...rest } = props\n\n // Get submenu context to set contentRef for aim guard and get childSurfaceId for focus transfer\n const submenuContext = useMaybeSubmenuContext()\n\n // Get aim guard to clear it when pointer enters submenu\n const { clearAimGuard, aimGuardActiveRef, guardedSubmenuSurfaceIdRef } =\n useAimGuard()\n\n // Get focus owner store for transferring ownership\n const focusOwnerStore = useFocusOwner()\n\n // Get open chain store for tracking submenu chain\n const openChainStore = useOpenChain()\n\n // Get popup menu context for depth\n const popupMenuContext = useMaybePopupMenuContext()\n const depth = popupMenuContext?.depth ?? 0\n\n // Get combobox context to detect if we're inside a combobox and for layout\n const comboboxContext = useMaybeComboboxContext()\n\n // Generate surfaceId for root menus, use submenu context for submenus\n const generatedSurfaceId = React.useId()\n const surfaceId = submenuContext?.childSurfaceId ?? generatedSurfaceId\n\n // Track when popup opened to ignore initial pointer events\n // This prevents focus transfer when the popup appears under a stationary cursor\n const openTimeRef = React.useRef<number>(0)\n\n // Record open time when popup opens\n React.useEffect(() => {\n if (submenuContext?.open) {\n openTimeRef.current = Date.now()\n }\n }, [submenuContext?.open])\n\n // Subscribe to focus ownership for data-focused attribute\n const isFocused = focusOwnerStore.useState('isOwner', surfaceId)\n\n // Subscribe to open chain for data-has-open-submenu attribute\n const hasOpenSubmenu = openChainStore.useState('hasOpenSubmenu', depth)\n\n // Local ref for the popup element\n const popupRef = React.useRef<HTMLDivElement>(null)\n\n // Combine refs\n const combinedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n // Update local ref\n popupRef.current = node\n\n // Update forwarded ref\n if (typeof forwardedRef === 'function') {\n forwardedRef(node)\n } else if (forwardedRef) {\n forwardedRef.current = node\n }\n\n // Update submenu context contentRef for aim guard\n if (submenuContext?.contentRef) {\n ;(\n submenuContext.contentRef as React.MutableRefObject<HTMLElement | null>\n ).current = node\n }\n },\n [forwardedRef, submenuContext],\n )\n\n // Clear aim guard when pointer moves inside this submenu popup\n // Only clear if aim guard is actually active AND this is the target submenu\n const handlePointerMove = React.useCallback(() => {\n // Only handle if this is a submenu popup (not the root popup) and aim guard is active\n // Also verify this is the specific submenu the user was aiming for\n if (\n submenuContext &&\n aimGuardActiveRef.current &&\n guardedSubmenuSurfaceIdRef.current === surfaceId\n ) {\n clearAimGuard()\n }\n }, [\n submenuContext,\n aimGuardActiveRef,\n guardedSubmenuSurfaceIdRef,\n surfaceId,\n clearAimGuard,\n ])\n\n // Transfer focus ownership when pointer moves inside this submenu popup\n // We ignore events shortly after open to prevent focus transfer when\n // the popup appears under a stationary cursor\n const handleFocusTransferOnMove = React.useCallback(\n (event: React.PointerEvent) => {\n // Ignore pointer events briefly after popup opens\n // This prevents focus transfer when popup appears under stationary cursor\n const timeSinceOpen = Date.now() - openTimeRef.current\n if (timeSinceOpen < POINTER_EVENT_DEBOUNCE_MS) {\n return\n }\n\n // Only transfer focus if this is a submenu popup (not the root popup)\n // Use childSurfaceId from SubmenuContext since Popup is outside Surface in the component tree\n if (!submenuContext) {\n return\n }\n\n // Check if the event target is actually within this popup's DOM\n // This prevents parent popups from claiming ownership when events\n // bubble through React portals from child submenus\n const target = event.target as Node\n if (!popupRef.current?.contains(target)) {\n return\n }\n\n // Check if the target is inside a nested submenu popup\n // If so, don't claim ownership - let the nested popup handle it\n const targetElement =\n target instanceof Element ? target : target.parentElement\n if (targetElement) {\n // Find the closest popup ancestor of the target\n const closestPopup = targetElement.closest('[data-base-ui-focusable]')\n // If the closest popup is not this popup, don't claim ownership\n if (closestPopup && closestPopup !== popupRef.current) {\n return\n }\n }\n\n // Only claim ownership if we're not already the owner\n if (focusOwnerStore.state.ownerId !== submenuContext.childSurfaceId) {\n focusOwnerStore.setOwnerId(submenuContext.childSurfaceId)\n }\n },\n [submenuContext, focusOwnerStore],\n )\n\n // Disable Base UI's auto-focus behavior for:\n // - Submenus: Focus is managed by our FocusOwner system\n // - Combobox: Focus should stay on the input element (which is outside the popup)\n const initialFocus = submenuContext || comboboxContext ? false : undefined\n\n // Disable returning focus to trigger when popup closes for:\n // - Submenus: Focus is managed by our FocusOwner system (we transfer to parent surface's input/list)\n // - Combobox: When clicking outside, we want focus to go to whatever was clicked, not back to input\n const finalFocus = submenuContext || comboboxContext ? false : undefined\n\n // Add data-input-embedded attribute when layout is input-embedded\n const isInputEmbedded = comboboxContext?.layout === 'input-embedded'\n\n // Determine if this popup is a submenu (not the root menu)\n const isSubmenu = !!submenuContext\n\n // Wrap className to include isSubmenu in the state\n const className = React.useMemo(() => {\n if (typeof classNameProp === 'function') {\n return (baseState: Popover.Popup.State) => {\n const extendedState: PopupMenuPopupState = { ...baseState, isSubmenu }\n return classNameProp(extendedState)\n }\n }\n return classNameProp\n }, [classNameProp, isSubmenu])\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'popup')\n\n return (\n <PopupSurfaceIdContext.Provider value={surfaceId}>\n <Popover.Popup\n ref={combinedRef}\n initialFocus={initialFocus}\n finalFocus={finalFocus}\n className={className}\n data-input-embedded={isInputEmbedded ? '' : undefined}\n {...(slotAttr ? { [slotAttr]: '' } : {})}\n {...{\n [PopupMenuPopupDataAttributes.focused]: isFocused ? '' : undefined,\n [PopupMenuPopupDataAttributes.hasOpenSubmenu]: hasOpenSubmenu\n ? ''\n : undefined,\n [PopupMenuPopupDataAttributes.submenu]: isSubmenu ? '' : undefined,\n }}\n onPointerMove={(event) => {\n handlePointerMove()\n handleFocusTransferOnMove(event)\n rest.onPointerMove?.(event)\n }}\n {...rest}\n >\n {children}\n </Popover.Popup>\n </PopupSurfaceIdContext.Provider>\n )\n})\n\nexport namespace PopupMenuPopup {\n export type Props = PopupMenuPopupProps\n export type State = PopupMenuPopupState\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { ItemEqualityComparer } from '../../utils/item-equality.js'\nimport type { ComboboxOpenChangeReason } from '../events.js'\nimport type { ComboboxLayout } from './combobox-positioner-context.js'\n\n// ============================================================================\n// Combobox Context\n// ============================================================================\n// Provides value management, input state, and form integration for Combobox.\n\n/**\n * Filter mode for the combobox.\n * Controls how the search/filter value is determined.\n *\n * State transitions:\n * - Closed → open (no value) → { type: 'active' }\n * - Closed → open (with value) → { type: 'showAll' }\n * - Open + user types → { type: 'active' }\n * - Open → close → { type: 'frozen', search: <current> }\n */\nexport type ComboboxFilterMode =\n | { type: 'active' } // Normal: use inputValue for filtering\n | { type: 'showAll' } // Opened with selected value, user hasn't typed yet\n | { type: 'frozen'; search: string } // Closing: freeze to this value during exit animation\n\n/**\n * Item text registry for displaying selected values.\n * Maps serialized item value to its text content.\n */\nexport type ItemTextRegistry = Map<string, string>\n\n/**\n * Context value for Combobox components.\n * Provides value state, input state, callbacks, and form integration.\n *\n * @template Value - The type of the combobox value (can be a primitive or object)\n */\nexport interface ComboboxContextValue<Value = unknown> {\n // ===== Selection State =====\n /** Whether multi-select mode is enabled */\n multiple: boolean\n /** Current selected value (single-select mode) */\n value: Value | null\n /** Current selected values (multi-select mode) */\n values: Value[]\n /** Callback when value changes (single-select mode) */\n onValueChange: (value: Value) => void\n /** Callback when values change (multi-select mode) */\n onValuesChange: (values: Value[]) => void\n\n // ===== Object Value Support =====\n /**\n * Custom comparison logic used to determine if a combobox item value\n * matches the current selected value.\n * Useful when item values are objects without matching referentially.\n * Defaults to Object.is comparison.\n */\n isItemEqualToValue: ItemEqualityComparer<Value>\n /**\n * When the item values are objects, this function converts the object\n * value to a string representation for display in the input.\n * If the shape of the object is { value, label }, the label will be\n * used automatically without needing to specify this prop.\n */\n itemToStringLabel?: (itemValue: Value) => string\n /**\n * When the item values are objects, this function converts the object\n * value to a string representation for form submission.\n * If the shape of the object is { value, label }, the value will be\n * used automatically without needing to specify this prop.\n */\n itemToStringValue?: (itemValue: Value) => string\n\n // ===== Input State =====\n /** Current input value */\n inputValue: string\n /** Callback when input value changes */\n onInputValueChange: (value: string) => void\n\n // ===== Form Integration =====\n /** Form field name for submission */\n name?: string\n /** Associate with a form by ID */\n form?: string\n /** Whether this field is required */\n required?: boolean\n /** Whether the combobox is disabled */\n disabled: boolean\n /** Placeholder text for the input */\n placeholder: string\n\n // ===== Item Text Registry =====\n /** Registry of item values to their text content */\n itemTextRegistry: ItemTextRegistry\n /** Register an item's text content */\n registerItemText: (value: string, text: string) => () => void\n /**\n * Data structure of the items for label resolution.\n * Used to display labels before items mount (e.g., on initial render with defaultValue).\n * Can be a record mapping values to labels, or an array of { value, label } objects.\n */\n items?:\n | Record<string, React.ReactNode>\n | Array<{ value: string; label: React.ReactNode }>\n\n // ===== List ID for ARIA =====\n /** ID for the listbox element */\n listId: string\n\n // ===== Element Refs for Positioning =====\n /** Ref to the input element (also serves as anchor) */\n inputRef: React.RefObject<HTMLInputElement | null>\n /** Callback to set the input element */\n setInputElement: (element: HTMLInputElement | null) => void\n /** Ref to the input wrapper element (used as anchor when present) */\n inputWrapperRef: React.RefObject<HTMLElement | null>\n /** Callback to set the input wrapper element */\n setInputWrapperElement: (element: HTMLElement | null) => void\n\n // ===== Behavior =====\n /** Whether to close on selection (default: true for single, false for multiple) */\n closeOnSelect: boolean\n /** Whether to open on focus */\n openOnFocus: boolean\n /** Open the combobox */\n openCombobox: () => void\n /** Close the combobox with an optional reason and event */\n closeCombobox: (reason?: ComboboxOpenChangeReason, event?: Event) => void\n\n // ===== Filter Mode =====\n /**\n * Current filter mode for the combobox.\n * Controls how the search/filter value is determined.\n */\n filterMode: ComboboxFilterMode\n /** Set the filter mode to 'active' (normal filtering using inputValue) */\n setFilterActive: () => void\n\n // ===== Input Dimensions =====\n /**\n * Height of the input element in pixels.\n * Used by the positioner for input-embedded layout calculations.\n */\n inputHeight: number\n /**\n * Width of the input element in pixels.\n * Used by the positioner for input-embedded layout calculations.\n */\n inputWidth: number\n\n // ===== Layout =====\n /**\n * The layout mode for the combobox popup.\n * - `'floating'` - Standard dropdown positioning\n * - `'input-embedded'` - Popup wraps around the input (macOS-style)\n */\n layout: ComboboxLayout\n}\n\nconst ComboboxContext =\n React.createContext<ComboboxContextValue<unknown> | null>(null)\n\n/**\n * Hook to access the Combobox context.\n * Throws if used outside a Combobox.Root.\n */\nexport function useComboboxContext<\n Value = unknown,\n>(): ComboboxContextValue<Value> {\n const context = React.useContext(ComboboxContext)\n if (!context) {\n throw new Error('Combobox components must be used within a Combobox.Root')\n }\n return context as ComboboxContextValue<Value>\n}\n\n/**\n * Hook to optionally access the Combobox context.\n * Returns null if used outside a Combobox.Root.\n */\nexport function useMaybeComboboxContext<\n Value = unknown,\n>(): ComboboxContextValue<Value> | null {\n return React.useContext(ComboboxContext) as ComboboxContextValue<Value> | null\n}\n\nexport { ComboboxContext }\n","'use client'\n\nimport { Popover, type PopoverPortalProps } from '@base-ui/react/popover'\n\nexport interface PopupMenuPortalProps extends PopoverPortalProps {}\n\n/**\n * A portal element that moves the popup to a different part of the DOM.\n * By default, the portal element is appended to `<body>`.\n */\nexport const PopupMenuPortal = Popover.Portal\n\nexport namespace PopupMenuPortal {\n export type Props = PopoverPortalProps\n export type State = Popover.Portal.State\n}\n","export enum PopupMenuPositionerCssVars {\n /**\n * The available width between the trigger and the edge of the viewport.\n * @type {number}\n */\n availableWidth = '--available-width',\n /**\n * The available height between the trigger and the edge of the viewport.\n * @type {number}\n */\n availableHeight = '--available-height',\n /**\n * The anchor's width.\n * @type {number}\n */\n anchorWidth = '--anchor-width',\n /**\n * The anchor's height.\n * @type {number}\n */\n anchorHeight = '--anchor-height',\n /**\n * The coordinates that this element is anchored to. Used for animations and transitions.\n * @type {string}\n */\n transformOrigin = '--transform-origin',\n /**\n * The width of the positioner element.\n * @type {number}\n */\n positionerWidth = '--positioner-width',\n /**\n * The height of the positioner element.\n * @type {number}\n */\n positionerHeight = '--positioner-height',\n}\n","export enum PopupMenuPositionerDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-positioner' | 'bazzaui-context-menu-positioner' | 'bazzaui-select-positioner' | 'bazzaui-combobox-positioner'}\n */\n slot = 'bazzaui-[component]-positioner',\n /**\n * Present when the popup menu is open.\n */\n open = 'data-open',\n /**\n * Present when the popup menu is closed.\n */\n closed = 'data-closed',\n /**\n * Present when the anchor is hidden.\n */\n anchorHidden = 'data-anchor-hidden',\n /**\n * Indicates which side the popup is positioned relative to the trigger.\n * @type {'top' | 'bottom' | 'left' | 'right' | 'inline-end' | 'inline-start'}\n */\n side = 'data-side',\n /**\n * Indicates how the popup is aligned relative to specified side.\n * @type {'start' | 'center' | 'end' | 'list-start'}\n */\n align = 'data-align',\n}\n","'use client'\n\nimport { Popover, type PopoverPositionerProps } from '@base-ui/react/popover'\nimport * as React from 'react'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { usePopupMenuContext } from '../../contexts/popup-menu-context.js'\nimport { useMaybeSubmenuContext } from '../../contexts/submenu-context.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype Side = 'top' | 'bottom' | 'left' | 'right' | 'inline-end' | 'inline-start'\n\n/**\n * Extended align options for popup menus.\n * - 'start' | 'center' | 'end': Standard Base UI alignment\n * - 'list-start': Align trigger top with the top of the List component (horizontal sides only)\n */\nexport type PopupMenuPositionerAlign =\n | PopoverPositionerProps['align']\n | 'list-start'\n\nexport interface PopupMenuPositionerProps\n extends Omit<PopoverPositionerProps, 'align' | 'style'> {\n /**\n * Override the virtual anchor from context.\n * Useful for nested menus that need different positioning.\n */\n virtualAnchor?: { getBoundingClientRect(): DOMRect }\n\n /**\n * How to align the popup relative to the specified side.\n * - 'start': align to start of anchor\n * - 'center': align to center of anchor\n * - 'end': align to end of anchor\n * - 'list-start': align the List component's top with the anchor top (horizontal sides only)\n * @default 'start' for submenus, 'center' for root dropdowns\n */\n align?: PopupMenuPositionerAlign\n\n /**\n * Custom styles for the positioner.\n * Note: During list-start alignment measurement, `transition: 'none'` is\n * temporarily applied to prevent visual flash.\n */\n style?: React.CSSProperties\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Returns the default collision avoidance strategy based on the side.\n *\n * - For horizontal sides (left/right): use shift to keep submenus visible\n * without flipping to the opposite side, which can be disorienting\n * - For vertical sides (top/bottom): use flip as the standard behavior\n */\nfunction getDefaultCollisionAvoidance(\n side: Side,\n): PopoverPositionerProps['collisionAvoidance'] {\n if (isHorizontalSide(side)) {\n return {\n side: 'shift',\n align: 'shift',\n }\n }\n\n // Vertical sides use flip (default Base UI behavior)\n return undefined\n}\n\n/**\n * Check if the side is horizontal (for list-start alignment).\n */\nfunction isHorizontalSide(side: Side): boolean {\n return (\n side === 'left' ||\n side === 'right' ||\n side === 'inline-start' ||\n side === 'inline-end'\n )\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Positions the popup menu against its anchor.\n * Wraps Popover.Positioner with:\n * - Automatic virtualAnchor from PopupMenuContext (for context menus)\n * - Smart default positioning based on depth and menu type\n * - Smart collision avoidance: shift for horizontal menus, flip for vertical\n * - 'list-start' alignment for horizontal submenus\n *\n * Renders a `<div>` element.\n */\nexport const PopupMenuPositioner = React.forwardRef<\n HTMLDivElement,\n PopupMenuPositioner.Props\n>(function PopupMenuPositioner(props, ref) {\n const {\n side: sideProp,\n align: alignProp,\n alignOffset: alignOffsetProp,\n collisionAvoidance: collisionAvoidanceProp,\n virtualAnchor: virtualAnchorProp,\n style: styleProp,\n ...rest\n } = props\n\n const {\n depth,\n virtualAnchor: contextVirtualAnchor,\n menuType,\n } = usePopupMenuContext()\n\n // Get submenu context to access contentRef for list-start measurement\n const submenuContext = useMaybeSubmenuContext()\n\n // Ref for calculated list-start offset\n // Using a ref instead of state to avoid re-renders that cause visual flash\n const listStartOffsetRef = React.useRef(0)\n\n // Track if we've measured (only measure once per open)\n const hasMeasuredRef = React.useRef(false)\n\n // Counter to force re-render after measurement\n const [, forceUpdate] = React.useReducer((x) => x + 1, 0)\n\n // For submenus (depth > 0), we should NOT use the context's virtualAnchor\n // because the submenu should anchor to its trigger element, not the cursor position.\n // Only the root menu (depth 0) should use the virtual anchor for context menus.\n const isSubmenu = depth > 0\n const virtualAnchor = isSubmenu\n ? virtualAnchorProp // Only use explicit prop for submenus (usually undefined)\n : (virtualAnchorProp ?? contextVirtualAnchor)\n\n // Default side based on depth:\n // - Root menu (depth 0): bottom for dropdown, start for context\n // - Submenu (depth > 0): right\n const defaultSide = isSubmenu ? 'right' : 'bottom'\n const side = sideProp ?? defaultSide\n\n // Align defaults to start for submenus, center for root dropdown, start for context\n const defaultAlign = isSubmenu\n ? 'start'\n : menuType === 'context'\n ? 'start'\n : 'center'\n const align = alignProp ?? defaultAlign\n\n // Determine if list-start alignment should be used\n // Only for horizontal sides\n const useListStartAlign = align === 'list-start' && isHorizontalSide(side)\n\n // Map to Base UI align (list-start -> start)\n const baseUIAlign = align === 'list-start' ? 'start' : align\n\n // Get open state from submenu context\n const isOpen = submenuContext?.open ?? false\n\n // Measurement function for list-start offset\n // Updates the ref and forces a synchronous re-render\n const measureListStartOffset = React.useCallback(() => {\n if (!useListStartAlign) return\n\n const contentEl = submenuContext?.contentRef.current\n if (!contentEl) return\n\n const contentRect = contentEl.getBoundingClientRect()\n\n // Find the List component by role=\"listbox\"\n const listEl = contentEl.querySelector<HTMLElement>('[role=\"listbox\"]')\n if (!listEl) {\n listStartOffsetRef.current = 0\n return\n }\n\n const listRect = listEl.getBoundingClientRect()\n\n // Get the list's padding-top to align to content start\n const listStyles = getComputedStyle(listEl)\n const listPaddingTop = Number.parseFloat(listStyles.paddingTop) || 0\n\n // Calculate offset: negative distance from popup top to list content top\n const offset = -(listRect.top + listPaddingTop - contentRect.top)\n listStartOffsetRef.current = offset\n }, [useListStartAlign, submenuContext])\n\n // Measure once when submenu opens\n // Using useLayoutEffect to measure synchronously before paint\n React.useLayoutEffect(() => {\n if (!useListStartAlign || !isOpen) {\n return\n }\n\n if (hasMeasuredRef.current) return\n\n // Measure synchronously - by this point, all children have rendered\n // and contentRef should be populated\n measureListStartOffset()\n hasMeasuredRef.current = true\n\n // Force a synchronous re-render to apply the measured offset\n // This happens within useLayoutEffect, so it completes before browser paint\n forceUpdate()\n }, [useListStartAlign, isOpen, measureListStartOffset])\n\n // Reset measurement flag when menu closes\n React.useEffect(() => {\n if (!isOpen) {\n hasMeasuredRef.current = false\n listStartOffsetRef.current = 0\n }\n }, [isOpen])\n\n // Calculate effective alignOffset\n // User's alignOffset is additive to the calculated offset (only if it's a number)\n const effectiveAlignOffset = useListStartAlign\n ? listStartOffsetRef.current +\n (typeof alignOffsetProp === 'number' ? alignOffsetProp : 0)\n : alignOffsetProp\n\n // Default collision avoidance based on side:\n // - Horizontal (left/right): shift to avoid disorienting flip\n // - Vertical (top/bottom): flip (standard behavior)\n const collisionAvoidance =\n collisionAvoidanceProp ?? getDefaultCollisionAvoidance(side)\n\n // Only pass anchor if we have one - otherwise let Popover use its default (Trigger element)\n const anchorProps = virtualAnchor ? { anchor: virtualAnchor } : {}\n\n // Disable transitions during measurement to prevent visual flash.\n // When using list-start alignment, the first render positions at 'start',\n // then measurement occurs and we re-render with the correct offset.\n // By disabling transitions during this phase, both renders happen\n // synchronously without any visible movement.\n const isMeasuring = useListStartAlign && !hasMeasuredRef.current && isOpen\n const style: React.CSSProperties | undefined = isMeasuring\n ? { ...styleProp, transition: 'none' }\n : styleProp\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'positioner')\n\n return (\n <Popover.Positioner\n ref={ref}\n side={side}\n align={baseUIAlign}\n alignOffset={effectiveAlignOffset}\n collisionAvoidance={collisionAvoidance}\n style={style}\n {...(slotAttr ? { [slotAttr]: '' } : {})}\n // Override data-align to show 'list-start' when using list-start alignment\n data-align={useListStartAlign ? 'list-start' : undefined}\n {...anchorProps}\n {...rest}\n />\n )\n})\n\nexport namespace PopupMenuPositioner {\n export type Props = PopupMenuPositionerProps\n export type State = Popover.Positioner.State\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { ListboxContextValue } from '../../listbox/contexts/listbox-context.js'\nimport { ListboxContext as ListboxContextProvider } from '../../listbox/contexts/listbox-context.js'\nimport type { ListboxStore, VirtualItem } from '../../listbox/index.js'\nimport {\n type ComponentName,\n ComponentNameContext,\n} from '../contexts/component-name-context.js'\nimport { FocusOwnerContext } from '../contexts/focus-owner-context.js'\nimport { OpenChainContext } from '../contexts/open-chain-context.js'\nimport {\n PopupMenuContext,\n type PopupMenuContextValue,\n type VirtualAnchor,\n type VirtualizationConfig,\n} from '../contexts/popup-menu-context.js'\nimport type { GetQualifiedRowIdFn } from '../deep-search/types.js'\nimport { AimGuardProvider } from '../hooks/use-aim-guard.js'\nimport type { FocusOwnerStore } from '../store/FocusOwnerStore.js'\nimport type { OpenChainStore } from '../store/OpenChainStore.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PopupMenuProvidersProps {\n /** The Listbox store instance */\n store: ListboxStore\n /** The FocusOwner store instance */\n focusOwnerStore: FocusOwnerStore\n /** The OpenChain store instance */\n openChainStore: OpenChainStore\n /** Nesting depth: 0 = root menu */\n depth: number\n /** Close the entire menu tree */\n closeAll: () => void\n /** Register a surface for closeAll tracking */\n registerSurface: (\n depth: number,\n setOpen: (open: boolean) => void,\n ) => () => void\n /** Virtualization configuration */\n virtualization?: VirtualizationConfig\n /**\n * Virtual anchor for positioning (used by ContextMenu).\n * DropdownMenu uses Popover's anchor (trigger button) instead.\n */\n virtualAnchor?: VirtualAnchor\n /**\n * Type of menu for positioning logic.\n * @default 'dropdown'\n */\n menuType?: 'dropdown' | 'context'\n /**\n * When to close the menu on outside interactions.\n * @default 'pointerdown'\n */\n closeOnOutsidePress?: 'click' | 'pointerdown'\n /**\n * Function to generate qualified unique IDs for rows.\n * Defined once at the root level and applied to all surfaces (root and submenus).\n */\n getQualifiedRowId?: GetQualifiedRowIdFn\n /**\n * Component name for generating bazzaui-* slot attributes.\n * E.g., 'dropdown-menu', 'context-menu', 'select', 'combobox'\n */\n componentName: ComponentName\n children: React.ReactNode\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Provides all shared context providers for popup menus.\n * Wraps children with:\n * - PopupMenuContext (menu-specific state)\n * - ListboxContextProvider (for compatibility with listbox components)\n * - AimGuardProvider (for submenu aim detection)\n * - FocusOwnerContext (for focus tracking across submenus)\n * - OpenChainContext (for tracking open submenu chain)\n */\nexport function PopupMenuProviders(props: PopupMenuProvidersProps) {\n const {\n store,\n focusOwnerStore,\n openChainStore,\n depth,\n closeAll,\n registerSurface,\n virtualization,\n virtualAnchor,\n menuType = 'dropdown',\n closeOnOutsidePress = 'pointerdown',\n getQualifiedRowId,\n componentName,\n children,\n } = props\n\n // PopupMenu context value\n const popupMenuContextValue: PopupMenuContextValue = React.useMemo(\n () => ({\n store,\n depth,\n closeAll,\n registerSurface,\n virtualization,\n virtualAnchor,\n menuType,\n closeOnOutsidePress,\n getQualifiedRowId,\n }),\n [\n store,\n depth,\n closeAll,\n registerSurface,\n virtualization,\n virtualAnchor,\n menuType,\n closeOnOutsidePress,\n getQualifiedRowId,\n ],\n )\n\n // Listbox context value (for compatibility with dropdown-menu components)\n const listboxContextValue: ListboxContextValue = React.useMemo(\n () => ({\n store,\n depth,\n closeAll,\n registerSurface,\n virtualization,\n }),\n [store, depth, closeAll, registerSurface, virtualization],\n )\n\n return (\n <ComponentNameContext.Provider value={componentName}>\n <PopupMenuContext.Provider value={popupMenuContextValue}>\n <ListboxContextProvider.Provider value={listboxContextValue}>\n <AimGuardProvider>\n <FocusOwnerContext.Provider value={focusOwnerStore}>\n <OpenChainContext.Provider value={openChainStore}>\n {children}\n </OpenChainContext.Provider>\n </FocusOwnerContext.Provider>\n </AimGuardProvider>\n </ListboxContextProvider.Provider>\n </PopupMenuContext.Provider>\n </ComponentNameContext.Provider>\n )\n}\n","'use client'\n\n// ============================================================================\n// usePopupMenuItem Hook - Wrapper around internal/listbox useListboxItem\n// ============================================================================\n// This wrapper adds aim-guard support and close-on-click behavior for popup menus\n\nimport * as React from 'react'\nimport {\n type UseListboxItemParams,\n type UseListboxItemReturn,\n useListboxContext,\n useListboxItem,\n} from '../../listbox/index.js'\nimport { useAimGuard } from './use-aim-guard.js'\n\nexport interface UsePopupMenuItemParams\n extends Omit<UseListboxItemParams, 'aimGuard' | 'onAfterSelect'> {\n /**\n * Whether clicking this item should close the menu.\n * @default true\n */\n closeOnClick?: boolean\n}\n\nexport type UsePopupMenuItemReturn = UseListboxItemReturn\n\n/**\n * Hook that provides all shared logic for navigatable/highlightable popup menu items.\n * This is a thin wrapper around useListboxItem that automatically adds aim-guard\n * support and handles close-on-click behavior.\n *\n * @see useListboxItem for full documentation\n */\nexport function usePopupMenuItem(\n params: UsePopupMenuItemParams,\n): UsePopupMenuItemReturn {\n const { closeOnClick = true, ...rest } = params\n const { aimGuardActiveRef, guardedDepthRef } = useAimGuard()\n const { closeAll } = useListboxContext()\n\n // Create aim guard refs object for the listbox hook\n const aimGuard = React.useMemo(\n () => ({\n aimGuardActiveRef,\n guardedDepthRef,\n }),\n [aimGuardActiveRef, guardedDepthRef],\n )\n\n // Handle after-select behavior (close menu if closeOnClick is true)\n const handleAfterSelect = React.useCallback(\n (itemId: string) => {\n if (closeOnClick) {\n closeAll()\n }\n },\n [closeOnClick, closeAll],\n )\n\n return useListboxItem({\n ...rest,\n aimGuard,\n closeOnClick,\n onAfterSelect: handleAfterSelect,\n })\n}\n","'use client'\n\n// ============================================================================\n// usePopupMenuKeyboard Hook - Wrapper around internal/listbox useListboxKeyboard\n// ============================================================================\n// This wrapper integrates the focus owner and submenu contexts from popup-menu\n\nimport * as React from 'react'\nimport { type ListboxStore, useListboxKeyboard } from '../../listbox/index.js'\nimport type { SubmenuContextValue } from '../contexts/submenu-context.js'\nimport type { FocusOwnerStore } from '../store/FocusOwnerStore.js'\n\nexport interface UsePopupMenuKeyboardParams {\n /** The Listbox store instance */\n store: ListboxStore\n /** Unique identifier for this surface */\n surfaceId: string\n /** The FocusOwner store for managing focus ownership */\n focusOwnerStore: FocusOwnerStore\n /** Menu depth (0 for root, >0 for submenus) */\n depth: number\n /** Submenu context for ArrowLeft navigation back to parent */\n submenuContext: SubmenuContextValue | null\n /** Whether keyboard handling is enabled */\n enabled: boolean\n /**\n * Whether to enable type-to-search behavior.\n * When true, printable characters will activate the input and set pending search.\n * Used by List when hideUntilActive is enabled and input is not yet active.\n * @default false\n */\n enableTypeToSearch?: boolean\n /** User's onKeyDown handler to compose with */\n onKeyDown?: React.KeyboardEventHandler\n /**\n * Callback to close the entire menu tree from the root.\n * Used when Escape is pressed and closeRootOnEsc is true (default).\n */\n closeAll: () => void\n /**\n * Whether to skip the focus owner check.\n * When true, keyboard handling will work based on `enabled` prop alone,\n * ignoring focus ownership. Useful for Combobox where the input is outside\n * the Surface but should still handle keyboard navigation.\n * @default false\n */\n skipFocusOwnerCheck?: boolean\n}\n\nexport interface UsePopupMenuKeyboardReturn {\n /** Keyboard event handler to attach to the element */\n handleKeyDown: React.KeyboardEventHandler\n}\n\n/**\n * Centralized keyboard navigation hook for popup menus.\n * Handles arrow navigation, vim bindings, submenu open/close, and selection.\n */\nexport function usePopupMenuKeyboard(\n params: UsePopupMenuKeyboardParams,\n): UsePopupMenuKeyboardReturn {\n const {\n store,\n surfaceId,\n focusOwnerStore,\n depth,\n submenuContext,\n enabled,\n enableTypeToSearch = false,\n onKeyDown,\n closeAll,\n skipFocusOwnerCheck = false,\n } = params\n\n // Convert submenu context to the interface expected by the listbox hook\n const submenuInterface = React.useMemo(() => {\n if (!submenuContext) return null\n return {\n setOpen: submenuContext.setOpen,\n parentSurfaceId: submenuContext.parentSurfaceId,\n closeRootOnEsc: submenuContext.closeRootOnEsc,\n }\n }, [submenuContext])\n\n // Handle selection via keyboard (Enter or shortcut)\n const handleSelect = React.useCallback(\n (details: { itemId: string | null; closeOnClick: boolean }) => {\n if (details.itemId && details.closeOnClick) {\n closeAll()\n }\n },\n [closeAll],\n )\n\n return useListboxKeyboard({\n store,\n surfaceId,\n enabled,\n onKeyDown,\n onSelect: handleSelect,\n closeAll,\n focusOwner: focusOwnerStore,\n depth,\n submenuContext: submenuInterface,\n enableTypeToSearch,\n skipFocusOwnerCheck,\n })\n}\n","export const PopupMenuIconDataAttributes = {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-icon' | 'bazzaui-context-menu-icon' | 'bazzaui-select-icon' | 'bazzaui-combobox-icon'}\n */\n slot: 'bazzaui-[component]-icon',\n /** Present when the popup is open. */\n open: 'data-popup-open',\n} as const\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { useMaybeComboboxContext } from '../../../../combobox/contexts/combobox-context.js'\nimport {\n resolveLabel,\n stringifyAsValue,\n} from '../../../../utils/resolve-value-label.js'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { usePopupMenuContext } from '../../contexts/popup-menu-context.js'\nimport { PopupMenuIconDataAttributes } from './icon.data-attrs.js'\n\nexport { PopupMenuIconDataAttributes }\n\nexport interface PopupMenuIconState extends Record<string, unknown> {\n /**\n * Whether the popup is currently open.\n */\n open: boolean\n}\n\nexport interface PopupMenuIconProps\n extends ComponentProps<'span', PopupMenuIcon.State> {}\n\nconst stateAttributesMapping = {\n open: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuIconDataAttributes.open]: '' } : null,\n}\n\n/**\n * An icon that indicates the trigger opens a popup.\n * Typically used inside the trigger to show a chevron or dropdown arrow.\n * Renders a `<span>` element.\n */\nexport const PopupMenuIcon = React.forwardRef<\n HTMLSpanElement,\n PopupMenuIcon.Props\n>(function PopupMenuIcon(props, forwardedRef) {\n const {\n render,\n className,\n style,\n children,\n onPointerDown,\n onClick,\n ...rest\n } = props\n\n const { store } = usePopupMenuContext()\n const open = store.useState('open')\n\n // Check if inside a Combobox to apply special focus handling\n const comboboxContext = useMaybeComboboxContext()\n\n const state: PopupMenuIcon.State = React.useMemo(() => ({ open }), [open])\n\n // Prevent pointer down from stealing focus from the input (Combobox only)\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLSpanElement>) => {\n if (comboboxContext) {\n event.preventDefault()\n }\n onPointerDown?.(event)\n },\n [comboboxContext, onPointerDown],\n )\n\n // Handle click to toggle the combobox (Combobox only)\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLSpanElement>) => {\n onClick?.(event)\n if (event.defaultPrevented) return\n\n if (comboboxContext) {\n if (open) {\n comboboxContext.closeCombobox()\n } else {\n // Pre-set the input value BEFORE opening to avoid the empty intermediate state\n // This mirrors what the input click handler does\n const hasValue = comboboxContext.multiple\n ? comboboxContext.values.length > 0\n : comboboxContext.value != null\n\n if (hasValue && !comboboxContext.multiple) {\n // Serialize the value to a string key for registry lookup\n const valueKey = stringifyAsValue(\n comboboxContext.value,\n comboboxContext.itemToStringValue,\n )\n // Get the label from the registry or resolve from the value\n const registryText = comboboxContext.itemTextRegistry.get(valueKey)\n const labelValue =\n registryText ??\n resolveLabel(\n comboboxContext.value,\n comboboxContext.itemToStringLabel,\n )\n comboboxContext.onInputValueChange(labelValue)\n }\n\n comboboxContext.openCombobox()\n }\n }\n },\n [onClick, comboboxContext, open],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'icon')\n\n return useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n className,\n style,\n children,\n onPointerDown: handlePointerDown,\n onClick: handleClick,\n },\n defaultTagName: 'span',\n })\n})\n\nexport namespace PopupMenuIcon {\n export type State = PopupMenuIconState\n export interface Props extends PopupMenuIconProps {}\n}\n","/**\n * Resolve a display label from an object value.\n * Auto-detects { label } shape if no custom function is provided.\n *\n * @param value - The value to convert to a label\n * @param itemToStringLabel - Optional custom function to extract the label\n * @returns The string label for display\n */\nexport function resolveLabel<Value>(\n value: Value,\n itemToStringLabel?: (value: Value) => string,\n): string {\n if (value == null) return ''\n if (itemToStringLabel) return itemToStringLabel(value)\n\n // Auto-detect { label } shape\n if (typeof value === 'object' && 'label' in value) {\n const label = (value as Record<string, unknown>).label\n if (typeof label === 'string') return label\n }\n\n return String(value)\n}\n\n/**\n * Serialize an object value for form submission.\n * Auto-detects { value } shape if no custom function is provided.\n *\n * @param value - The value to serialize\n * @param itemToStringValue - Optional custom function to serialize the value\n * @returns The string value for form submission\n */\nexport function stringifyAsValue<Value>(\n value: Value,\n itemToStringValue?: (value: Value) => string,\n): string {\n if (value == null) return ''\n if (itemToStringValue) return itemToStringValue(value)\n\n // Auto-detect { value } shape\n if (typeof value === 'object' && 'value' in value) {\n return String((value as Record<string, unknown>).value)\n }\n\n return String(value)\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { useSurfaceContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\n\n// Empty doesn't have any state - using an empty object type\nexport interface PopupMenuEmptyState extends Record<string, unknown> {}\n\nexport interface PopupMenuEmptyProps\n extends ComponentProps<'div', PopupMenuEmpty.State> {\n children: React.ReactNode\n}\n\n/**\n * Renders when no items match the current search query.\n * Only visible when there's an active search with zero results.\n * Renders a `<div>` element.\n */\nexport const PopupMenuEmpty = React.forwardRef<\n HTMLDivElement,\n PopupMenuEmpty.Props\n>(function PopupMenuEmpty(props, forwardedRef) {\n const { render, className, style, children, ...rest } = props\n\n const { store } = useSurfaceContext()\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'empty')\n\n const element = useRender({\n render,\n ref: forwardedRef,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n role: 'presentation',\n className,\n style,\n children,\n },\n defaultTagName: 'div',\n })\n\n // Use dedicated selector for this check\n const shouldRender = store.useState('hasSearchWithNoResults')\n\n if (!shouldRender) {\n return null\n }\n\n return element\n})\n\nexport namespace PopupMenuEmpty {\n export type State = PopupMenuEmptyState\n export interface Props extends PopupMenuEmptyProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { useListboxContext, useSurfaceContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { useFocusOwner } from '../../contexts/focus-owner-context.js'\nimport { useMaybeSubmenuContext } from '../../contexts/submenu-context.js'\nimport { usePopupMenuKeyboard } from '../../hooks/use-popup-menu-keyboard.js'\n\nexport interface PopupMenuInputState extends Record<string, unknown> {\n /**\n * Whether the input is active (visible).\n * Only relevant when `hideUntilActive` is true.\n */\n active: boolean\n}\n\nexport interface PopupMenuInputProps\n extends Omit<\n ComponentProps<'input', PopupMenuInput.State>,\n 'value' | 'onChange' | 'type'\n > {\n /**\n * Controlled value for the search input.\n * If provided, this takes precedence over the Surface's search state.\n */\n value?: string\n\n /**\n * Callback when the input value changes.\n */\n onValueChange?: (value: string) => void\n\n /**\n * When true, the input is not rendered until the user starts typing.\n * The List receives focus initially, and typing a character activates the input.\n * Once activated, the input stays visible until the menu closes.\n * @default false\n */\n hideUntilActive?: boolean\n}\n\n/**\n * Search input for filtering popup menu items.\n * Handles keyboard navigation (Arrow keys, Ctrl+N/P, Enter).\n * Renders an `<input>` element.\n */\nexport const PopupMenuInput = React.forwardRef<\n HTMLInputElement,\n PopupMenuInput.Props\n>(function PopupMenuInput(props, forwardedRef) {\n const {\n value: controlledValue,\n onValueChange,\n hideUntilActive = false,\n render,\n className,\n style,\n onKeyDown,\n ...rest\n } = props\n\n const { store, surfaceId } = useSurfaceContext()\n const { depth, closeAll } = useListboxContext()\n const submenuContext = useMaybeSubmenuContext()\n const focusOwnerStore = useFocusOwner()\n const internalRef = React.useRef<HTMLInputElement>(null)\n\n // Get values from store\n const search = store.useState('search')\n const highlightedId = store.useState('highlightedId')\n const listId = store.context.listId\n const inputId = store.context.inputId\n\n // Register hideUntilActive mode\n React.useEffect(() => {\n store.setHideUntilActive(hideUntilActive)\n return () => store.setHideUntilActive(false)\n }, [store, hideUntilActive])\n\n // Subscribe to inputActive and pendingSearch state\n const inputActive = store.useState('inputActive')\n const pendingSearch = store.useState('pendingSearch')\n\n // Determine if we should render\n const shouldRender = !hideUntilActive || inputActive\n\n // Register that an Input is present - ONLY when actually rendering\n // This ensures List handles keyboard when Input is hidden\n React.useEffect(() => {\n if (!shouldRender) {\n return // Don't register when hidden\n }\n store.setHasInput(true)\n return () => store.setHasInput(false)\n }, [store, shouldRender])\n\n // Determine the actual value (controlled input prop > controlled surface > uncontrolled)\n const isInputControlled = controlledValue !== undefined\n const displayValue = isInputControlled ? controlledValue : search\n\n // Consume pending search on activation\n React.useEffect(() => {\n if (pendingSearch && internalRef.current) {\n // Always sync to store for filtering/highlighting, even in controlled mode\n store.setSearch(pendingSearch)\n onValueChange?.(pendingSearch)\n // Clear pending search\n store.setPendingSearch('')\n // Focus the input\n internalRef.current.focus()\n }\n }, [pendingSearch, store, onValueChange])\n\n const handleChange = React.useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = event.target.value\n\n // Always sync to store for filtering/highlighting, even in controlled mode\n store.setSearch(newValue)\n onValueChange?.(newValue)\n },\n [onValueChange, store],\n )\n\n // Use centralized keyboard navigation hook\n const { handleKeyDown } = usePopupMenuKeyboard({\n store,\n surfaceId,\n focusOwnerStore,\n depth,\n submenuContext,\n enabled: true,\n enableTypeToSearch: false,\n onKeyDown,\n closeAll,\n })\n\n const state: PopupMenuInput.State = React.useMemo(\n () => ({\n active: inputActive,\n }),\n [inputActive],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'input')\n\n const element = useRender({\n render,\n ref: [internalRef, forwardedRef],\n state,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n id: inputId,\n type: 'text',\n role: 'combobox',\n 'aria-autocomplete': 'list',\n 'aria-expanded': true,\n 'aria-controls': listId,\n 'aria-activedescendant': highlightedId ?? undefined,\n autoComplete: 'off',\n autoCorrect: 'off',\n spellCheck: false,\n className,\n style,\n value: displayValue,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n },\n defaultTagName: 'input',\n })\n\n // Don't render if hideUntilActive is enabled and not yet active\n if (!shouldRender) {\n return null\n }\n\n return element\n})\n\nexport namespace PopupMenuInput {\n export type State = PopupMenuInputState\n export interface Props extends PopupMenuInputProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { useMaybeComboboxContext } from '../../../../combobox/contexts/combobox-context.js'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n RowWidthContext,\n useListboxContext,\n useStickyRowWidth,\n useSurfaceContext,\n} from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { useFocusOwner } from '../../contexts/focus-owner-context.js'\nimport { useMaybeSubmenuContext } from '../../contexts/submenu-context.js'\nimport { usePopupMenuKeyboard } from '../../hooks/use-popup-menu-keyboard.js'\nimport { PopupMenuListCssVars } from './list.css-vars.js'\nimport { PopupMenuListDataAttributes } from './list.data-attrs.js'\n\nexport { PopupMenuListCssVars, PopupMenuListDataAttributes }\n\n/**\n * State passed to children render function.\n */\nexport interface PopupMenuListChildrenState {\n /** Current search query */\n search: string\n /** Number of items matching the current filter */\n filteredCount: number\n}\n\n// List doesn't expose data attributes - using empty state\nexport interface PopupMenuListState extends Record<string, unknown> {}\n\nexport interface PopupMenuListProps\n extends Omit<ComponentProps<'div', PopupMenuList.State>, 'children'> {\n /**\n * Content to render inside the list.\n * Can be a render function that receives the current search state.\n */\n children:\n | React.ReactNode\n | ((state: PopupMenuListChildrenState) => React.ReactNode)\n\n /**\n * Accessible label for the listbox.\n * @default 'Suggestions'\n */\n label?: string\n\n /**\n * When true, measures row widths and applies `--row-width` CSS variable.\n * Keeps the list at the maximum width seen while scrolling.\n * Useful for virtualized lists where content width varies.\n * @default true\n */\n measureRowWidth?: boolean\n\n /**\n * Maximum width cap for row measurement (in pixels).\n * Only used when `measureRowWidth` is true.\n */\n maxRowWidth?: number\n}\n\n/**\n * Container for popup menu items.\n * Supports render props for accessing search state.\n * Renders a `<div>` element with role=\"listbox\".\n */\nexport const PopupMenuList = React.forwardRef<\n HTMLDivElement,\n PopupMenuList.Props\n>(function PopupMenuList(props, forwardedRef) {\n const {\n children,\n label = 'Suggestions',\n measureRowWidth = true,\n maxRowWidth,\n render,\n className,\n style,\n onKeyDown,\n onPointerDown,\n ...rest\n } = props\n\n const { store, surfaceId } = useSurfaceContext()\n const { depth, closeAll } = useListboxContext()\n const submenuContext = useMaybeSubmenuContext()\n const focusOwnerStore = useFocusOwner()\n const comboboxContext = useMaybeComboboxContext()\n const internalRef = React.useRef<HTMLDivElement>(null)\n\n // Ref to the popup element (found via closest) for applying --row-width CSS var\n const popupRef = React.useRef<HTMLElement | null>(null)\n\n // Register list ref with store for scroll behavior\n React.useEffect(() => {\n store.setListRef(internalRef)\n }, [store])\n\n // Find popup element on mount for row width measurement target\n React.useLayoutEffect(() => {\n if (!measureRowWidth || !internalRef.current) return\n // Find the closest popup element (Base UI's Popover.Popup adds data-open)\n const popup = internalRef.current.closest(\n '[data-open]',\n ) as HTMLElement | null\n popupRef.current = popup\n }, [measureRowWidth])\n\n // Row width measurement - apply CSS var to popup instead of list\n const { queueMeasurement, resetMeasurements } = useStickyRowWidth({\n listRef: internalRef,\n targetRef: popupRef,\n maxWidth: maxRowWidth,\n enabled: measureRowWidth,\n })\n\n // Register resetMeasurements callback with store for close completion\n React.useEffect(() => {\n if (measureRowWidth) {\n store.context.onCloseComplete = resetMeasurements\n return () => {\n store.context.onCloseComplete = undefined\n }\n }\n }, [measureRowWidth, resetMeasurements, store])\n\n // Row width context value\n const rowWidthContextValue = React.useMemo(\n () => (measureRowWidth ? { queueMeasurement } : null),\n [measureRowWidth, queueMeasurement],\n )\n\n // Get values from store\n const search = store.useState('search')\n const filteredCount = store.useState('filteredCount')\n const hasInput = store.useState('hasInput')\n const highlightedId = store.useState('highlightedId')\n const listId = store.context.listId\n\n // When there's no Input, the List should receive focus and handle keyboard nav\n // Note: Auto-focus is handled by Surface when it becomes the focus owner\n const shouldHandleKeyboard = !hasInput\n\n // Use centralized keyboard navigation hook\n const { handleKeyDown } = usePopupMenuKeyboard({\n store,\n surfaceId,\n focusOwnerStore,\n depth,\n submenuContext,\n enabled: shouldHandleKeyboard,\n enableTypeToSearch: true,\n onKeyDown,\n closeAll,\n })\n\n // Prevent pointer down from stealing focus from Input\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n event.preventDefault()\n onPointerDown?.(event)\n },\n [onPointerDown],\n )\n\n const childrenState: PopupMenuList.ChildrenState = React.useMemo(\n () => ({\n search,\n filteredCount,\n }),\n [search, filteredCount],\n )\n\n const renderedChildren =\n typeof children === 'function' ? children(childrenState) : children\n\n // Wrap children with RowWidthContext if measurement is enabled\n const wrappedChildren = rowWidthContextValue ? (\n <RowWidthContext.Provider value={rowWidthContextValue}>\n {renderedChildren}\n </RowWidthContext.Provider>\n ) : (\n renderedChildren\n )\n\n // Add data-input-embedded attribute when layout is input-embedded\n const isInputEmbedded = comboboxContext?.layout === 'input-embedded'\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'list')\n\n return useRender({\n render,\n ref: [internalRef, forwardedRef],\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n id: listId,\n role: 'listbox',\n 'aria-label': label,\n 'aria-activedescendant': shouldHandleKeyboard\n ? (highlightedId ?? undefined)\n : undefined,\n tabIndex: shouldHandleKeyboard ? 0 : -1,\n [PopupMenuListDataAttributes.list]: '',\n 'data-input-embedded': isInputEmbedded ? '' : undefined,\n className,\n style,\n onKeyDown: handleKeyDown,\n onPointerDown: handlePointerDown,\n children: wrappedChildren,\n },\n defaultTagName: 'div',\n })\n})\n\nexport namespace PopupMenuList {\n export type State = PopupMenuListState\n export type ChildrenState = PopupMenuListChildrenState\n export interface Props extends PopupMenuListProps {}\n}\n","/**\n * CSS custom properties applied to the List component.\n */\nexport enum PopupMenuListCssVars {\n /**\n * The maximum measured row width.\n * Applied when `measureRowWidth` is true.\n * Useful for keeping virtualized lists at a consistent width.\n * @type {number}\n */\n rowWidth = '--row-width',\n}\n","export enum PopupMenuListDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-list' | 'bazzaui-context-menu-list' | 'bazzaui-select-list' | 'bazzaui-combobox-list'}\n */\n slot = 'bazzaui-[component]-list',\n /**\n * Always present on the list element.\n * Used for styling and by useStickyRowWidth to find the list container.\n */\n list = 'data-popup-menu-list',\n}\n","export const PopupMenuScrollArrowDataAttributes = {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-scroll-up-arrow' | 'bazzaui-dropdown-menu-scroll-down-arrow' | 'bazzaui-context-menu-scroll-up-arrow' | 'bazzaui-context-menu-scroll-down-arrow' | 'bazzaui-select-scroll-up-arrow' | 'bazzaui-select-scroll-down-arrow' | 'bazzaui-combobox-scroll-up-arrow' | 'bazzaui-combobox-scroll-down-arrow'}\n */\n slot: 'bazzaui-[component]-scroll-[up|down]-arrow',\n /** @type {'up' | 'down'} */\n direction: 'data-direction',\n /** @type {'top' | 'bottom' | 'left' | 'right'} */\n side: 'data-side',\n} as const\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { useSurfaceContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { PopupMenuScrollArrowDataAttributes } from './scroll-arrow.data-attrs.js'\n\nexport { PopupMenuScrollArrowDataAttributes }\n\ntype Direction = 'up' | 'down'\n\nexport interface PopupMenuScrollArrowState extends Record<string, unknown> {\n /**\n * The scroll direction this arrow controls.\n */\n direction: Direction\n /**\n * Whether there is content to scroll in this direction.\n */\n visible: boolean\n}\n\nexport interface PopupMenuScrollArrowProps\n extends ComponentProps<'div', PopupMenuScrollArrow.State> {\n /**\n * The direction to scroll when hovering over this arrow.\n */\n direction: Direction\n /**\n * Whether to keep the element mounted when there's nothing to scroll.\n * When false (default), the element is not rendered.\n * When true, the element is rendered but can be styled via `data-visible=\"false\"`.\n * @default false\n */\n keepMounted?: boolean\n /**\n * Scroll speed in pixels per frame.\n * @default 10\n */\n scrollSpeed?: number\n}\n\nconst stateAttributesMapping = {\n direction: (value: unknown): Record<string, string> | null =>\n value\n ? { [PopupMenuScrollArrowDataAttributes.direction]: String(value) }\n : null,\n visible: (value: unknown): Record<string, string> | null => ({\n 'data-visible': value ? 'true' : 'false',\n }),\n}\n\n/**\n * Base scroll arrow component used by ScrollUpArrow and ScrollDownArrow.\n * Shows when there is content to scroll in the specified direction.\n * Scrolls the list continuously while pointer is over it.\n * Renders a `<div>` element.\n */\nexport const PopupMenuScrollArrow = React.forwardRef<\n HTMLDivElement,\n PopupMenuScrollArrow.Props\n>(function PopupMenuScrollArrow(props, forwardedRef) {\n const {\n direction,\n keepMounted = false,\n scrollSpeed = 10,\n render,\n className,\n style,\n children,\n ...rest\n } = props\n\n const { store } = useSurfaceContext()\n const [visible, setVisible] = React.useState(false)\n const scrollingRef = React.useRef(false)\n const rafRef = React.useRef<number | null>(null)\n\n // Check if there's content to scroll in this direction\n const checkVisibility = React.useCallback(() => {\n const listRef = store.context.refs.listRef\n const list = listRef?.current\n if (!list) {\n setVisible(false)\n return\n }\n\n if (direction === 'up') {\n // Visible when not at top\n setVisible(list.scrollTop > 0)\n } else {\n // Visible when not at bottom\n const atBottom =\n list.scrollTop + list.clientHeight >= list.scrollHeight - 1\n setVisible(!atBottom)\n }\n }, [store, direction])\n\n // Set up scroll listener on the list\n React.useEffect(() => {\n const listRef = store.context.refs.listRef\n const list = listRef?.current\n if (!list) return\n\n // Initial check\n checkVisibility()\n\n // Listen for scroll events\n list.addEventListener('scroll', checkVisibility, { passive: true })\n\n // Also check on resize (content might change)\n const resizeObserver = new ResizeObserver(checkVisibility)\n resizeObserver.observe(list)\n\n return () => {\n list.removeEventListener('scroll', checkVisibility)\n resizeObserver.disconnect()\n }\n }, [store, checkVisibility])\n\n // Also recheck when items change (filteredCount changes)\n const filteredCount = store.useState('filteredCount')\n React.useEffect(() => {\n // Delay to allow DOM to update\n requestAnimationFrame(checkVisibility)\n }, [filteredCount, checkVisibility])\n\n // Continuous scrolling while pointer is over\n const startScrolling = React.useCallback(() => {\n scrollingRef.current = true\n\n const scroll = () => {\n if (!scrollingRef.current) return\n\n const listRef = store.context.refs.listRef\n const list = listRef?.current\n if (list) {\n const delta = direction === 'up' ? -scrollSpeed : scrollSpeed\n list.scrollTop += delta\n }\n\n rafRef.current = requestAnimationFrame(scroll)\n }\n\n rafRef.current = requestAnimationFrame(scroll)\n }, [store, direction, scrollSpeed])\n\n const stopScrolling = React.useCallback(() => {\n scrollingRef.current = false\n if (rafRef.current) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n }, [])\n\n // Clean up on unmount\n React.useEffect(() => {\n return () => {\n if (rafRef.current) {\n cancelAnimationFrame(rafRef.current)\n }\n }\n }, [])\n\n const state: PopupMenuScrollArrow.State = React.useMemo(\n () => ({ direction, visible }),\n [direction, visible],\n )\n\n // Determine if we should render\n const shouldRender = visible || keepMounted\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(\n componentName,\n direction === 'up' ? 'scroll-up-arrow' : 'scroll-down-arrow',\n )\n\n return useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n className,\n style,\n onPointerEnter: (event: React.PointerEvent<HTMLDivElement>) => {\n startScrolling()\n rest.onPointerEnter?.(event)\n },\n onPointerLeave: (event: React.PointerEvent<HTMLDivElement>) => {\n stopScrolling()\n rest.onPointerLeave?.(event)\n },\n children,\n },\n defaultTagName: 'div',\n enabled: shouldRender,\n })\n})\n\nexport namespace PopupMenuScrollArrow {\n export type State = PopupMenuScrollArrowState\n export interface Props extends PopupMenuScrollArrowProps {}\n}\n\n// ============================================================================\n// Convenience Components\n// ============================================================================\n\nexport interface PopupMenuScrollUpArrowProps\n extends Omit<PopupMenuScrollArrowProps, 'direction'> {}\n\n/**\n * A scroll indicator that appears when there's content above.\n * Scrolls the list up continuously while pointer is over it.\n * Renders a `<div>` element.\n */\nexport const PopupMenuScrollUpArrow = React.forwardRef<\n HTMLDivElement,\n PopupMenuScrollUpArrow.Props\n>(function PopupMenuScrollUpArrow(props, forwardedRef) {\n return <PopupMenuScrollArrow ref={forwardedRef} direction=\"up\" {...props} />\n})\n\nexport namespace PopupMenuScrollUpArrow {\n export type State = PopupMenuScrollArrowState\n export interface Props extends PopupMenuScrollUpArrowProps {}\n}\n\nexport interface PopupMenuScrollDownArrowProps\n extends Omit<PopupMenuScrollArrowProps, 'direction'> {}\n\n/**\n * A scroll indicator that appears when there's content below.\n * Scrolls the list down continuously while pointer is over it.\n * Renders a `<div>` element.\n */\nexport const PopupMenuScrollDownArrow = React.forwardRef<\n HTMLDivElement,\n PopupMenuScrollDownArrow.Props\n>(function PopupMenuScrollDownArrow(props, forwardedRef) {\n return <PopupMenuScrollArrow ref={forwardedRef} direction=\"down\" {...props} />\n})\n\nexport namespace PopupMenuScrollDownArrow {\n export type State = PopupMenuScrollArrowState\n export interface Props extends PopupMenuScrollDownArrowProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport { useStableCallback } from '@base-ui/utils/useStableCallback'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n defaultFilter,\n type FilterFn,\n SurfaceContext,\n useListboxContext,\n useSurfaceContext as useParentSurfaceContext,\n} from '../../../listbox/index.js'\nimport { POINTER_EVENT_DEBOUNCE_MS } from '../../constants.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { useFocusOwner } from '../../contexts/focus-owner-context.js'\nimport { usePopupSurfaceId } from '../../contexts/popup-surface-id-context.js'\nimport { useMaybeSubmenuContext } from '../../contexts/submenu-context.js'\n\n// Surface doesn't expose data attributes - using empty state\nexport interface PopupMenuSurfaceState extends Record<string, unknown> {}\n\nexport interface PopupMenuSurfaceProps\n extends ComponentProps<'div', PopupMenuSurface.State> {\n /**\n * Filter function for matching items against search query.\n * Returns a score between 0 and 1 (0 = no match, > 0 = match).\n * Pass `false` to disable filtering entirely.\n * @default commandScore (fuzzy matching)\n */\n filter?: FilterFn | false\n\n /**\n * Controlled search value.\n */\n search?: string\n\n /**\n * Callback when search value changes.\n */\n onSearchChange?: (search: string) => void\n\n /**\n * Default search value for uncontrolled usage.\n * @default ''\n */\n defaultSearch?: string\n\n /**\n * Whether navigation should loop from last to first item and vice versa.\n * @default true\n */\n loop?: boolean\n\n /**\n * Controls auto-highlighting behavior when the menu opens.\n * - `true`: highlight the first item (default)\n * - `false`: don't auto-highlight any item\n * - `string`: highlight the item with this specific value\n * @default true\n */\n autoHighlightFirst?: boolean | string\n\n /**\n * Whether to clear the search query when the menu closes.\n * - `true`: clear immediately when menu closes (default)\n * - `false`: preserve search when menu closes\n * - `'after-exit'`: clear after exit animation completes\n * @default true\n */\n clearSearchOnClose?: boolean | 'after-exit'\n\n /**\n * Whether to skip auto-focusing the input/list when this surface becomes the focus owner.\n * Useful for Combobox where the input is outside the popup and should retain focus.\n * @default false\n */\n skipAutoFocus?: boolean\n\n /**\n * Ordered list of item values when using `filter={false}`.\n * This tells the store the intended display order for navigation/highlighting.\n * Required when `filter={false}` - must always be provided with the current visible items.\n */\n orderedItems?: string[]\n\n children: React.ReactNode\n}\n\n/**\n * Provides search context and manages item registration for popup menu.\n * Place inside PopupMenu.Popup to enable search functionality.\n * Renders a `<div>` element.\n */\nexport const PopupMenuSurface = React.forwardRef<\n HTMLDivElement,\n PopupMenuSurface.Props\n>(function PopupMenuSurface(props, forwardedRef) {\n const {\n filter = defaultFilter,\n search: searchProp,\n onSearchChange,\n defaultSearch = '',\n loop = true,\n autoHighlightFirst = true,\n clearSearchOnClose = true,\n skipAutoFocus = false,\n orderedItems,\n render,\n className,\n style,\n onPointerDown,\n onPointerMove,\n children,\n ...rest\n } = props\n\n // Get store and depth from Listbox context\n const { store, depth, virtualization } = useListboxContext()\n\n // Get submenu context (if inside a submenu)\n const submenuContext = useMaybeSubmenuContext()\n\n // Get focus owner store\n const focusOwnerStore = useFocusOwner()\n\n // Track when surface opened to ignore initial pointer events\n // This prevents focus transfer when a popup appears under a stationary cursor\n const openTimeRef = React.useRef<number>(0)\n\n // Generate stable IDs\n const listId = React.useId()\n const inputId = React.useId()\n const generatedSurfaceId = React.useId()\n\n // Get surfaceId from Popup context (if available) to ensure Popup and Surface share the same ID\n const popupSurfaceId = usePopupSurfaceId()\n\n // Priority: PopupSurfaceIdContext > SubmenuContext > generated\n // This ensures Popup and Surface share the same ID for data attribute tracking\n const surfaceId =\n popupSurfaceId ?? submenuContext?.childSurfaceId ?? generatedSurfaceId\n\n // Subscribe to focus ownership\n const isOwner = focusOwnerStore.useState('isOwner', surfaceId)\n\n // Create stable callback for onSearchChange\n const handleSearchChange = useStableCallback((search: string) => {\n onSearchChange?.(search)\n })\n\n // Update store context with surface configuration\n React.useEffect(() => {\n store.context.filter = filter\n store.context.loop = loop\n store.context.autoHighlightFirst = autoHighlightFirst\n store.context.clearSearchOnClose = clearSearchOnClose\n store.context.listId = listId\n store.context.inputId = inputId\n store.context.onSearchChange = handleSearchChange\n\n // Configure virtualization if enabled via props\n // Note: We only manage virtualization when explicitly provided via props.\n // When virtualization is undefined, we don't clear it - this allows child\n // components (like VirtualizedDataListContent) to manage virtualization\n // independently without being overwritten by Surface.\n if (virtualization) {\n store.setVirtualized(virtualization.virtualized)\n store.setVirtualItems(virtualization.items)\n store.setOnHighlightChange(virtualization.onHighlightChange)\n }\n\n // Apply auto-highlight after context is updated\n // This handles the case where autoHighlightFirst is a string value\n // (the open observer only handles boolean true for backwards compatibility)\n if (typeof autoHighlightFirst === 'string') {\n store.applyAutoHighlight()\n }\n }, [\n store,\n filter,\n loop,\n autoHighlightFirst,\n clearSearchOnClose,\n listId,\n inputId,\n handleSearchChange,\n virtualization,\n ])\n\n // Sync consumer-provided ordered items to store\n // This is separate from the config effect since orderedItems changes on each search\n React.useEffect(() => {\n if (orderedItems) {\n store.setOrderedItems(orderedItems)\n }\n }, [store, orderedItems])\n\n // Sync controlled search prop to store\n store.useControlledProp('search', searchProp, defaultSearch)\n\n // Track the open state\n const open = store.useState('open')\n\n // Ref to the surface element for finding focusable elements\n const surfaceRef = React.useRef<HTMLDivElement | null>(null)\n\n // Record open time when surface opens\n React.useEffect(() => {\n if (open) {\n openTimeRef.current = Date.now()\n }\n }, [open])\n\n // Claim focus ownership when root menu opens\n React.useEffect(() => {\n if (depth === 0 && open) {\n focusOwnerStore.setOwnerId(surfaceId)\n }\n }, [depth, open, surfaceId, focusOwnerStore])\n\n // Auto-focus when becoming owner\n // Skip for Combobox where the input is outside the popup and should retain focus\n React.useEffect(() => {\n if (!isOwner || skipAutoFocus) {\n return\n }\n\n // Use setTimeout(0) to push focus to the next macrotask\n // This allows FloatingFocusManager's cleanup to complete before we focus\n const timeoutId = setTimeout(() => {\n requestAnimationFrame(() => {\n if (!surfaceRef.current) {\n return\n }\n\n // Find input or list within this surface\n const input = surfaceRef.current.querySelector('input')\n const list = surfaceRef.current.querySelector('[role=\"listbox\"]')\n const focusTarget = input ?? list\n\n if (focusTarget && focusTarget instanceof HTMLElement) {\n focusTarget.focus()\n }\n })\n }, 0)\n\n return () => clearTimeout(timeoutId)\n }, [isOwner, skipAutoFocus])\n\n const contextValue = React.useMemo(\n () => ({\n store,\n surfaceId,\n }),\n [store, surfaceId],\n )\n\n // Prevent pointer down from stealing focus from Input\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n event.preventDefault()\n onPointerDown?.(event)\n },\n [onPointerDown],\n )\n\n // Claim focus ownership when pointer moves inside this surface\n // This handles the case when moving from a submenu back to parent\n const handlePointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event)\n\n // Ignore pointer events briefly after surface opens\n // This prevents focus transfer when popup appears under stationary cursor\n const timeSinceOpen = Date.now() - openTimeRef.current\n if (timeSinceOpen < POINTER_EVENT_DEBOUNCE_MS) {\n return\n }\n\n // Check if the event target is actually within this surface's DOM\n // This prevents parent surfaces from claiming ownership when events\n // bubble through React portals from child surfaces\n const target = event.target as Node\n if (!surfaceRef.current?.contains(target)) {\n return\n }\n\n // Check store directly to avoid stale reactive state issues\n // Only claim ownership if we're not already the owner\n if (focusOwnerStore.state.ownerId !== surfaceId) {\n focusOwnerStore.setOwnerId(surfaceId)\n }\n },\n [onPointerMove, surfaceId, focusOwnerStore],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'surface')\n\n const element = useRender({\n render,\n ref: [surfaceRef, forwardedRef],\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n className,\n style,\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n children,\n },\n defaultTagName: 'div',\n })\n\n return (\n <SurfaceContext.Provider value={contextValue}>\n {element}\n </SurfaceContext.Provider>\n )\n})\n\nexport namespace PopupMenuSurface {\n export type State = PopupMenuSurfaceState\n export interface Props extends PopupMenuSurfaceProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport {\n createChangeEventDetails,\n REASONS,\n} from '../../../../utils/events/index.js'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { ItemContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport type {\n CheckedChangeEventDetails,\n CheckedChangeReason,\n} from '../../events.js'\nimport { usePopupMenuItem } from '../../hooks/use-popup-menu-item.js'\nimport { PopupMenuCheckboxItemDataAttributes } from './checkbox-item.data-attrs.js'\nimport {\n CheckboxItemContext,\n type CheckboxItemContextValue,\n} from './checkbox-item-context.js'\n\nexport { PopupMenuCheckboxItemDataAttributes }\n\nexport interface PopupMenuCheckboxItemState extends Record<string, unknown> {\n /**\n * Whether the item is highlighted (via keyboard or pointer).\n */\n highlighted: boolean\n /**\n * Whether the item is disabled.\n */\n disabled: boolean\n /**\n * Whether the item is currently checked.\n */\n checked: boolean\n}\n\nexport interface PopupMenuCheckboxItemProps\n extends ComponentProps<'div', PopupMenuCheckboxItem.State> {\n /**\n * The controlled checked state.\n */\n checked?: boolean\n\n /**\n * The default checked state for uncontrolled mode.\n * @default false\n */\n defaultChecked?: boolean\n\n /**\n * Callback fired when the checked state changes.\n * The second parameter contains event details including the reason for the change.\n */\n onCheckedChange?: (\n checked: boolean,\n eventDetails: CheckedChangeEventDetails,\n ) => void\n\n /**\n * Additional keywords to match against when filtering.\n * Useful for aliases or synonyms.\n */\n keywords?: string[]\n\n /**\n * Whether this item is disabled.\n * Disabled items are not selectable and are skipped during keyboard navigation.\n * @default false\n */\n disabled?: boolean\n\n /**\n * Callback when this item is selected (via click or Enter key).\n */\n onSelect?: () => void\n\n /**\n * Whether to force render this item regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n /**\n * Whether clicking this item should close the menu.\n * @default false\n */\n closeOnClick?: boolean\n\n /**\n * Keyboard shortcut to trigger this item.\n * When the menu is focused and the user presses this key, the item will be selected.\n * Should be a single character (e.g., \"1\", \"a\", etc.).\n */\n shortcut?: string\n}\n\nconst stateAttributesMapping = {\n checked: (value: unknown): Record<string, string> | null =>\n value\n ? { [PopupMenuCheckboxItemDataAttributes.checked]: '' }\n : { [PopupMenuCheckboxItemDataAttributes.unchecked]: '' },\n highlighted: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuCheckboxItemDataAttributes.highlighted]: '' } : null,\n disabled: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuCheckboxItemDataAttributes.disabled]: '' } : null,\n}\n\n/**\n * A selectable checkbox item within a popup menu.\n * Manages its own checked state independently.\n * Renders a `<div>` element with role=\"menuitemcheckbox\".\n */\nexport const PopupMenuCheckboxItem = React.forwardRef<\n HTMLDivElement,\n PopupMenuCheckboxItem.Props\n>(function PopupMenuCheckboxItem(props, forwardedRef) {\n const {\n id,\n checked: checkedProp,\n defaultChecked = false,\n onCheckedChange,\n keywords,\n disabled = false,\n onSelect,\n forceMount = false,\n closeOnClick = false,\n shortcut,\n render,\n className,\n style,\n onClick,\n onPointerDown,\n onPointerMove,\n children,\n ...rest\n } = props\n\n // Controlled/uncontrolled state management\n const [internalChecked, setInternalChecked] =\n React.useState<boolean>(defaultChecked)\n const isControlled = checkedProp !== undefined\n const checked = isControlled ? checkedProp : internalChecked\n\n const toggleChecked = React.useCallback(\n (reason: CheckedChangeReason = REASONS.itemPress, event?: Event) => {\n const newChecked = !checked\n const eventDetails = createChangeEventDetails(reason, event)\n\n // Call user's callback first\n onCheckedChange?.(newChecked, eventDetails)\n\n // If canceled, don't update internal state\n if (eventDetails.isCanceled) return\n\n if (!isControlled) {\n setInternalChecked(newChecked)\n }\n },\n [checked, isControlled, onCheckedChange],\n )\n\n const item = usePopupMenuItem({\n id,\n keywords,\n disabled,\n forceMount,\n shortcut,\n closeOnClick,\n children,\n })\n\n // Register the select handler that toggles checked state\n // Note: closeOnClick is handled by usePopupMenuItem's onAfterSelect\n React.useEffect(() => {\n const handleSelect = () => {\n if (disabled) return\n toggleChecked()\n onSelect?.()\n }\n return item.registerSelect(handleSelect)\n }, [disabled, toggleChecked, onSelect, item])\n\n const state: PopupMenuCheckboxItem.State = React.useMemo(\n () => ({ highlighted: item.isHighlighted, disabled, checked }),\n [item.isHighlighted, disabled, checked],\n )\n\n const checkboxItemContextValue: CheckboxItemContextValue = React.useMemo(\n () => ({\n ...item.contextValue,\n checked,\n toggle: toggleChecked,\n }),\n [item.contextValue, checked, toggleChecked],\n )\n\n // Merge user-provided handlers with item handlers\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onClick?.(event)\n if (!event.defaultPrevented) {\n item.handlers.onClick(event)\n }\n },\n [onClick, item.handlers],\n )\n\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n item.handlers.onPointerDown(event)\n onPointerDown?.(event)\n },\n [item.handlers, onPointerDown],\n )\n\n const handlePointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event)\n if (!event.defaultPrevented) {\n item.handlers.onPointerMove(event)\n }\n },\n [onPointerMove, item.handlers],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'checkbox-item')\n\n const element = useRender({\n render,\n ref: [item.ref, forwardedRef],\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n id: item.id,\n role: 'menuitemcheckbox',\n tabIndex: -1,\n 'aria-checked': checked,\n 'aria-disabled': disabled || undefined,\n className,\n style,\n onClick: handleClick,\n onPointerMove: handlePointerMove,\n onPointerDown: handlePointerDown,\n children,\n },\n enabled: item.isVisible,\n defaultTagName: 'div',\n })\n\n if (!item.isVisible) {\n return null\n }\n\n return (\n <ItemContext.Provider value={item.contextValue}>\n <CheckboxItemContext.Provider value={checkboxItemContextValue}>\n {element}\n </CheckboxItemContext.Provider>\n </ItemContext.Provider>\n )\n})\n\nexport namespace PopupMenuCheckboxItem {\n export type State = PopupMenuCheckboxItemState\n export interface Props extends PopupMenuCheckboxItemProps {}\n}\n","export enum PopupMenuCheckboxItemDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-checkbox-item' | 'bazzaui-context-menu-checkbox-item'}\n */\n slot = 'bazzaui-[component]-checkbox-item',\n /**\n * Present when the checkbox item is checked.\n */\n checked = 'data-checked',\n /**\n * Present when the checkbox item is unchecked.\n */\n unchecked = 'data-unchecked',\n /**\n * Present when the item is highlighted (via keyboard or pointer).\n */\n highlighted = 'data-highlighted',\n /**\n * Present when the item is disabled.\n */\n disabled = 'data-disabled',\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { ItemContextValue } from '../../../listbox/index.js'\nimport type { CheckedChangeReason } from '../../events.js'\n\n/**\n * Context value for checkbox menu items.\n * Extends ItemContextValue with checkbox-specific state.\n */\nexport interface CheckboxItemContextValue extends ItemContextValue {\n /** Whether this checkbox item is currently checked */\n checked: boolean\n /**\n * Toggle the checked state.\n * @param reason - The reason for the change (default: 'item-press')\n * @param event - The native DOM event that triggered the change\n */\n toggle: (reason?: CheckedChangeReason, event?: Event) => void\n}\n\nconst CheckboxItemContext =\n React.createContext<CheckboxItemContextValue | null>(null)\n\nexport function useCheckboxItemContext(): CheckboxItemContextValue {\n const context = React.useContext(CheckboxItemContext)\n if (!context) {\n throw new Error(\n 'PopupMenu.CheckboxItemIndicator must be used within PopupMenu.CheckboxItem',\n )\n }\n return context\n}\n\nexport { CheckboxItemContext }\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { PopupMenuCheckboxItemDataAttributes } from './checkbox-item.data-attrs.js'\nimport { useCheckboxItemContext } from './checkbox-item-context.js'\n\nexport interface PopupMenuCheckboxItemIndicatorState\n extends Record<string, unknown> {\n /**\n * Whether the parent checkbox item is currently checked.\n */\n checked: boolean\n /**\n * Whether the parent checkbox item is currently highlighted.\n */\n highlighted: boolean\n /**\n * Whether the parent checkbox item is disabled.\n */\n disabled: boolean\n /**\n * Toggle the checked state without triggering closeOnClick.\n * Useful when you want clicking directly on the indicator to toggle\n * without closing the menu.\n */\n toggle: () => void\n}\n\nexport interface PopupMenuCheckboxItemIndicatorProps\n extends ComponentProps<'span', PopupMenuCheckboxItemIndicator.State> {\n /**\n * Whether to keep the indicator mounted in the DOM when unchecked.\n * Useful for animations.\n * @default false\n */\n keepMounted?: boolean\n}\n\nconst stateAttributesMapping = {\n checked: (value: unknown): Record<string, string> | null =>\n value\n ? { [PopupMenuCheckboxItemDataAttributes.checked]: '' }\n : { [PopupMenuCheckboxItemDataAttributes.unchecked]: '' },\n disabled: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuCheckboxItemDataAttributes.disabled]: '' } : null,\n}\n\n/**\n * A visual indicator that shows when a CheckboxItem is checked.\n * Must be used within a CheckboxItem component.\n * Renders a `<span>` element with aria-hidden=\"true\".\n */\nexport const PopupMenuCheckboxItemIndicator = React.forwardRef<\n HTMLSpanElement,\n PopupMenuCheckboxItemIndicator.Props\n>(function PopupMenuCheckboxItemIndicator(props, forwardedRef) {\n const {\n keepMounted = false,\n render,\n className,\n style,\n children,\n ...rest\n } = props\n\n const { checked, highlighted, disabled, toggle } = useCheckboxItemContext()\n\n const state: PopupMenuCheckboxItemIndicator.State = React.useMemo(\n () => ({ checked, highlighted, disabled, toggle }),\n [checked, highlighted, disabled, toggle],\n )\n\n const shouldRender = keepMounted || checked\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'checkbox-item-indicator')\n\n return useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n 'aria-hidden': true,\n className,\n style,\n children,\n },\n enabled: shouldRender,\n defaultTagName: 'span',\n })\n})\n\nexport namespace PopupMenuCheckboxItemIndicator {\n export type State = PopupMenuCheckboxItemIndicatorState\n export interface Props extends PopupMenuCheckboxItemIndicatorProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { ItemContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { usePopupMenuItem } from '../../hooks/use-popup-menu-item.js'\nimport { PopupMenuItemDataAttributes } from './item.data-attrs.js'\n\nexport { PopupMenuItemDataAttributes }\n\nexport interface PopupMenuItemState extends Record<string, unknown> {\n /**\n * Whether the item is highlighted (via keyboard or pointer).\n */\n highlighted: boolean\n /**\n * Whether the item is disabled.\n */\n disabled: boolean\n}\n\nexport interface PopupMenuItemProps\n extends ComponentProps<'div', PopupMenuItem.State> {\n /**\n * Unique value for this item used for filtering.\n * If not provided, will be inferred from textContent.\n */\n value?: string\n\n /**\n * Additional keywords to match against when filtering.\n * Useful for aliases or synonyms.\n */\n keywords?: string[]\n\n /**\n * Whether this item is disabled.\n * Disabled items are not selectable and are skipped during keyboard navigation.\n */\n disabled?: boolean\n\n /**\n * Callback when this item is selected (via click or Enter key).\n */\n onSelect?: () => void\n\n /**\n * Whether to force render this item regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n /**\n * Whether clicking this item should close the menu.\n * @default true\n */\n closeOnClick?: boolean\n\n /**\n * Keyboard shortcut to trigger this item.\n * When the menu is focused and the user presses this key, the item will be selected.\n * Should be a single character (e.g., \"1\", \"a\", etc.).\n */\n shortcut?: string\n}\n\nconst stateAttributesMapping = {\n highlighted: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuItemDataAttributes.highlighted]: '' } : null,\n disabled: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuItemDataAttributes.disabled]: '' } : null,\n}\n\n/**\n * A selectable item in the popup menu.\n * Renders a `<div>` element with role=\"option\".\n */\nexport const PopupMenuItem = React.forwardRef<\n HTMLDivElement,\n PopupMenuItem.Props\n>(function PopupMenuItem(props, forwardedRef) {\n const {\n id,\n value,\n keywords,\n disabled = false,\n onSelect,\n forceMount = false,\n closeOnClick = true,\n shortcut,\n render,\n className,\n style,\n onClick,\n onPointerDown,\n onPointerMove,\n children,\n ...rest\n } = props\n\n const item = usePopupMenuItem({\n id,\n value,\n keywords,\n disabled,\n forceMount,\n shortcut,\n onSelect,\n closeOnClick,\n children,\n })\n\n const state: PopupMenuItem.State = React.useMemo(\n () => ({\n highlighted: item.isHighlighted,\n disabled,\n }),\n [item.isHighlighted, disabled],\n )\n\n // Merge user-provided handlers with item handlers\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onClick?.(event)\n if (!event.defaultPrevented) {\n item.handlers.onClick(event)\n }\n },\n [onClick, item.handlers],\n )\n\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n item.handlers.onPointerDown(event)\n onPointerDown?.(event)\n },\n [item.handlers, onPointerDown],\n )\n\n const handlePointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event)\n if (!event.defaultPrevented) {\n item.handlers.onPointerMove(event)\n }\n },\n [onPointerMove, item.handlers],\n )\n\n // Wrap children with ItemContext.Provider so child components can access item state\n const wrappedChildren = (\n <ItemContext.Provider value={item.contextValue}>\n {children}\n </ItemContext.Provider>\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'item')\n\n return useRender({\n render,\n ref: [item.ref, forwardedRef],\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n id: item.id,\n role: 'option',\n tabIndex: -1,\n 'aria-selected': item.isHighlighted,\n 'aria-disabled': disabled || undefined,\n className,\n style,\n onClick: handleClick,\n onPointerMove: handlePointerMove,\n onPointerDown: handlePointerDown,\n children: wrappedChildren,\n },\n enabled: item.isVisible,\n defaultTagName: 'div',\n })\n})\n\nexport namespace PopupMenuItem {\n export type State = PopupMenuItemState\n export interface Props extends PopupMenuItemProps {}\n}\n","export enum PopupMenuItemDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-item' | 'bazzaui-context-menu-item' | 'bazzaui-select-item' | 'bazzaui-combobox-item'}\n */\n slot = 'bazzaui-[component]-item',\n /**\n * Present when the item is highlighted (via keyboard or pointer).\n */\n highlighted = 'data-highlighted',\n /**\n * Present when the item is disabled.\n */\n disabled = 'data-disabled',\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport {\n createChangeEventDetails,\n REASONS,\n} from '../../../../utils/events/index.js'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { GroupContext, useSurfaceContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport type {\n RadioValueChangeEventDetails,\n RadioValueChangeReason,\n} from '../../events.js'\nimport { PopupMenuRadioGroupDataAttributes } from './radio-group.data-attrs.js'\nimport {\n RadioGroupContext,\n type RadioGroupContextValue,\n} from './radio-group-context.js'\n\nexport { PopupMenuRadioGroupDataAttributes }\n\nexport interface PopupMenuRadioGroupState extends Record<string, unknown> {\n /**\n * Whether the radio group is disabled.\n */\n disabled: boolean\n}\n\nexport interface PopupMenuRadioGroupProps\n extends ComponentProps<'div', PopupMenuRadioGroup.State> {\n /**\n * The controlled selected value.\n */\n value?: string\n\n /**\n * The default value for uncontrolled mode.\n */\n defaultValue?: string\n\n /**\n * Callback fired when the selected value changes.\n * The second parameter contains event details including the reason for the change.\n */\n onValueChange?: (\n value: string,\n eventDetails: RadioValueChangeEventDetails,\n ) => void\n\n /**\n * Whether all items in this group are disabled.\n * @default false\n */\n disabled?: boolean\n\n /**\n * Whether to force render this group regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n children: React.ReactNode\n}\n\nconst stateAttributesMapping = {\n disabled: (value: unknown) =>\n value ? { [PopupMenuRadioGroupDataAttributes.disabled]: '' } : null,\n}\n\n/**\n * Groups radio items together and manages the selected value.\n * Only one item can be selected at a time within a radio group.\n * Renders a `<div>` element with role=\"group\".\n */\nexport const PopupMenuRadioGroup = React.forwardRef(\n function PopupMenuRadioGroup(\n props: PopupMenuRadioGroupProps,\n forwardedRef: React.ForwardedRef<HTMLDivElement>,\n ) {\n const {\n value: valueProp,\n defaultValue,\n onValueChange,\n disabled = false,\n forceMount = false,\n render,\n className,\n style,\n children,\n ...rest\n } = props\n\n const { store } = useSurfaceContext()\n const groupId = React.useId()\n\n // Controlled/uncontrolled state management\n const [internalValue, setInternalValue] = React.useState<\n string | undefined\n >(defaultValue)\n const isControlled = valueProp !== undefined\n const value = isControlled ? valueProp : internalValue\n\n const setValue = React.useCallback(\n (\n newValue: string,\n reason: RadioValueChangeReason = REASONS.itemPress,\n event?: Event,\n ) => {\n const eventDetails = createChangeEventDetails(reason, event)\n\n // Call user's callback first\n onValueChange?.(newValue, eventDetails)\n\n // If canceled, don't update internal state\n if (eventDetails.isCanceled) return\n\n if (!isControlled) {\n setInternalValue(newValue)\n }\n },\n [isControlled, onValueChange],\n )\n\n // Register group with store for filtering visibility\n React.useEffect(() => {\n const unregister = store.registerGroup(groupId)\n return unregister\n }, [groupId, store])\n\n // Check visibility using selector\n const isGroupVisible = store.useState('isGroupVisible', groupId)\n const isVisible = forceMount || isGroupVisible\n\n // Context values\n const radioGroupContextValue: RadioGroupContextValue = React.useMemo(\n () => ({ value, setValue, disabled }),\n [value, setValue, disabled],\n )\n\n const groupContextValue = React.useMemo(() => ({ groupId }), [groupId])\n\n const state: PopupMenuRadioGroup.State = React.useMemo(\n () => ({ disabled }),\n [disabled],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'radio-group')\n\n const element = useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n role: 'group',\n 'aria-disabled': disabled || undefined,\n className,\n style,\n children,\n },\n enabled: isVisible,\n defaultTagName: 'div',\n })\n\n if (!isVisible) {\n return null\n }\n\n return (\n <RadioGroupContext.Provider value={radioGroupContextValue}>\n <GroupContext.Provider value={groupContextValue}>\n {element}\n </GroupContext.Provider>\n </RadioGroupContext.Provider>\n )\n },\n)\n\nexport namespace PopupMenuRadioGroup {\n export type State = PopupMenuRadioGroupState\n export interface Props extends PopupMenuRadioGroupProps {}\n}\n","export enum PopupMenuRadioGroupDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-radio-group' | 'bazzaui-context-menu-radio-group'}\n */\n slot = 'bazzaui-[component]-radio-group',\n /**\n * Present when the radio group is disabled.\n */\n disabled = 'data-disabled',\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { RadioValueChangeReason } from '../../events.js'\n\nexport interface RadioGroupContextValue {\n /** Current selected value */\n value: string | undefined\n /**\n * Function to update the selected value.\n * @param value - The new value to select\n * @param reason - The reason for the change (default: 'item-press')\n * @param event - The native DOM event that triggered the change\n */\n setValue: (\n value: string,\n reason?: RadioValueChangeReason,\n event?: Event,\n ) => void\n /** Whether all items in the group are disabled */\n disabled: boolean\n}\n\nconst RadioGroupContext = React.createContext<RadioGroupContextValue | null>(\n null,\n)\n\nexport function useRadioGroupContext(): RadioGroupContextValue {\n const context = React.useContext(RadioGroupContext)\n if (!context) {\n throw new Error(\n 'PopupMenu.RadioItem must be used within PopupMenu.RadioGroup',\n )\n }\n return context\n}\n\nexport { RadioGroupContext }\n","'use client'\n\nimport * as React from 'react'\nimport {\n createChangeEventDetails,\n REASONS,\n} from '../../../../utils/events/index.js'\nimport type {\n RadioValueChangeEventDetails,\n RadioValueChangeReason,\n} from '../../events.js'\nimport {\n RadioGroupContext,\n type RadioGroupContextValue,\n} from './radio-group-context.js'\n\nexport interface PopupMenuRadioGroupValueProps {\n /**\n * The controlled selected value.\n */\n value: string | undefined\n\n /**\n * Callback fired when the selected value changes.\n * The second parameter contains event details including the reason for the change.\n */\n onValueChange?: (\n value: string,\n eventDetails: RadioValueChangeEventDetails,\n ) => void\n\n /**\n * Whether all items in this group are disabled.\n * @default false\n */\n disabled?: boolean\n\n /**\n * Children to render within the radio group context.\n */\n children: React.ReactNode\n}\n\n/**\n * Headless provider for radio group state.\n * Use this to wrap DataSurface when using RadioItems in deep search.\n * Does not render any DOM element - only provides context.\n *\n * @example\n * ```tsx\n * const [theme, setTheme] = useState('light')\n *\n * <DropdownMenu.RadioGroupValue value={theme} onValueChange={setTheme}>\n * <DropdownMenu.DataSurface content={content}>\n * ...\n * </DropdownMenu.DataSurface>\n * </DropdownMenu.RadioGroupValue>\n * ```\n */\nexport function PopupMenuRadioGroupValue(props: PopupMenuRadioGroupValueProps) {\n const { value, onValueChange, disabled = false, children } = props\n\n const setValue = React.useCallback(\n (\n newValue: string,\n reason: RadioValueChangeReason = REASONS.itemPress,\n event?: Event,\n ) => {\n const eventDetails = createChangeEventDetails(reason, event)\n onValueChange?.(newValue, eventDetails)\n },\n [onValueChange],\n )\n\n const contextValue: RadioGroupContextValue = React.useMemo(\n () => ({ value, setValue, disabled }),\n [value, setValue, disabled],\n )\n\n return (\n <RadioGroupContext.Provider value={contextValue}>\n {children}\n </RadioGroupContext.Provider>\n )\n}\n\nexport namespace PopupMenuRadioGroupValue {\n export interface Props extends PopupMenuRadioGroupValueProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { ItemContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { usePopupMenuItem } from '../../hooks/use-popup-menu-item.js'\nimport { useRadioGroupContext } from '../radio-group/radio-group-context.js'\nimport { PopupMenuRadioItemDataAttributes } from './radio-item.data-attrs.js'\nimport {\n RadioItemContext,\n type RadioItemContextValue,\n} from './radio-item-context.js'\n\nexport { PopupMenuRadioItemDataAttributes }\n\nexport interface PopupMenuRadioItemState extends Record<string, unknown> {\n /**\n * Whether the item is highlighted (via keyboard or pointer).\n */\n highlighted: boolean\n /**\n * Whether the item is disabled.\n */\n disabled: boolean\n /**\n * Whether the item is currently selected/checked.\n */\n checked: boolean\n}\n\nexport interface PopupMenuRadioItemProps\n extends ComponentProps<'div', PopupMenuRadioItem.State> {\n /**\n * The value to set when this item is selected.\n * This is required and must be unique within the RadioGroup.\n */\n value: string\n\n /**\n * Additional keywords to match against when filtering.\n * Useful for aliases or synonyms.\n */\n keywords?: string[]\n\n /**\n * Whether this item is disabled.\n * Disabled items are not selectable and are skipped during keyboard navigation.\n * @default false\n */\n disabled?: boolean\n\n /**\n * Callback when this item is selected.\n */\n onSelect?: () => void\n\n /**\n * Whether to force render this item regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n /**\n * Whether clicking this item should close the menu.\n * @default false\n */\n closeOnClick?: boolean\n\n /**\n * Keyboard shortcut to trigger this item.\n * When the menu is focused and the user presses this key, the item will be selected.\n * Should be a single character (e.g., \"1\", \"a\", etc.).\n */\n shortcut?: string\n}\n\nconst stateAttributesMapping = {\n checked: (value: unknown): Record<string, string> | null =>\n value\n ? { [PopupMenuRadioItemDataAttributes.checked]: '' }\n : { [PopupMenuRadioItemDataAttributes.unchecked]: '' },\n highlighted: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuRadioItemDataAttributes.highlighted]: '' } : null,\n disabled: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuRadioItemDataAttributes.disabled]: '' } : null,\n}\n\n/**\n * A selectable radio item within a RadioGroup.\n * Only one RadioItem can be selected at a time within a RadioGroup.\n * Renders a `<div>` element with role=\"menuitemradio\".\n */\nexport const PopupMenuRadioItem = React.forwardRef(function PopupMenuRadioItem(\n props: PopupMenuRadioItemProps,\n forwardedRef: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n id,\n value,\n keywords,\n disabled: disabledProp = false,\n onSelect,\n forceMount = false,\n closeOnClick = false,\n shortcut,\n render,\n className,\n style,\n onClick,\n onPointerDown,\n onPointerMove,\n children,\n ...rest\n } = props\n\n const radioGroupContext = useRadioGroupContext()\n\n // Combine disabled from props and RadioGroup\n const disabled = disabledProp || radioGroupContext.disabled\n\n // Check if this item is selected\n const checked = radioGroupContext.value === value\n\n const item = usePopupMenuItem({\n id,\n keywords,\n disabled,\n forceMount,\n shortcut,\n closeOnClick,\n children,\n })\n\n // Register the select handler that sets the radio value\n // Note: closeOnClick is handled by usePopupMenuItem's onAfterSelect\n React.useEffect(() => {\n const handleSelect = () => {\n if (disabled) return\n radioGroupContext.setValue(value)\n onSelect?.()\n }\n return item.registerSelect(handleSelect)\n }, [disabled, radioGroupContext, value, onSelect, item])\n\n const state: PopupMenuRadioItem.State = React.useMemo(\n () => ({ highlighted: item.isHighlighted, disabled, checked }),\n [item.isHighlighted, disabled, checked],\n )\n\n const radioItemContextValue: RadioItemContextValue = React.useMemo(\n () => ({\n ...item.contextValue,\n checked,\n }),\n [item.contextValue, checked],\n )\n\n // Merge user-provided handlers with item handlers\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n onClick?.(event)\n if (!event.defaultPrevented) {\n item.handlers.onClick(event)\n }\n },\n [onClick, item.handlers],\n )\n\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n item.handlers.onPointerDown(event)\n onPointerDown?.(event)\n },\n [item.handlers, onPointerDown],\n )\n\n const handlePointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event)\n if (!event.defaultPrevented) {\n item.handlers.onPointerMove(event)\n }\n },\n [onPointerMove, item.handlers],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'radio-item')\n\n const element = useRender({\n render,\n ref: [item.ref, forwardedRef],\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n id: item.id,\n role: 'menuitemradio',\n tabIndex: -1,\n 'aria-checked': checked,\n 'aria-disabled': disabled || undefined,\n className,\n style,\n onClick: handleClick,\n onPointerMove: handlePointerMove,\n onPointerDown: handlePointerDown,\n children,\n },\n enabled: item.isVisible,\n defaultTagName: 'div',\n })\n\n if (!item.isVisible) {\n return null\n }\n\n return (\n <ItemContext.Provider value={item.contextValue}>\n <RadioItemContext.Provider value={radioItemContextValue}>\n {element}\n </RadioItemContext.Provider>\n </ItemContext.Provider>\n )\n})\n\nexport namespace PopupMenuRadioItem {\n export type State = PopupMenuRadioItemState\n export interface Props extends PopupMenuRadioItemProps {}\n}\n","export enum PopupMenuRadioItemDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-radio-item' | 'bazzaui-context-menu-radio-item'}\n */\n slot = 'bazzaui-[component]-radio-item',\n /**\n * Present when the radio item is checked/selected.\n */\n checked = 'data-checked',\n /**\n * Present when the radio item is unchecked.\n */\n unchecked = 'data-unchecked',\n /**\n * Present when the item is highlighted (via keyboard or pointer).\n */\n highlighted = 'data-highlighted',\n /**\n * Present when the item is disabled.\n */\n disabled = 'data-disabled',\n}\n","'use client'\n\nimport * as React from 'react'\nimport type { ItemContextValue } from '../../../listbox/index.js'\n\n/**\n * Context value for radio menu items.\n * Extends ItemContextValue with radio-specific state.\n */\nexport interface RadioItemContextValue extends ItemContextValue {\n /** Whether this radio item is currently selected */\n checked: boolean\n}\n\nconst RadioItemContext = React.createContext<RadioItemContextValue | null>(null)\n\nexport function useRadioItemContext(): RadioItemContextValue {\n const context = React.useContext(RadioItemContext)\n if (!context) {\n throw new Error(\n 'PopupMenu.RadioItemIndicator must be used within PopupMenu.RadioItem',\n )\n }\n return context\n}\n\nexport { RadioItemContext }\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { PopupMenuRadioItemDataAttributes } from './radio-item.data-attrs.js'\nimport { useRadioItemContext } from './radio-item-context.js'\n\nexport interface PopupMenuRadioItemIndicatorState\n extends Record<string, unknown> {\n /**\n * Whether the parent radio item is currently selected/checked.\n */\n checked: boolean\n /**\n * Whether the parent radio item is currently highlighted.\n */\n highlighted: boolean\n /**\n * Whether the parent radio item is disabled.\n */\n disabled: boolean\n}\n\nexport interface PopupMenuRadioItemIndicatorProps\n extends ComponentProps<'span', PopupMenuRadioItemIndicator.State> {\n /**\n * Whether to keep the indicator mounted in the DOM when unchecked.\n * Useful for animations.\n * @default false\n */\n keepMounted?: boolean\n}\n\nconst stateAttributesMapping = {\n checked: (value: unknown): Record<string, string> | null =>\n value\n ? { [PopupMenuRadioItemDataAttributes.checked]: '' }\n : { [PopupMenuRadioItemDataAttributes.unchecked]: '' },\n disabled: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuRadioItemDataAttributes.disabled]: '' } : null,\n}\n\n/**\n * A visual indicator that shows when a RadioItem is selected.\n * Must be used within a RadioItem component.\n * Renders a `<span>` element with aria-hidden=\"true\".\n */\nexport const PopupMenuRadioItemIndicator = React.forwardRef<\n HTMLSpanElement,\n PopupMenuRadioItemIndicator.Props\n>(function PopupMenuRadioItemIndicator(props, forwardedRef) {\n const {\n keepMounted = false,\n render,\n className,\n style,\n children,\n ...rest\n } = props\n\n const { checked, highlighted, disabled } = useRadioItemContext()\n\n const state: PopupMenuRadioItemIndicator.State = React.useMemo(\n () => ({ checked, highlighted, disabled }),\n [checked, highlighted, disabled],\n )\n\n const shouldRender = keepMounted || checked\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'radio-item-indicator')\n\n return useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n 'aria-hidden': true,\n className,\n style,\n children,\n },\n enabled: shouldRender,\n defaultTagName: 'span',\n })\n})\n\nexport namespace PopupMenuRadioItemIndicator {\n export type State = PopupMenuRadioItemIndicatorState\n export interface Props extends PopupMenuRadioItemIndicatorProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { GroupContext, useSurfaceContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\n\nexport interface PopupMenuGroupState extends Record<string, unknown> {\n /**\n * Whether the group is hidden due to no matching items.\n */\n hidden: boolean\n}\n\nexport interface PopupMenuGroupProps\n extends ComponentProps<'div', PopupMenuGroup.State> {\n /**\n * Whether to force render this group regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n children: React.ReactNode\n}\n\n/**\n * Groups related popup menu items together.\n * Hidden when no child items match the current filter.\n * Renders a `<div>` element with role=\"group\".\n */\nexport const PopupMenuGroup = React.forwardRef<\n HTMLDivElement,\n PopupMenuGroup.Props\n>(function PopupMenuGroup(props, forwardedRef) {\n const {\n forceMount = false,\n render,\n className,\n style,\n children,\n ...rest\n } = props\n\n const { store } = useSurfaceContext()\n const groupId = React.useId()\n\n // Register group with store\n React.useEffect(() => {\n const unregister = store.registerGroup(groupId)\n return unregister\n }, [groupId, store])\n\n // Check if group has visible items using selector\n const isGroupVisible = store.useState('isGroupVisible', groupId)\n const isVisible = forceMount || isGroupVisible\n\n // Provide group context to children\n const groupContextValue = React.useMemo(() => ({ groupId }), [groupId])\n\n const state: PopupMenuGroup.State = React.useMemo(\n () => ({\n hidden: !isVisible,\n }),\n [isVisible],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'group')\n\n const element = useRender({\n render,\n ref: forwardedRef,\n state,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n // Using role=\"presentation\" since we're inside a listbox.\n // The group is purely visual - items are the semantic options.\n role: 'presentation',\n className,\n style,\n children,\n },\n enabled: isVisible,\n defaultTagName: 'div',\n })\n\n if (!isVisible) {\n return null\n }\n\n return (\n <GroupContext.Provider value={groupContextValue}>\n {element}\n </GroupContext.Provider>\n )\n})\n\nexport namespace PopupMenuGroup {\n export type State = PopupMenuGroupState\n export interface Props extends PopupMenuGroupProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\n\n// GroupLabel doesn't have any state - using an empty object type\nexport interface PopupMenuGroupLabelState extends Record<string, unknown> {}\n\nexport interface PopupMenuGroupLabelProps\n extends ComponentProps<'div', PopupMenuGroupLabel.State> {\n children: React.ReactNode\n}\n\n/**\n * A label/heading for a group of popup menu items.\n * Renders a `<div>` element with role=\"presentation\".\n */\nexport const PopupMenuGroupLabel = React.forwardRef<\n HTMLDivElement,\n PopupMenuGroupLabel.Props\n>(function PopupMenuGroupLabel(props, forwardedRef) {\n const { render, className, style, children, ...rest } = props\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'group-label')\n\n return useRender({\n render,\n ref: forwardedRef,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n // Presentation role - this is a visual label, not interactive\n role: 'presentation',\n // aria-hidden since the group label is decorative for screen readers\n // in the context of a listbox (options are the semantic elements)\n 'aria-hidden': 'true',\n className,\n style,\n children,\n },\n defaultTagName: 'div',\n })\n})\n\nexport namespace PopupMenuGroupLabel {\n export type State = PopupMenuGroupLabelState\n export interface Props extends PopupMenuGroupLabelProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { useSurfaceContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\n\n// Separator doesn't have any state - using an empty object type\nexport interface PopupMenuSeparatorState extends Record<string, unknown> {}\n\nexport interface PopupMenuSeparatorProps\n extends ComponentProps<'div', PopupMenuSeparator.State> {\n /**\n * Whether to always render the separator, even during search.\n * By default, separators are hidden when there's an active search query.\n * @default false\n */\n alwaysRender?: boolean\n}\n\n/**\n * A visual separator between popup menu items.\n * Hidden during active search unless `alwaysRender` is true.\n * Renders a `<div>` element with role=\"separator\".\n */\nexport const PopupMenuSeparator = React.forwardRef<\n HTMLDivElement,\n PopupMenuSeparator.Props\n>(function PopupMenuSeparator(props, forwardedRef) {\n const { alwaysRender = false, render, className, style, ...rest } = props\n\n const { store } = useSurfaceContext()\n\n // Get search state from store\n const search = store.useState('search')\n\n // Hide separator when there's an active search (unless alwaysRender)\n const hasSearch = search.length > 0\n const isHidden = hasSearch && !alwaysRender\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'separator')\n\n const element = useRender({\n render,\n ref: forwardedRef,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n // Using role=\"none\" as this is a purely visual separator within a listbox.\n // The semantic separator role requires focus for interactive separators.\n role: 'none',\n className,\n style,\n },\n defaultTagName: 'div',\n })\n\n if (isHidden) {\n return null\n }\n\n return element\n})\n\nexport namespace PopupMenuSeparator {\n export type State = PopupMenuSeparatorState\n export interface Props extends PopupMenuSeparatorProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport { useItemContext } from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { PopupMenuShortcutDataAttributes } from './shortcut.data-attrs.js'\n\nexport { PopupMenuShortcutDataAttributes }\n\n/**\n * State for the Shortcut component, passed to children render function.\n */\nexport interface PopupMenuShortcutState extends Record<string, unknown> {\n /**\n * The keyboard shortcut value from the parent Item.\n */\n shortcut: string | undefined\n /**\n * Whether the parent item is highlighted.\n */\n highlighted: boolean\n}\n\nexport interface PopupMenuShortcutProps\n extends Omit<ComponentProps<'kbd', PopupMenuShortcut.State>, 'children'> {\n /**\n * Content to render inside the shortcut.\n * Can be a render function that receives the shortcut value.\n * If not provided, renders the shortcut value from the parent Item.\n */\n children?:\n | React.ReactNode\n | ((state: PopupMenuShortcutState) => React.ReactNode)\n}\n\nconst stateAttributesMapping = {\n highlighted: (value: unknown): Record<string, string> | null =>\n value ? { [PopupMenuShortcutDataAttributes.highlighted]: '' } : null,\n}\n\n/**\n * Displays the keyboard shortcut for a menu item.\n * Must be used within a PopupMenu.Item component.\n * Renders a `<kbd>` element by default.\n *\n * @example\n * ```tsx\n * // Auto-renders the shortcut value\n * <PopupMenu.Item shortcut=\"1\">\n * Icebox\n * <PopupMenu.Shortcut />\n * </PopupMenu.Item>\n *\n * // Custom rendering with children as function\n * <PopupMenu.Item shortcut=\"1\">\n * Icebox\n * <PopupMenu.Shortcut>\n * {({ shortcut }) => <span className=\"key\">{shortcut}</span>}\n * </PopupMenu.Shortcut>\n * </PopupMenu.Item>\n * ```\n */\nexport const PopupMenuShortcut = React.forwardRef<\n HTMLElement,\n PopupMenuShortcut.Props\n>(function PopupMenuShortcut(props, forwardedRef) {\n const { children, render, className, style, ...rest } = props\n\n const { shortcut, highlighted } = useItemContext()\n\n const state: PopupMenuShortcut.State = React.useMemo(\n () => ({ shortcut, highlighted }),\n [shortcut, highlighted],\n )\n\n // Render children as function, custom children, or default to shortcut value\n const renderedChildren =\n typeof children === 'function' ? children(state) : (children ?? shortcut)\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'shortcut')\n\n return useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n className,\n style,\n children: renderedChildren,\n },\n defaultTagName: 'kbd',\n })\n})\n\nexport namespace PopupMenuShortcut {\n export type State = PopupMenuShortcutState\n export interface Props extends PopupMenuShortcutProps {}\n}\n","export enum PopupMenuShortcutDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-shortcut' | 'bazzaui-context-menu-shortcut'}\n */\n slot = 'bazzaui-[component]-shortcut',\n /**\n * Present when the parent item is highlighted.\n */\n highlighted = 'data-highlighted',\n}\n","'use client'\n\nimport { Popover, type PopoverRootProps } from '@base-ui/react/popover'\nimport { useStableCallback } from '@base-ui/utils/useStableCallback'\nimport * as React from 'react'\nimport {\n ListboxContextProvider,\n ListboxStore,\n useMaybeListboxContext,\n useSurfaceContext,\n type VirtualItem,\n} from '../../../listbox/index.js'\nimport { useOpenChain } from '../../contexts/open-chain-context.js'\nimport {\n PopupMenuContext,\n useMaybePopupMenuContext,\n} from '../../contexts/popup-menu-context.js'\nimport { SubmenuContext } from '../../contexts/submenu-context.js'\n\nexport interface PopupMenuSubmenuRootProps\n extends Omit<PopoverRootProps, 'open' | 'onOpenChange' | 'defaultOpen'> {\n /**\n * Whether the submenu is open.\n * Use for controlled mode.\n */\n open?: boolean\n\n /**\n * Callback when the open state changes.\n * The second parameter contains event details including the reason for the change.\n */\n onOpenChange?: (\n open: boolean,\n eventDetails: Popover.Root.ChangeEventDetails,\n ) => void\n\n /**\n * Whether the submenu is initially open.\n * Use for uncontrolled mode.\n * @default false\n */\n defaultOpen?: boolean\n\n /**\n * Whether pressing Escape in this submenu closes the entire menu from the root.\n * When true (default), Escape closes the entire menu tree.\n * When false, Escape only closes this submenu and moves focus to the parent.\n * @default true\n */\n closeRootOnEsc?: boolean\n\n /**\n * Whether virtualization mode is enabled for this submenu.\n * When true, items should provide an explicit `index` prop and\n * the `items` prop should be provided for navigation to work correctly.\n * @default false\n */\n virtualized?: boolean\n\n /**\n * Pre-registered items for virtualization.\n * When provided with `virtualized={true}`, this allows navigation to work\n * for items that aren't currently mounted in the DOM.\n */\n items?: VirtualItem[]\n\n /**\n * Callback when the highlighted item changes.\n * Useful for synchronizing with a virtualizer (e.g., scrollToIndex).\n * Only called when `virtualized={true}`.\n */\n onHighlightChange?: (id: string | null, index: number) => void\n\n /**\n * Event handler called after any open/close animations have completed.\n * When `clearSearchOnClose=\"after-exit\"` is set on Surface, the search\n * will be cleared before this callback is invoked.\n */\n onOpenChangeComplete?: (open: boolean) => void\n\n children: React.ReactNode\n}\n\n/**\n * Groups all parts of a submenu.\n * Manages open state and provides context to children.\n * Creates its own ListboxStore independent from the parent menu.\n * Doesn't render its own HTML element.\n */\nexport function PopupMenuSubmenuRoot(props: PopupMenuSubmenuRootProps) {\n const {\n open: openProp,\n onOpenChange,\n defaultOpen = false,\n closeRootOnEsc = true,\n virtualized = false,\n items: itemsProp,\n onHighlightChange,\n onOpenChangeComplete: onOpenChangeCompleteProp,\n children,\n ...rest\n } = props\n\n const parentListboxContext = useMaybeListboxContext()\n const parentPopupMenuContext = useMaybePopupMenuContext()\n const parentDepth = parentListboxContext?.depth ?? 0\n const parentCloseAll = parentListboxContext?.closeAll\n const parentRegisterSurface = parentListboxContext?.registerSurface\n\n // Get parent surface ID for keyboard navigation back\n const { surfaceId: parentSurfaceId } = useSurfaceContext()\n\n // Generate unique surface ID for this submenu\n const childSurfaceId = React.useId()\n\n // Ref for trigger element\n const triggerRef = React.useRef<HTMLElement | null>(null)\n // Ref for submenu content element (used for aim guard rect calculations)\n const contentRef = React.useRef<HTMLElement | null>(null)\n\n // Create the store instance for this submenu\n const store = ListboxStore.useStore(undefined, { open: defaultOpen })\n\n // Sync controlled open prop to store\n store.useControlledProp('open', openProp, defaultOpen)\n\n // Get open chain store\n const openChainStore = useOpenChain()\n\n // Get open state from store for Popover\n const open = store.useState('open')\n\n // Track this submenu in the open chain\n React.useEffect(() => {\n if (open) {\n openChainStore.open(childSurfaceId)\n } else {\n openChainStore.close(childSurfaceId)\n }\n }, [open, childSurfaceId, openChainStore])\n\n // Handle Popover's onOpenChange to update the store and call user's callback\n const handlePopoverOpenChange = React.useCallback(\n (newOpen: boolean, eventDetails: Popover.Root.ChangeEventDetails) => {\n // Call user's onOpenChange first so they can cancel\n onOpenChange?.(newOpen, eventDetails)\n\n // If the user cancelled, don't update the store\n if (eventDetails.isCanceled) {\n return\n }\n\n store.setOpen(newOpen)\n },\n [store, onOpenChange],\n )\n\n // Handle animation complete - clear search and hide input if clearSearchOnClose is 'after-exit'\n const handleOpenChangeComplete = React.useCallback(\n (nextOpen: boolean) => {\n // Clear search and hide input after exit animation completes\n if (!nextOpen && store.context.clearSearchOnClose === 'after-exit') {\n store.clearSearch()\n store.setInputActive(false)\n }\n // Reset row width measurements after close animation completes\n if (!nextOpen) {\n store.context.onCloseComplete?.()\n }\n // Call user's callback\n onOpenChangeCompleteProp?.(nextOpen)\n },\n [store, onOpenChangeCompleteProp],\n )\n\n // Close submenu when parent menu closes\n // We track parent open state to close the submenu when parent closes\n const [parentOpen, setParentOpen] = React.useState(true)\n\n React.useEffect(() => {\n if (!parentListboxContext) return\n\n const parentStore = parentListboxContext.store\n // Poll the parent store's open state\n const checkParentOpen = () => {\n const isOpen = parentStore.state.open\n setParentOpen(isOpen)\n }\n\n // Check immediately\n checkParentOpen()\n\n // Subscribe to state changes by observing the store\n // We use observe method which is called when state changes\n const unsubscribe = parentStore.observe('open', checkParentOpen)\n\n return unsubscribe\n }, [parentListboxContext])\n\n React.useEffect(() => {\n if (!parentOpen) {\n store.setOpen(false)\n }\n }, [parentOpen, store])\n\n // Register this submenu with the root for closeAll tracking\n const depth = parentDepth + 1\n React.useEffect(() => {\n if (!parentRegisterSurface) return\n return parentRegisterSurface(depth, (newOpen) => store.setOpen(newOpen))\n }, [parentRegisterSurface, depth, store])\n\n // Submenu context value\n const submenuContextValue = React.useMemo(\n () => ({\n open,\n setOpen: (newOpen: boolean) => store.setOpen(newOpen),\n triggerRef,\n contentRef,\n parentSurfaceId,\n childSurfaceId,\n closeRootOnEsc,\n }),\n [open, store, parentSurfaceId, childSurfaceId, closeRootOnEsc],\n )\n\n // Fallback registerSurface for edge cases (submenu without parent root)\n const fallbackRegisterSurface = React.useCallback(() => () => {}, [])\n\n // Memoize virtualization config for this submenu\n const virtualization = React.useMemo(() => {\n if (!virtualized) return undefined\n return {\n virtualized: true as const,\n items: itemsProp ?? [],\n onHighlightChange,\n }\n }, [virtualized, itemsProp, onHighlightChange])\n\n // Listbox context value with incremented depth\n // Pass parent's closeAll and registerSurface through unchanged\n const listboxContextValue = React.useMemo(\n () => ({\n store,\n depth,\n closeAll: parentCloseAll ?? (() => store.setOpen(false)),\n registerSurface: parentRegisterSurface ?? fallbackRegisterSurface,\n virtualization,\n }),\n [\n store,\n depth,\n parentCloseAll,\n parentRegisterSurface,\n fallbackRegisterSurface,\n virtualization,\n ],\n )\n\n // PopupMenu context value with incremented depth\n // This is needed for PopupMenuPositioner to get the correct depth\n const popupMenuContextValue = React.useMemo(\n () => ({\n store,\n depth,\n closeAll: parentCloseAll ?? (() => store.setOpen(false)),\n registerSurface: parentRegisterSurface ?? fallbackRegisterSurface,\n virtualization,\n virtualAnchor: parentPopupMenuContext?.virtualAnchor,\n menuType: parentPopupMenuContext?.menuType ?? ('dropdown' as const),\n closeOnOutsidePress:\n parentPopupMenuContext?.closeOnOutsidePress ?? 'pointerdown',\n }),\n [\n store,\n depth,\n parentCloseAll,\n parentRegisterSurface,\n fallbackRegisterSurface,\n virtualization,\n parentPopupMenuContext?.virtualAnchor,\n parentPopupMenuContext?.menuType,\n parentPopupMenuContext?.closeOnOutsidePress,\n ],\n )\n\n return (\n <SubmenuContext.Provider value={submenuContextValue}>\n <PopupMenuContext.Provider value={popupMenuContextValue}>\n <ListboxContextProvider.Provider value={listboxContextValue}>\n <Popover.Root\n {...rest}\n open={open}\n onOpenChange={handlePopoverOpenChange}\n onOpenChangeComplete={handleOpenChangeComplete}\n >\n {children}\n </Popover.Root>\n </ListboxContextProvider.Provider>\n </PopupMenuContext.Provider>\n </SubmenuContext.Provider>\n )\n}\n\nexport namespace PopupMenuSubmenuRoot {\n export interface Props extends PopupMenuSubmenuRootProps {}\n export type ChangeEventDetails = Popover.Root.ChangeEventDetails\n export type Actions = Popover.Root.Actions\n}\n","'use client'\n\nimport { Popover } from '@base-ui/react/popover'\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n ItemContext,\n useListboxContext,\n useSurfaceContext,\n} from '../../../listbox/index.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { useFocusOwner } from '../../contexts/focus-owner-context.js'\nimport { useSubmenuContext } from '../../contexts/submenu-context.js'\nimport { useAimGuard } from '../../hooks/use-aim-guard.js'\nimport { usePopupMenuItem } from '../../hooks/use-popup-menu-item.js'\nimport {\n getSmoothedHeading,\n resolveAnchorSide,\n willHitSubmenu,\n} from '../../utils/aim-guard.js'\nimport { useMouseTrail } from '../../utils/use-mouse-trail.js'\nimport { PopupMenuSubmenuTriggerDataAttributes } from './submenu-trigger-indicator.js'\n\nexport interface PopupMenuSubmenuTriggerState extends Record<string, unknown> {\n /**\n * Whether this is a submenu trigger (always true).\n */\n submenuTrigger: boolean\n /**\n * Whether the submenu popup is open.\n */\n popupOpen: boolean\n /**\n * Whether the submenu owns keyboard focus.\n */\n popupFocused: boolean\n /**\n * Whether the item is highlighted.\n */\n highlighted: boolean\n /**\n * Whether the item is disabled.\n */\n disabled: boolean\n}\n\n// Custom mapping to convert state to kebab-case data attributes\nconst stateAttributesMapping = {\n submenuTrigger: (value: unknown) =>\n value\n ? { [PopupMenuSubmenuTriggerDataAttributes.submenuTrigger]: '' }\n : null,\n popupOpen: (value: unknown) =>\n value ? { [PopupMenuSubmenuTriggerDataAttributes.popupOpen]: '' } : null,\n popupFocused: (value: unknown) =>\n value ? { [PopupMenuSubmenuTriggerDataAttributes.popupFocused]: '' } : null,\n highlighted: (value: unknown) =>\n value ? { [PopupMenuSubmenuTriggerDataAttributes.highlighted]: '' } : null,\n disabled: (value: unknown) =>\n value ? { [PopupMenuSubmenuTriggerDataAttributes.disabled]: '' } : null,\n}\n\nexport interface PopupMenuSubmenuTriggerProps\n extends ComponentProps<'div', PopupMenuSubmenuTrigger.State> {\n /**\n * Explicit unique identifier for this item in the store.\n * When provided (e.g., from data-first API's computed composite ID),\n * this takes priority over `value` for store registration.\n */\n id?: string\n\n /**\n * Unique value for this item used for filtering.\n * If not provided, will be inferred from textContent.\n */\n value?: string\n\n /**\n * Additional keywords to match against when filtering.\n * Useful for aliases or synonyms.\n */\n keywords?: string[]\n\n /**\n * Whether this item is disabled.\n * Disabled items are not selectable and are skipped during keyboard navigation.\n */\n disabled?: boolean\n\n /**\n * Whether to force render this item regardless of filter results.\n * @default false\n */\n forceMount?: boolean\n\n /**\n * Whether the submenu opens when this trigger is highlighted.\n * @default true\n */\n openOnHighlight?: boolean\n\n /**\n * Delay before opening the submenu (in milliseconds).\n * Can be a number (applies to both pointer and keyboard) or an object\n * with separate `pointer` and `keyboard` values.\n * @default { pointer: 0, keyboard: 150 }\n */\n delay?: number | { pointer?: number; keyboard?: number }\n\n /**\n * Delay before closing the submenu when pointer leaves (in milliseconds).\n * @default 0\n */\n closeDelay?: number\n}\n\n/**\n * A menu item that opens a submenu when hovered.\n * Must be used within PopupMenu.Submenu.\n * Renders a `<div>` element with role=\"menuitem\" wrapped in Popover.Trigger.\n */\nexport const PopupMenuSubmenuTrigger = React.forwardRef<\n HTMLDivElement,\n PopupMenuSubmenuTrigger.Props\n>(function PopupMenuSubmenuTrigger(props, forwardedRef) {\n const {\n id: idProp,\n value,\n keywords,\n disabled = false,\n forceMount = false,\n openOnHighlight = true,\n delay: delayProp,\n closeDelay = 0,\n render,\n className,\n style,\n onPointerDown,\n onPointerMove,\n onPointerEnter,\n onPointerLeave,\n children,\n ...rest\n } = props\n\n // Normalize delay prop to { pointer, keyboard } format\n const delay = React.useMemo(() => {\n if (typeof delayProp === 'number') {\n return { pointer: delayProp, keyboard: delayProp }\n }\n return {\n pointer: delayProp?.pointer ?? 0,\n keyboard: delayProp?.keyboard ?? 150,\n }\n }, [delayProp])\n\n // Get parent menu's store (from Surface context)\n const { store: parentStore } = useSurfaceContext()\n\n // Get depth from listbox context (this is the submenu's depth, parent is depth - 1)\n const { depth } = useListboxContext()\n const parentDepth = depth - 1\n\n // Get submenu context for open state and refs\n const submenuContext = useSubmenuContext()\n const { open, setOpen, triggerRef, contentRef, childSurfaceId } =\n submenuContext\n\n // Timer for delayed opening (pointer / keyboard navigation)\n const openTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const clearOpenTimer = React.useCallback(() => {\n if (openTimerRef.current !== null) {\n clearTimeout(openTimerRef.current)\n openTimerRef.current = null\n }\n }, [])\n\n // Cleanup timer on unmount\n React.useEffect(() => clearOpenTimer, [clearOpenTimer])\n\n // Track if submenu was just closed while highlighted (e.g. ArrowLeft back)\n // to suppress the keyboard auto-open until highlight leaves and returns\n const suppressAutoOpenRef = React.useRef(false)\n\n // Get focus owner store for keyboard focus transfer\n const focusOwnerStore = useFocusOwner()\n\n // Get aim guard for safe polygon navigation\n const {\n aimGuardActiveRef,\n guardedTriggerIdRef,\n guardedDepthRef,\n activateAimGuard,\n clearAimGuard,\n } = useAimGuard()\n\n // Track mouse positions for aim guard trajectory calculation\n const mouseTrailRef = useMouseTrail(4)\n\n // Use the shared item hook for registration, visibility, and highlight state\n // When id is provided (e.g., from data-first API), it takes priority for store registration\n const item = usePopupMenuItem({\n id: idProp,\n value,\n keywords,\n disabled,\n forceMount,\n isSubmenuTrigger: true,\n closeOnClick: false, // Submenu triggers don't close the menu\n children,\n })\n\n // Register submenu open callback with parent store\n // When submenu is opened via keyboard (ArrowRight/Ctrl+L), transfer focus ownership\n React.useEffect(() => {\n return parentStore.registerSubmenuOpen(item.storeId, () => {\n setOpen(true)\n // Transfer focus ownership to the submenu surface\n focusOwnerStore.setOwnerId(childSurfaceId)\n // Auto-focus after DOM is ready\n requestAnimationFrame(() => {\n const input = contentRef.current?.querySelector('input')\n const list = contentRef.current?.querySelector('[role=\"listbox\"]')\n const focusTarget = input ?? list\n if (focusTarget && focusTarget instanceof HTMLElement) {\n focusTarget.focus()\n }\n })\n })\n }, [\n item.storeId,\n parentStore,\n setOpen,\n focusOwnerStore,\n childSurfaceId,\n contentRef,\n ])\n\n // Register submenu close callback with parent store\n // This allows the store to close this submenu when another item is highlighted\n React.useEffect(() => {\n return parentStore.registerSubmenuClose(item.storeId, () => setOpen(false))\n }, [item.storeId, parentStore, setOpen])\n\n // Check if this submenu owns keyboard focus\n const isPopupFocused = focusOwnerStore.useState('isOwner', childSurfaceId)\n\n // Close submenu when trigger becomes invisible (e.g., filtered out by search)\n // This prevents the popup from rendering without its anchor element\n React.useEffect(() => {\n if (!item.isVisible && open) {\n setOpen(false)\n }\n }, [item.isVisible, open, setOpen])\n\n // When submenu closes while this trigger is highlighted, suppress auto-open\n const prevOpenRef = React.useRef(open)\n React.useEffect(() => {\n if (prevOpenRef.current && !open && item.isHighlighted) {\n suppressAutoOpenRef.current = true\n }\n prevOpenRef.current = open\n }, [open, item.isHighlighted])\n\n // Reset suppression when highlight leaves this trigger\n React.useEffect(() => {\n if (!item.isHighlighted) {\n suppressAutoOpenRef.current = false\n }\n }, [item.isHighlighted])\n\n // When highlighted via keyboard, schedule open after keyboard delay\n // This effect only handles *navigation* highlight (ArrowUp/Down).\n // Explicit open actions (ArrowRight, Ctrl+L) bypass this by calling registerSubmenuOpen directly.\n React.useEffect(() => {\n // Skip if openOnHighlight is disabled\n if (!openOnHighlight) {\n return\n }\n\n // Only schedule open when highlighted via explicit keyboard navigation\n // Don't auto-open for 'auto' highlights (search results, initial open)\n if (\n !item.isHighlighted ||\n parentStore.state.highlightSource !== 'keyboard'\n ) {\n clearOpenTimer()\n return\n }\n\n // Don't auto-open if user just explicitly closed the submenu (e.g. ArrowLeft)\n if (suppressAutoOpenRef.current) {\n return\n }\n\n const keyboardDelay = delay.keyboard\n if (keyboardDelay <= 0) {\n setOpen(true)\n } else {\n openTimerRef.current = setTimeout(() => {\n openTimerRef.current = null\n setOpen(true)\n }, keyboardDelay)\n }\n\n return clearOpenTimer\n }, [\n item.isHighlighted,\n parentStore,\n delay.keyboard,\n setOpen,\n clearOpenTimer,\n openOnHighlight,\n ])\n\n // Set the trigger ref when element mounts\n React.useEffect(() => {\n ;(triggerRef as React.MutableRefObject<HTMLElement | null>).current =\n item.ref.current\n return () => {\n ;(triggerRef as React.MutableRefObject<HTMLElement | null>).current = null\n }\n }, [triggerRef, item.ref])\n\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n // Prevent focus from leaving the input\n event.preventDefault()\n onPointerDown?.(event)\n },\n [onPointerDown],\n )\n\n // Custom pointer move handler for submenu triggers\n // Different from usePopupMenuItem's handler: allows the guarded trigger to highlight itself\n const handlePointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event)\n\n if (event.defaultPrevented) return\n if (disabled) return\n\n // Check if pointer has actually moved (prevents phantom highlights)\n if (\n !parentStore.shouldAllowPointerHighlight(event.clientX, event.clientY)\n ) {\n return\n }\n\n // Don't highlight if aim guard is active at this depth for a different trigger\n if (\n aimGuardActiveRef.current &&\n guardedDepthRef.current === parentDepth &&\n guardedTriggerIdRef.current !== item.id\n ) {\n return\n }\n\n // Highlight on hover (use storeId for store operations)\n parentStore.setHighlightedId(item.storeId)\n },\n [\n onPointerMove,\n disabled,\n aimGuardActiveRef,\n guardedDepthRef,\n parentDepth,\n guardedTriggerIdRef,\n item.id,\n item.storeId,\n parentStore,\n ],\n )\n\n const handlePointerEnter = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerEnter?.(event)\n\n if (event.defaultPrevented) return\n if (disabled) return\n\n // Check if aim guard is blocking this trigger\n if (\n aimGuardActiveRef.current &&\n guardedTriggerIdRef.current !== item.id\n ) {\n return\n }\n\n // Highlight the trigger on pointer enter (use storeId for store operations)\n parentStore.setHighlightedId(item.storeId)\n\n // Skip submenu opening if openOnHighlight is disabled\n if (!openOnHighlight) return\n\n // Clear any existing aim guard and schedule open with delay\n clearAimGuard()\n clearOpenTimer()\n\n const pointerDelay = delay.pointer\n if (pointerDelay <= 0) {\n setOpen(true)\n } else {\n openTimerRef.current = setTimeout(() => {\n openTimerRef.current = null\n setOpen(true)\n }, pointerDelay)\n }\n },\n [\n onPointerEnter,\n disabled,\n aimGuardActiveRef,\n guardedTriggerIdRef,\n item.id,\n item.storeId,\n parentStore,\n openOnHighlight,\n clearAimGuard,\n clearOpenTimer,\n delay.pointer,\n setOpen,\n ],\n )\n\n const handlePointerLeave = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerLeave?.(event)\n\n if (event.defaultPrevented) return\n if (disabled) return\n\n // Cancel any pending open timer\n clearOpenTimer()\n\n // Check if aim guard is blocking this trigger\n if (aimGuardActiveRef.current && guardedTriggerIdRef.current !== item.id)\n return\n\n // Get the submenu content rect for safe polygon calculation\n const contentRect = contentRef.current?.getBoundingClientRect()\n if (!contentRect) {\n clearAimGuard()\n setOpen(false)\n return\n }\n\n // Check if pointer is already inside the popup (can happen with fast movement or overlapping elements)\n const { clientX, clientY } = event\n const isInsidePopup =\n clientX >= contentRect.left &&\n clientX <= contentRect.right &&\n clientY >= contentRect.top &&\n clientY <= contentRect.bottom\n\n if (isInsidePopup) {\n // Pointer is already in the popup, clear guard and keep open\n clearAimGuard()\n return\n }\n\n // Get trigger rect for aim guard calculation\n const tRect = triggerRef.current?.getBoundingClientRect() ?? null\n\n // Calculate safe polygon and check if user is aiming toward submenu\n const anchor = resolveAnchorSide(contentRect, tRect, clientX)\n const heading = getSmoothedHeading(\n mouseTrailRef.current,\n clientX,\n clientY,\n anchor,\n tRect,\n contentRect,\n )\n const hit = willHitSubmenu(\n clientX,\n clientY,\n heading,\n contentRect,\n anchor,\n tRect,\n )\n\n // DEBUG: Uncomment to debug aim guard issues\n // console.log('[AimGuard]', { clientX, clientY, contentRect, anchor, heading, hit, trail: [...mouseTrailRef.current] })\n\n if (hit) {\n // User is aiming at submenu - activate aim guard for 600ms\n // Guard is activated at parentDepth to block highlighting in the parent menu only\n activateAimGuard(item.id, parentDepth, childSurfaceId, 600)\n parentStore.setHighlightedId(item.storeId)\n setOpen(true)\n } else {\n // User is not aiming at submenu - close it\n clearAimGuard()\n setOpen(false)\n }\n },\n [\n onPointerLeave,\n disabled,\n clearOpenTimer,\n aimGuardActiveRef,\n guardedTriggerIdRef,\n item.id,\n item.storeId,\n contentRef,\n clearAimGuard,\n setOpen,\n triggerRef,\n mouseTrailRef,\n activateAimGuard,\n parentDepth,\n childSurfaceId,\n parentStore,\n ],\n )\n\n const state: PopupMenuSubmenuTrigger.State = React.useMemo(\n () => ({\n submenuTrigger: true,\n popupOpen: open,\n popupFocused: isPopupFocused,\n highlighted: item.isHighlighted,\n disabled,\n }),\n [open, isPopupFocused, item.isHighlighted, disabled],\n )\n\n // Wrap children with ItemContext.Provider so child components can access item state\n const wrappedChildren = (\n <ItemContext.Provider value={item.contextValue}>\n {children}\n </ItemContext.Provider>\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'submenu-trigger')\n\n // Use useRender to create the element with state-based data attributes\n const element = useRender({\n render,\n ref: [item.ref, forwardedRef],\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n id: item.id,\n role: 'menuitem',\n 'aria-haspopup': 'menu',\n 'aria-expanded': open,\n tabIndex: -1,\n 'aria-disabled': disabled || undefined,\n className,\n style,\n onPointerMove: handlePointerMove,\n onPointerDown: handlePointerDown,\n onPointerEnter: handlePointerEnter,\n onPointerLeave: handlePointerLeave,\n children: wrappedChildren,\n },\n defaultTagName: 'div',\n })\n\n // Don't render if not visible\n if (!item.isVisible) return null\n\n return <Popover.Trigger nativeButton={false} render={element} />\n})\n\nexport namespace PopupMenuSubmenuTrigger {\n export type State = PopupMenuSubmenuTriggerState\n export interface Props extends PopupMenuSubmenuTriggerProps {}\n}\n","'use client'\n\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ComponentProps } from '../../../../utils/types.js'\nimport {\n getSlotAttribute,\n useMaybeComponentName,\n} from '../../contexts/component-name-context.js'\nimport { useFocusOwner } from '../../contexts/focus-owner-context.js'\nimport { useSubmenuContext } from '../../contexts/submenu-context.js'\nimport { PopupMenuSubmenuTriggerDataAttributes } from './submenu-trigger.data-attrs.js'\n\nexport { PopupMenuSubmenuTriggerDataAttributes }\n\nexport interface PopupMenuSubmenuTriggerIndicatorState\n extends Record<string, unknown> {\n /**\n * Whether the submenu popup is open.\n */\n popupOpen: boolean\n /**\n * Whether the submenu owns keyboard focus.\n */\n popupFocused: boolean\n}\n\n// Custom mapping to convert state to kebab-case data attributes\nconst stateAttributesMapping = {\n popupOpen: (value: unknown) =>\n value ? { [PopupMenuSubmenuTriggerDataAttributes.popupOpen]: '' } : null,\n popupFocused: (value: unknown) =>\n value ? { [PopupMenuSubmenuTriggerDataAttributes.popupFocused]: '' } : null,\n}\n\nexport interface PopupMenuSubmenuTriggerIndicatorProps\n extends ComponentProps<'span', PopupMenuSubmenuTriggerIndicator.State> {}\n\n/**\n * An indicator element for submenu triggers that reflects the submenu's open and focus state.\n * Typically used to render a chevron or arrow icon.\n * Must be used within PopupMenu.SubmenuTrigger.\n * Renders a `<span>` element.\n */\nexport const PopupMenuSubmenuTriggerIndicator = React.forwardRef<\n HTMLSpanElement,\n PopupMenuSubmenuTriggerIndicator.Props\n>(function PopupMenuSubmenuTriggerIndicator(props, forwardedRef) {\n const { render, className, style, children, ...rest } = props\n\n // Get submenu context for open state\n const { open, childSurfaceId } = useSubmenuContext()\n\n // Get focus owner store to check if this submenu owns focus\n const focusOwnerStore = useFocusOwner()\n const isPopupFocused = focusOwnerStore.useState('isOwner', childSurfaceId)\n\n const state: PopupMenuSubmenuTriggerIndicator.State = React.useMemo(\n () => ({\n popupOpen: open,\n popupFocused: isPopupFocused,\n }),\n [open, isPopupFocused],\n )\n\n // Get component name for slot attribute\n const componentName = useMaybeComponentName()\n const slotAttr = getSlotAttribute(componentName, 'submenu-trigger-indicator')\n\n return useRender({\n render,\n ref: forwardedRef,\n state,\n stateAttributesMapping,\n props: {\n ...rest,\n ...(slotAttr ? { [slotAttr]: '' } : {}),\n 'aria-hidden': true,\n className,\n style,\n children,\n },\n defaultTagName: 'span',\n })\n})\n\nexport namespace PopupMenuSubmenuTriggerIndicator {\n export type State = PopupMenuSubmenuTriggerIndicatorState\n export interface Props extends PopupMenuSubmenuTriggerIndicatorProps {}\n}\n","export enum PopupMenuSubmenuTriggerDataAttributes {\n /**\n * Identifies the component part.\n * @type {'bazzaui-dropdown-menu-submenu-trigger' | 'bazzaui-context-menu-submenu-trigger'}\n */\n slot = 'bazzaui-[component]-submenu-trigger',\n /**\n * Present on submenu trigger elements.\n */\n submenuTrigger = 'data-submenu-trigger',\n /**\n * Present when the submenu popup is open.\n */\n popupOpen = 'data-popup-open',\n /**\n * Present when the submenu owns keyboard focus.\n */\n popupFocused = 'data-popup-focused',\n /**\n * Present when the item is highlighted.\n */\n highlighted = 'data-highlighted',\n /**\n * Present when the item is disabled.\n */\n disabled = 'data-disabled',\n}\n","'use client'\n\nimport * as React from 'react'\nimport type {\n AsyncLoaderConfig,\n AsyncLoaderResult,\n AsyncState,\n NodeDef,\n} from './types.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * State for a registered async loader.\n */\nexport interface AsyncMenuState {\n /** Unique identifier for this async menu */\n id: string\n /** Breadcrumbs path to this menu (for merging into tree) */\n breadcrumbs: string[]\n /** The loader configuration */\n config: AsyncLoaderConfig\n /** Current loader result */\n result: AsyncLoaderResult<NodeDef[]>\n}\n\n/**\n * Context value for the async menu coordinator.\n */\nexport interface AsyncMenuCoordinatorValue {\n // ---- Registration ----\n /** Register a new async loader */\n registerLoader: (state: AsyncMenuState) => void\n /** Unregister an async loader */\n unregisterLoader: (id: string) => void\n /** Update loader result */\n updateLoaderResult: (id: string, result: AsyncLoaderResult<NodeDef[]>) => void\n\n // ---- Search Query ----\n /** Current search query from the store */\n searchQuery: string\n\n // ---- Loader State ----\n /** All registered loaders */\n loaders: Map<string, AsyncMenuState>\n\n // ---- Computed State ----\n /** Any loader is currently loading */\n isAnyLoading: boolean\n /** Static loaders are loading */\n isStaticLoading: boolean\n /** Query loaders are loading */\n isQueryLoading: boolean\n /** All loaders have resolved (not loading, no pending) */\n allResolved: boolean\n\n // ---- Async Nodes ----\n /** Get all resolved async nodes with their breadcrumbs */\n getAsyncNodes: () => Array<{\n id: string\n breadcrumbs: string[]\n nodes: NodeDef[]\n }>\n\n // ---- Error Tracking ----\n /** Loaders that errored */\n erroredLoaders: Map<string, Error>\n\n // ---- Aggregated State ----\n /** Get the aggregate async state for DataList */\n getAsyncState: () => AsyncState\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nexport const AsyncMenuCoordinatorContext =\n React.createContext<AsyncMenuCoordinatorValue | null>(null)\n\nexport function useAsyncMenuCoordinator(): AsyncMenuCoordinatorValue | null {\n return React.useContext(AsyncMenuCoordinatorContext)\n}\n\nexport function useMaybeAsyncMenuCoordinator(): AsyncMenuCoordinatorValue | null {\n return React.useContext(AsyncMenuCoordinatorContext)\n}\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\nexport interface AsyncMenuCoordinatorProviderProps {\n /** Children to render */\n children: React.ReactNode\n /** Current search query from the store */\n searchQuery: string\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\nexport function AsyncMenuCoordinatorProvider(\n props: AsyncMenuCoordinatorProviderProps,\n) {\n const { children, searchQuery } = props\n\n // Registered loaders\n const [loaders, setLoaders] = React.useState<Map<string, AsyncMenuState>>(\n () => new Map(),\n )\n\n // Track errored loaders\n const [erroredLoaders, setErroredLoaders] = React.useState<\n Map<string, Error>\n >(() => new Map())\n\n // Register a loader\n const registerLoader = React.useCallback((state: AsyncMenuState) => {\n setLoaders((prev) => {\n const next = new Map(prev)\n next.set(state.id, state)\n return next\n })\n }, [])\n\n // Unregister a loader\n const unregisterLoader = React.useCallback((id: string) => {\n setLoaders((prev) => {\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n\n // Clear error state\n setErroredLoaders((prev) => {\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, [])\n\n // Update loader result\n const updateLoaderResult = React.useCallback(\n (id: string, result: AsyncLoaderResult<NodeDef[]>) => {\n setLoaders((prev) => {\n const existing = prev.get(id)\n if (!existing) return prev\n\n const next = new Map(prev)\n next.set(id, { ...existing, result })\n return next\n })\n\n // Track errors\n if (result.isError && result.error) {\n setErroredLoaders((prev) => {\n const next = new Map(prev)\n next.set(id, result.error!)\n return next\n })\n } else if (!result.isError) {\n setErroredLoaders((prev) => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }\n },\n [],\n )\n\n // Computed loading states\n const isStaticLoading = React.useMemo(() => {\n for (const [, state] of loaders) {\n if (state.config.type === 'static' && state.result.isLoading) {\n return true\n }\n }\n return false\n }, [loaders])\n\n const isQueryLoading = React.useMemo(() => {\n for (const [, state] of loaders) {\n if (state.config.type === 'query' && state.result.isLoading) {\n return true\n }\n }\n return false\n }, [loaders])\n\n const isAnyLoading = isStaticLoading || isQueryLoading\n\n const allResolved = React.useMemo(() => {\n for (const [, state] of loaders) {\n if (state.result.isLoading) {\n return false\n }\n }\n return true\n }, [loaders])\n\n // Get all resolved async nodes\n const getAsyncNodes = React.useCallback(() => {\n const result: Array<{\n id: string\n breadcrumbs: string[]\n nodes: NodeDef[]\n }> = []\n\n for (const [id, state] of loaders) {\n // Skip errored loaders\n if (erroredLoaders.has(id)) {\n continue\n }\n\n // Add resolved data\n if (state.result.data) {\n result.push({\n id,\n breadcrumbs: state.breadcrumbs,\n nodes: state.result.data,\n })\n }\n }\n\n return result\n }, [loaders, erroredLoaders])\n\n // Get aggregate async state\n const getAsyncState = React.useCallback((): AsyncState => {\n const skippedMenus: Array<{ id: string; reason: 'error' }> = []\n\n for (const [id] of erroredLoaders) {\n skippedMenus.push({ id, reason: 'error' })\n }\n\n return {\n isLoading: isAnyLoading,\n isStaticLoading,\n isQueryLoading,\n skippedMenus,\n }\n }, [isAnyLoading, isStaticLoading, isQueryLoading, erroredLoaders])\n\n // Context value\n const contextValue: AsyncMenuCoordinatorValue = React.useMemo(\n () => ({\n registerLoader,\n unregisterLoader,\n updateLoaderResult,\n searchQuery,\n loaders,\n isAnyLoading,\n isStaticLoading,\n isQueryLoading,\n allResolved,\n getAsyncNodes,\n erroredLoaders,\n getAsyncState,\n }),\n [\n registerLoader,\n unregisterLoader,\n updateLoaderResult,\n searchQuery,\n loaders,\n isAnyLoading,\n isStaticLoading,\n isQueryLoading,\n allResolved,\n getAsyncNodes,\n erroredLoaders,\n getAsyncState,\n ],\n )\n\n return (\n <AsyncMenuCoordinatorContext.Provider value={contextValue}>\n {children}\n </AsyncMenuCoordinatorContext.Provider>\n )\n}\n","'use client'\n\nimport * as React from 'react'\nimport type {\n AsyncLoaderConfig,\n DeepSearchConfig,\n DisplayNode,\n GetQualifiedRowIdFn,\n NodeDef,\n} from './types.js'\n\n// ============================================================================\n// Data Surface Context\n// ============================================================================\n\nexport interface DataSurfaceContextValue {\n /** The original node definitions */\n content: NodeDef[]\n\n /** Async content configuration for root-level async loading */\n asyncContent?: AsyncLoaderConfig\n\n /** Deep search configuration */\n deepSearchConfig: DeepSearchConfig\n\n /** List element ID for aria-activedescendant */\n listId: string\n\n /** Function to generate qualified IDs for row items */\n getQualifiedRowId: GetQualifiedRowIdFn\n}\n\nexport const DataSurfaceContext =\n React.createContext<DataSurfaceContextValue | null>(null)\n\nexport function useDataSurfaceContext(): DataSurfaceContextValue {\n const context = React.useContext(DataSurfaceContext)\n if (!context) {\n throw new Error(\n 'useDataSurfaceContext must be used within a DataSurface component',\n )\n }\n return context\n}\n\nexport function useMaybeDataSurfaceContext(): DataSurfaceContextValue | null {\n return React.useContext(DataSurfaceContext)\n}\n\n// ============================================================================\n// Render Node Function Type\n// ============================================================================\n\nexport type RenderNodeFn = (displayNode: DisplayNode) => React.ReactNode\n","'use client'\n\nimport * as React from 'react'\nimport { useSurfaceContext } from '../../listbox/index.js'\nimport { PopupMenuList } from '../components/list/list.js'\nimport {\n AsyncMenuCoordinatorProvider,\n type AsyncMenuState,\n useAsyncMenuCoordinator,\n} from './async-coordinator.js'\nimport { type RenderNodeFn, useDataSurfaceContext } from './context.js'\nimport type {\n AsyncLoaderResult,\n AsyncNodesConfig,\n BreadcrumbNode,\n CheckboxItemDef,\n DataListChildrenState,\n DataListProps,\n DisplayNode,\n DisplayRowNode,\n GetQualifiedRowIdFn,\n GroupRenderContext,\n ItemDef,\n NodeDef,\n RadioGroupDef,\n RowRenderContext,\n SubmenuDef,\n} from './types.js'\nimport {\n isDisplayGroupNode,\n isDisplayRadioGroupNode,\n isDisplaySeparatorNode,\n} from './types.js'\nimport {\n type AsyncSubmenuInfo,\n collectAsyncSubmenus,\n filterNodes,\n mergeAsyncNodesIntoTree,\n shouldIncludeInDeepSearch,\n shouldLoadEagerly,\n} from './utils.js'\n\n// ============================================================================\n// Helper: Compute composite IDs for all row nodes\n// ============================================================================\n\n/**\n * Computes and sets composite IDs directly on all row nodes in the display list.\n * Mutates the displayNodes in place for performance.\n * The index is the flat position across all items (including those inside groups).\n */\nfunction computeItemIds(\n displayNodes: DisplayNode[],\n getQualifiedRowId: GetQualifiedRowIdFn,\n isDeepSearching: boolean,\n): void {\n let index = 0\n\n for (const displayNode of displayNodes) {\n if (isDisplayGroupNode(displayNode)) {\n for (const item of displayNode.items) {\n item.compositeId = getQualifiedRowId({\n node: item.node,\n value: item.node.value,\n id: item.node.id,\n index,\n breadcrumbs: item.context.breadcrumbs,\n isDeepSearching,\n search: item.context.search,\n isDeepSearchResult: item.context.isDeepSearchResult,\n group: item.context.group,\n radioGroup: null,\n })\n index++\n }\n } else if (isDisplayRadioGroupNode(displayNode)) {\n for (const item of displayNode.items) {\n item.compositeId = getQualifiedRowId({\n node: item.node,\n value: item.node.value,\n id: item.node.id,\n index,\n breadcrumbs: item.context.breadcrumbs,\n isDeepSearching,\n search: item.context.search,\n isDeepSearchResult: item.context.isDeepSearchResult,\n group: null,\n radioGroup: item.radioGroup ?? null,\n })\n index++\n }\n } else if (isDisplaySeparatorNode(displayNode)) {\n // Separators don't need IDs\n } else {\n // Row node\n displayNode.compositeId = getQualifiedRowId({\n node: displayNode.node,\n value: displayNode.node.value,\n id: displayNode.node.id,\n index,\n breadcrumbs: displayNode.context.breadcrumbs,\n isDeepSearching,\n search: displayNode.context.search,\n isDeepSearchResult: displayNode.context.isDeepSearchResult,\n group: displayNode.context.group,\n radioGroup: displayNode.radioGroup ?? null,\n })\n index++\n }\n }\n}\n\n/**\n * Extracts ordered composite IDs from display nodes for store navigation.\n * Assumes `computeItemIds` has already been called to set `compositeId` on each node.\n */\nfunction getOrderedItemIds(displayNodes: DisplayNode[]): string[] {\n const ids: string[] = []\n\n for (const displayNode of displayNodes) {\n if (isDisplayGroupNode(displayNode)) {\n for (const item of displayNode.items) {\n if (!item.node.disabled && item.compositeId) {\n ids.push(item.compositeId)\n }\n }\n } else if (isDisplayRadioGroupNode(displayNode)) {\n for (const item of displayNode.items) {\n if (!item.node.disabled && item.compositeId) {\n ids.push(item.compositeId)\n }\n }\n } else if (isDisplaySeparatorNode(displayNode)) {\n // skip\n } else {\n if (!displayNode.node.disabled && displayNode.compositeId) {\n ids.push(displayNode.compositeId)\n }\n }\n }\n\n return ids\n}\n\n// ============================================================================\n// Async Loader Component\n// ============================================================================\n\ninterface AsyncLoaderRendererProps {\n info: AsyncSubmenuInfo\n query: string\n enabled: boolean\n}\n\n/**\n * Renders an async loader component and registers its state with the coordinator.\n * This component exists solely to call the Loader component (which contains hooks).\n */\nfunction AsyncLoaderRenderer({\n info,\n query,\n enabled,\n}: AsyncLoaderRendererProps) {\n const coordinator = useAsyncMenuCoordinator()\n const { config, id, breadcrumbs, node } = info\n const Loader = config.Loader\n\n // For query-dependent loaders, determine effective query\n const effectiveQuery = React.useMemo(() => {\n if (config.type === 'query') {\n const minLength = config.minQueryLength ?? 1\n if (query.length < minLength) {\n return ''\n }\n }\n return query\n }, [config, query])\n\n // Track if this loader should be active\n const isActive = enabled || shouldLoadEagerly(config)\n\n if (!isActive) {\n return null\n }\n\n return (\n <Loader query={effectiveQuery}>\n {(result) => (\n <AsyncLoaderResultHandler\n id={id}\n breadcrumbs={breadcrumbs}\n config={config}\n result={result}\n coordinator={coordinator}\n />\n )}\n </Loader>\n )\n}\n\ninterface AsyncLoaderResultHandlerProps {\n id: string\n breadcrumbs: string[]\n config: AsyncNodesConfig\n result: AsyncLoaderResult<NodeDef[]>\n coordinator: ReturnType<typeof useAsyncMenuCoordinator>\n}\n\n/**\n * Handles registering and updating loader results with the coordinator.\n * This is a separate component to avoid re-rendering the Loader on every result change.\n */\nfunction AsyncLoaderResultHandler({\n id,\n breadcrumbs,\n config,\n result,\n coordinator,\n}: AsyncLoaderResultHandlerProps) {\n // Use refs to hold the latest values without causing re-renders\n // This is critical because coordinator changes on every state update (new Map)\n const breadcrumbsRef = React.useRef(breadcrumbs)\n const configRef = React.useRef(config)\n const coordinatorRef = React.useRef(coordinator)\n const resultRef = React.useRef(result)\n\n // Track previous result values to avoid unnecessary updates\n // TanStack Query returns new object references on every render\n const prevResultRef = React.useRef<{\n data: unknown\n isLoading: boolean\n isError: boolean\n error: Error | null\n } | null>(null)\n\n // Keep refs up to date\n breadcrumbsRef.current = breadcrumbs\n configRef.current = config\n coordinatorRef.current = coordinator\n resultRef.current = result\n\n // Register on mount, unregister on unmount\n // IMPORTANT: Only depend on `id` - coordinator is accessed via ref to avoid\n // infinite loops (coordinator object changes on every state update)\n React.useEffect(() => {\n const coord = coordinatorRef.current\n if (!coord) return\n\n const state: AsyncMenuState = {\n id,\n breadcrumbs: breadcrumbsRef.current,\n config: configRef.current,\n result: resultRef.current,\n }\n\n coord.registerLoader(state)\n\n return () => {\n coord.unregisterLoader(id)\n }\n }, [id]) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Update result when meaningful values change\n // IMPORTANT: Depend on individual result values, not the result object reference.\n // TanStack Query creates new object references on every render, but we only want\n // to trigger updates when actual values change.\n // Using coordinatorRef prevents re-running when coordinator context changes.\n React.useEffect(() => {\n const coord = coordinatorRef.current\n if (!coord) return\n\n // Compare against previous values to avoid unnecessary updates\n const prev = prevResultRef.current\n const hasChanged =\n prev === null ||\n prev.data !== result.data ||\n prev.isLoading !== result.isLoading ||\n prev.isError !== result.isError ||\n prev.error !== result.error\n\n if (hasChanged) {\n prevResultRef.current = {\n data: result.data,\n isLoading: result.isLoading,\n isError: result.isError,\n error: result.error,\n }\n coord.updateLoaderResult(id, result)\n }\n }, [id, result.data, result.isLoading, result.isError, result.error]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return null\n}\n\n// ============================================================================\n// Root Async Loader Component\n// ============================================================================\n\ninterface RootAsyncLoaderProps {\n query: string\n}\n\n/**\n * Renders the root async content loader if configured.\n */\nfunction RootAsyncLoader({ query }: RootAsyncLoaderProps) {\n const dataSurfaceCtx = useDataSurfaceContext()\n const coordinator = useAsyncMenuCoordinator()\n const { asyncContent } = dataSurfaceCtx\n\n // For query-dependent loaders, determine effective query\n const effectiveQuery = React.useMemo(() => {\n if (!asyncContent) return ''\n if (asyncContent.type === 'query') {\n const minLength = asyncContent.minQueryLength ?? 1\n if (query.length < minLength) {\n return ''\n }\n }\n return query\n }, [asyncContent, query])\n\n if (!asyncContent) {\n return null\n }\n\n const Loader = asyncContent.Loader\n\n return (\n <Loader query={effectiveQuery}>\n {(result) => (\n <AsyncLoaderResultHandler\n id=\"__root__\"\n breadcrumbs={[]}\n config={asyncContent as AsyncNodesConfig}\n result={result}\n coordinator={coordinator}\n />\n )}\n </Loader>\n )\n}\n\n// ============================================================================\n// DataList Component\n// ============================================================================\n\nexport interface PopupMenuDataListProps extends DataListProps {\n /** Render function for custom element */\n render?: React.ReactElement\n}\n\n/**\n * DataList renders the menu items using a render prop pattern.\n * It reads from the store for search and computes filtered nodes.\n *\n * Place inside PopupMenuDataSurface.\n * Wraps PopupMenuList for keyboard navigation and accessibility.\n */\nexport const PopupMenuDataList = React.forwardRef<\n HTMLDivElement,\n PopupMenuDataList.Props\n>(function PopupMenuDataList(props, forwardedRef) {\n const {\n children,\n label = 'Menu',\n className,\n style,\n render,\n measureRowWidth,\n maxRowWidth,\n } = props\n\n // Get data surface context for content and deep search config\n const dataSurfaceCtx = useDataSurfaceContext()\n const { content, asyncContent, deepSearchConfig, getQualifiedRowId } =\n dataSurfaceCtx\n\n // Get store from surface context for search state\n const { store } = useSurfaceContext()\n const search = store.useState('search')\n\n // Wrap with coordinator provider\n return (\n <AsyncMenuCoordinatorProvider searchQuery={search}>\n <DataListInner\n ref={forwardedRef}\n {...props}\n content={content}\n asyncContent={asyncContent}\n deepSearchConfig={deepSearchConfig}\n getQualifiedRowId={getQualifiedRowId}\n search={search}\n store={store}\n />\n </AsyncMenuCoordinatorProvider>\n )\n})\n\n// ============================================================================\n// DataList Inner Component (with coordinator access)\n// ============================================================================\n\ninterface DataListInnerProps extends PopupMenuDataListProps {\n content: NodeDef[]\n asyncContent: ReturnType<typeof useDataSurfaceContext>['asyncContent']\n deepSearchConfig: ReturnType<typeof useDataSurfaceContext>['deepSearchConfig']\n getQualifiedRowId: GetQualifiedRowIdFn\n search: string\n store: ReturnType<typeof useSurfaceContext>['store']\n}\n\nconst DataListInner = React.forwardRef<HTMLDivElement, DataListInnerProps>(\n function DataListInner(props, forwardedRef) {\n const {\n children,\n label = 'Menu',\n className,\n style,\n render,\n measureRowWidth,\n maxRowWidth,\n content,\n asyncContent,\n deepSearchConfig,\n getQualifiedRowId,\n search,\n store,\n } = props\n\n // Get coordinator for async state\n const coordinator = useAsyncMenuCoordinator()\n\n // Collect async submenus from content\n const asyncSubmenus = React.useMemo(\n () => collectAsyncSubmenus(content),\n [content],\n )\n\n // Determine if deep search is active\n const minLength = deepSearchConfig.minLength ?? 0\n const isDeepSearchActive =\n deepSearchConfig.enabled !== false && search.length >= minLength\n\n // Determine which async loaders should be rendered\n const shouldRenderAsyncLoaders =\n isDeepSearchActive ||\n asyncSubmenus.some((s) => shouldLoadEagerly(s.config)) ||\n (asyncContent && asyncContent.loadStrategy === 'eager')\n\n // Get async nodes from coordinator\n const asyncNodes = React.useMemo(() => {\n if (!coordinator) return []\n return coordinator.getAsyncNodes()\n }, [coordinator, coordinator?.loaders])\n\n // Merge async nodes into content tree\n const mergedContent = React.useMemo(() => {\n if (asyncNodes.length === 0) return content\n return mergeAsyncNodesIntoTree(content, asyncNodes)\n }, [content, asyncNodes])\n\n // Handle root async content if available\n const contentWithRootAsync = React.useMemo(() => {\n const rootAsyncData = asyncNodes.find((n) => n.id === '__root__')\n if (!rootAsyncData) return mergedContent\n\n // When asyncContent is provided, it's the sole data source - use only its results\n if (asyncContent) {\n return rootAsyncData.nodes\n }\n\n // For root-level DataSurface without asyncContent, append to static content\n return [...mergedContent, ...rootAsyncData.nodes]\n }, [mergedContent, asyncNodes, asyncContent])\n\n // Compute filtered display nodes and set composite IDs\n const { displayNodes, isDeepSearching } = React.useMemo(() => {\n const result = filterNodes({\n query: search,\n nodes: contentWithRootAsync,\n highlightedId: null, // Primitives handle highlighting via store\n deepSearch: deepSearchConfig.enabled,\n minLength: deepSearchConfig.minLength,\n groupSearchBehavior: deepSearchConfig.groupSearchBehavior,\n radioGroupSearchBehavior: deepSearchConfig.radioGroupSearchBehavior,\n sortGroups: deepSearchConfig.sortGroups,\n })\n // Set composite IDs directly on the freshly created display nodes\n computeItemIds(\n result.displayNodes,\n getQualifiedRowId,\n result.isDeepSearching,\n )\n return result\n }, [search, contentWithRootAsync, deepSearchConfig, getQualifiedRowId])\n\n // Sync orderedItems with the store when display nodes change\n // This is needed because DataSurface sets filter={false} on the underlying Surface\n //\n // We use a ref to track the previous IDs and do a deep comparison to avoid\n // triggering highlight resets when the content hasn't actually changed.\n const prevOrderedItemIdsRef = React.useRef<string[]>([])\n\n // Compute new ordered IDs using composite IDs\n const newOrderedItemIds = React.useMemo(\n () => getOrderedItemIds(displayNodes),\n [displayNodes],\n )\n\n // Memoize the ordered IDs, only returning a new array if content changed\n const orderedItemIds = React.useMemo(() => {\n const prev = prevOrderedItemIdsRef.current\n const current = newOrderedItemIds\n\n // Deep comparison\n const changed =\n prev.length !== current.length ||\n prev.some((id, i) => id !== current[i])\n\n if (changed) {\n prevOrderedItemIdsRef.current = current\n return current\n }\n\n return prev\n }, [newOrderedItemIds])\n\n React.useEffect(() => {\n store.setOrderedItems(orderedItemIds)\n }, [store, orderedItemIds])\n\n // Helper to render a single row node (item, checkbox item, or submenu)\n const renderRowNode = React.useCallback(\n (displayNode: DisplayRowNode): React.ReactNode => {\n const { node, context } = displayNode\n\n // Use composite ID from display node, fallback to node.id/value for submenu children\n const compositeId = displayNode.compositeId ?? node.id ?? node.value\n\n if (node.kind === 'item') {\n return (\n <React.Fragment key={compositeId}>\n {node.render({\n props: {\n id: compositeId,\n value: node.value,\n disabled: node.disabled ?? false,\n closeOnClick: node.closeOnClick,\n onSelect: node.onSelect,\n shortcut: node.shortcut,\n },\n context: {\n ...context,\n value: node.value,\n disabled: node.disabled ?? false,\n },\n })}\n </React.Fragment>\n )\n }\n\n if (node.kind === 'radio-item') {\n return (\n <React.Fragment key={compositeId}>\n {node.render({\n props: {\n id: compositeId,\n value: node.value,\n disabled: node.disabled ?? false,\n closeOnClick: node.closeOnClick,\n onSelect: node.onSelect,\n shortcut: node.shortcut,\n },\n context: {\n ...context,\n value: node.value,\n disabled: node.disabled ?? false,\n },\n })}\n </React.Fragment>\n )\n }\n\n if (node.kind === 'checkbox-item') {\n return (\n <React.Fragment key={compositeId}>\n {node.render({\n props: {\n id: compositeId,\n value: node.value,\n checked: node.checked,\n onCheckedChange: node.onCheckedChange,\n disabled: node.disabled ?? false,\n closeOnClick: node.closeOnClick,\n },\n context: {\n ...context,\n value: node.value,\n checked: node.checked,\n disabled: node.disabled ?? false,\n },\n })}\n </React.Fragment>\n )\n }\n\n if (node.kind === 'submenu') {\n // For submenus, provide the nodes and a recursive renderNode function\n // Note: We pass the compositeId to the submenu trigger so it registers with the\n // correct ID for keyboard navigation during deep search\n\n // Get async state for this submenu if it has asyncNodes\n let submenuAsyncState:\n | {\n isLoading: boolean\n isError: boolean\n error: Error | null\n isBelowMinLength?: boolean\n }\n | undefined\n if (node.asyncNodes && coordinator) {\n const asyncResult = coordinator.loaders.get(compositeId)\n if (asyncResult) {\n const isBelowMinLength =\n node.asyncNodes.type === 'query' &&\n search.length < (node.asyncNodes.minQueryLength ?? 1)\n submenuAsyncState = {\n isLoading: asyncResult.result.isLoading,\n isError: asyncResult.result.isError,\n error: asyncResult.result.error,\n isBelowMinLength,\n }\n }\n }\n\n // Static nodes only - async content is handled by the submenu's own DataSurface\n const staticNodes = node.nodes ?? []\n\n // Create breadcrumb node for current submenu (used in child contexts)\n const submenuBreadcrumb: BreadcrumbNode = {\n node,\n value: node.value,\n id: node.id,\n }\n\n const submenuRenderNode = (childNode: NodeDef): React.ReactNode => {\n // Skip separators\n if (childNode.kind === 'separator') {\n return null\n }\n\n // Handle groups - render the group with its children\n if (childNode.kind === 'group') {\n const groupItems = childNode.nodes.filter(\n (n): n is ItemDef | CheckboxItemDef | SubmenuDef =>\n (n.kind === 'item' ||\n n.kind === 'checkbox-item' ||\n n.kind === 'submenu') &&\n !n.hidden,\n )\n\n if (groupItems.length === 0) {\n return null\n }\n\n // Render group items - renderRowNode already wraps in keyed Fragment\n const groupChildren = groupItems.map((item) => {\n const itemContext: RowRenderContext = {\n search: null,\n breadcrumbs: [...context.breadcrumbs, submenuBreadcrumb],\n isDeepSearchResult: false,\n highlighted: false,\n disabled: item.disabled ?? false,\n group: { id: childNode.id, label: childNode.label },\n }\n\n return renderRowNode({ node: item, context: itemContext })\n })\n\n // Use custom group render if provided\n if (childNode.render) {\n const groupContext: GroupRenderContext = {\n search: null,\n matchCount: groupItems.length,\n breadcrumbs: [...context.breadcrumbs, submenuBreadcrumb],\n isDeepSearchResult: false,\n }\n return (\n <React.Fragment key={childNode.id}>\n {childNode.render({\n props: {},\n context: {\n ...groupContext,\n label: childNode.label,\n },\n children: <>{groupChildren}</>,\n })}\n </React.Fragment>\n )\n }\n\n // Default group rendering\n return (\n // biome-ignore lint/a11y/useSemanticElements: ignore for now\n <div\n key={childNode.id}\n role=\"group\"\n aria-label={childNode.label}\n >\n {groupChildren}\n </div>\n )\n }\n\n // Handle radio groups inside submenus\n if (childNode.kind === 'radio-group') {\n return renderRadioGroup(childNode, [\n ...context.breadcrumbs,\n submenuBreadcrumb,\n ])\n }\n\n // Handle items, checkbox items, and submenus\n if (\n childNode.kind !== 'item' &&\n childNode.kind !== 'checkbox-item' &&\n childNode.kind !== 'submenu'\n ) {\n return null\n }\n\n // Create context for child node (no deep search in submenu)\n const childContext: RowRenderContext = {\n search: null,\n breadcrumbs: [...context.breadcrumbs, submenuBreadcrumb],\n isDeepSearchResult: false,\n highlighted: false,\n disabled: childNode.disabled ?? false,\n group: null,\n }\n\n // renderRowNode already wraps in a keyed Fragment\n return renderRowNode({\n node: childNode,\n context: childContext,\n })\n }\n\n return (\n <React.Fragment key={compositeId}>\n {node.render({\n props: {\n id: compositeId,\n value: node.value,\n disabled: node.disabled ?? false,\n },\n context: {\n ...context,\n value: node.value,\n disabled: node.disabled ?? false,\n async: submenuAsyncState,\n },\n nodes: staticNodes,\n asyncContent: node.asyncNodes,\n renderNode: submenuRenderNode,\n })}\n </React.Fragment>\n )\n }\n\n return null\n },\n [coordinator, search],\n )\n\n // Helper to render a radio group\n const renderRadioGroup = React.useCallback(\n (\n radioGroup: RadioGroupDef,\n breadcrumbs: BreadcrumbNode[] = [],\n ): React.ReactNode => {\n const isDeepSearchResult = breadcrumbs.length > 0\n\n // Build group context\n const groupContext: GroupRenderContext = {\n search: null,\n matchCount: radioGroup.nodes.length,\n breadcrumbs,\n isDeepSearchResult,\n }\n\n // Render children - renderRowNode already wraps in keyed Fragment\n const childElements = radioGroup.nodes.map((item) => {\n if (item.hidden) return null\n\n const itemContext: RowRenderContext = {\n search: null,\n breadcrumbs,\n isDeepSearchResult,\n highlighted: false,\n disabled: item.disabled ?? false,\n group: null,\n }\n\n return renderRowNode({\n node: item,\n context: itemContext,\n radioGroup: { id: radioGroup.id, label: radioGroup.label },\n })\n })\n\n // Use custom render if provided\n if (radioGroup.render) {\n return (\n <React.Fragment key={radioGroup.id}>\n {radioGroup.render({\n props: {\n value: radioGroup.value,\n onValueChange: radioGroup.onValueChange,\n disabled: radioGroup.disabled ?? false,\n },\n context: {\n ...groupContext,\n label: radioGroup.label,\n value: radioGroup.value,\n disabled: radioGroup.disabled ?? false,\n },\n children: <>{childElements}</>,\n })}\n </React.Fragment>\n )\n }\n\n // Minimal default: just render children with a wrapper\n return (\n <div\n key={radioGroup.id}\n role=\"radiogroup\"\n aria-label={radioGroup.label}\n >\n {childElements}\n </div>\n )\n },\n [renderRowNode],\n )\n\n // Build the renderNode function that handles groups, radio groups, and rows\n const renderNode: RenderNodeFn = React.useCallback(\n (displayNode: DisplayNode): React.ReactNode => {\n // Handle group display nodes\n if (isDisplayGroupNode(displayNode)) {\n const { group, context, items } = displayNode\n\n // Render children - renderRowNode already wraps in keyed Fragment\n const children = items.map((item) => renderRowNode(item))\n\n // Use custom render if provided\n if (group.render) {\n return (\n <React.Fragment key={group.id}>\n {group.render({\n props: {},\n context: {\n ...context,\n label: group.label,\n },\n children: <>{children}</>,\n })}\n </React.Fragment>\n )\n }\n\n // Minimal default: just render children with a wrapper\n return (\n // biome-ignore lint/a11y/useSemanticElements: ignore for now\n <div key={group.id} role=\"group\" aria-label={group.label}>\n {children}\n </div>\n )\n }\n\n // Handle radio group display nodes\n if (isDisplayRadioGroupNode(displayNode)) {\n const { radioGroup, context, items } = displayNode\n\n // Render children - renderRowNode already wraps in keyed Fragment\n const children = items.map((item) => renderRowNode(item))\n\n // Use custom render if provided\n if (radioGroup.render) {\n return (\n <React.Fragment key={radioGroup.id}>\n {radioGroup.render({\n props: {\n value: radioGroup.value,\n onValueChange: radioGroup.onValueChange,\n disabled: radioGroup.disabled ?? false,\n },\n context: {\n ...context,\n label: radioGroup.label,\n value: radioGroup.value,\n disabled: radioGroup.disabled ?? false,\n },\n children: <>{children}</>,\n })}\n </React.Fragment>\n )\n }\n\n // Minimal default: just render children with a wrapper\n return (\n <div\n key={radioGroup.id}\n role=\"radiogroup\"\n aria-label={radioGroup.label}\n >\n {children}\n </div>\n )\n }\n\n // Handle separator display nodes\n if (isDisplaySeparatorNode(displayNode)) {\n const { separator } = displayNode\n\n // Use custom render if provided\n if (separator.render) {\n return (\n <React.Fragment key={separator.id ?? 'separator'}>\n {separator.render({\n props: { id: separator.id },\n })}\n </React.Fragment>\n )\n }\n\n // Minimal default: render a div with role=\"none\"\n return <div key={separator.id ?? 'separator'} role=\"none\" />\n }\n\n // Handle row display nodes (items/checkbox items/submenus)\n // renderRowNode already wraps in keyed Fragment\n return renderRowNode(displayNode)\n },\n [renderRowNode],\n )\n\n // Get async state from coordinator\n const asyncState = React.useMemo(() => {\n if (!coordinator) {\n return {\n isLoading: false,\n isStaticLoading: false,\n isQueryLoading: false,\n skippedMenus: [] as Array<{\n id: string\n reason: 'error'\n }>,\n }\n }\n return coordinator.getAsyncState()\n }, [coordinator, coordinator?.loaders, coordinator?.erroredLoaders])\n\n // Build children state\n const childrenState: DataListChildrenState = React.useMemo(\n () => ({\n search,\n nodes: displayNodes,\n renderNode,\n count: displayNodes.length,\n isDeepSearching,\n async: asyncState,\n }),\n [search, displayNodes, renderNode, isDeepSearching, asyncState],\n )\n\n const renderedChildren = children(childrenState)\n\n // Use PopupMenuList which handles keyboard navigation\n return (\n <>\n {/* Render async loaders (hidden, just for hook execution) */}\n {shouldRenderAsyncLoaders && (\n <>\n {/* Root async content loader */}\n <RootAsyncLoader query={search} />\n\n {/* Submenu async loaders */}\n {asyncSubmenus.map((info) => (\n <AsyncLoaderRenderer\n key={info.id}\n info={info}\n query={search}\n enabled={\n isDeepSearchActive && shouldIncludeInDeepSearch(info.config)\n }\n />\n ))}\n </>\n )}\n\n <PopupMenuList\n ref={forwardedRef}\n label={label}\n className={className}\n style={style}\n render={render}\n measureRowWidth={measureRowWidth}\n maxRowWidth={maxRowWidth}\n >\n {renderedChildren}\n </PopupMenuList>\n </>\n )\n },\n)\n\nexport namespace PopupMenuDataList {\n export interface Props extends PopupMenuDataListProps {}\n export type ChildrenState = DataListChildrenState\n}\n","import type * as React from 'react'\nimport type { PopupMenuCheckboxItemProps } from '../components/checkbox-item/checkbox-item.js'\nimport type { PopupMenuItemProps } from '../components/item/item.js'\nimport type { PopupMenuRadioGroupProps } from '../components/radio-group/radio-group.js'\nimport type { PopupMenuRadioItemProps } from '../components/radio-item/radio-item.js'\nimport type { PopupMenuSubmenuTriggerProps } from '../components/submenu-trigger/submenu-trigger.js'\nimport type {\n CheckedChangeEventDetails,\n RadioValueChangeEventDetails,\n} from '../events.js'\n\n// ============================================================================\n// Async Loader Types\n// ============================================================================\n\n/**\n * Library-agnostic result from an async loader.\n * Compatible with TanStack Query, SWR, and custom loaders.\n */\nexport interface AsyncLoaderResult<T> {\n /** The loaded data, undefined while loading or on error */\n data: T | undefined\n /** Error if the load failed, null otherwise */\n error: Error | null\n /** Whether the loader is currently loading */\n isLoading: boolean\n /** Whether the loader encountered an error */\n isError: boolean\n /** Optional function to refetch the data */\n refetch?: () => void\n}\n\n/**\n * Props passed to loader components.\n * The component should call hooks internally and pass the result to children.\n */\nexport interface LoaderComponentProps {\n /** Search query (for query-dependent loaders) */\n query: string\n /** Render function receiving loader state */\n children: (state: AsyncLoaderResult<NodeDef[]>) => React.ReactNode\n}\n\n/**\n * Static loader configuration.\n * Loads data once, then filters client-side.\n */\nexport interface StaticLoaderConfig {\n type: 'static'\n /**\n * Component that calls hooks and provides loader state.\n * This component pattern allows hooks to be called legally within React's rules.\n */\n Loader: React.ComponentType<LoaderComponentProps>\n /**\n * When to trigger the loader:\n * - 'eager': Load when menu opens (good for deep search)\n * - 'lazy': Load when submenu opens (default)\n * @default 'lazy'\n */\n loadStrategy?: 'eager' | 'lazy'\n}\n\n/**\n * Query-dependent loader configuration.\n * Refetches based on search query - server does the filtering.\n */\nexport interface QueryDependentLoaderConfig {\n type: 'query'\n /**\n * Component that calls hooks and provides loader state.\n * Receives the current search query as a prop.\n */\n Loader: React.ComponentType<LoaderComponentProps>\n /**\n * Minimum query length before fetching.\n * @default 1\n */\n minQueryLength?: number\n /**\n * Initial query to use when the loader becomes active.\n * Set to '' to fetch all items immediately when the submenu opens.\n * If undefined, waits for user to type before fetching.\n */\n initialQuery?: string\n /**\n * When to trigger the loader:\n * - 'eager': Load when root menu opens (good for deep search)\n * - 'lazy': Load when submenu opens (default)\n * @default 'lazy'\n */\n loadStrategy?: 'eager' | 'lazy'\n /**\n * What to show when query is below minQueryLength.\n * - 'empty': Show nothing\n * - 'placeholder': Show placeholderNodes\n * @default 'empty'\n */\n belowMinBehavior?: 'empty' | 'placeholder'\n /**\n * Placeholder nodes shown when query is below minQueryLength.\n */\n placeholderNodes?: NodeDef[]\n}\n\n/**\n * Union of all async loader configurations.\n */\nexport type AsyncLoaderConfig = StaticLoaderConfig | QueryDependentLoaderConfig\n\n/**\n * Base options for async nodes that apply to both loader types.\n */\ninterface AsyncNodesBaseOptions {\n /**\n * Include this menu's async content in parent's deep search.\n * - Static loaders: default true (data loaded, filter client-side)\n * - Query loaders: default true (pass query to server)\n */\n includeInDeepSearch?: boolean\n}\n\n/**\n * Static async nodes configuration for submenus.\n */\nexport type StaticAsyncNodesConfig = StaticLoaderConfig & AsyncNodesBaseOptions\n\n/**\n * Query-dependent async nodes configuration for submenus.\n */\nexport type QueryAsyncNodesConfig = QueryDependentLoaderConfig &\n AsyncNodesBaseOptions\n\n/**\n * Async nodes configuration for submenus.\n * Union of static and query-dependent loader configs with deep search options.\n */\nexport type AsyncNodesConfig = StaticAsyncNodesConfig | QueryAsyncNodesConfig\n\n/**\n * Async state exposed to submenu render functions.\n */\nexport interface AsyncRenderState {\n /** Whether the loader is currently loading */\n isLoading: boolean\n /** Whether the loader encountered an error */\n isError: boolean\n /** The error if any */\n error: Error | null\n /** For query loaders: whether query is below minQueryLength */\n isBelowMinLength?: boolean\n}\n\n/**\n * Aggregate async state exposed to DataList children.\n */\nexport interface AsyncState {\n /** Any loader is currently loading */\n isLoading: boolean\n /** Static loaders specifically are loading */\n isStaticLoading: boolean\n /** Query loaders specifically are loading */\n isQueryLoading: boolean\n /** Menus that failed (skipped from results) */\n skippedMenus: Array<{ id: string; reason: 'error' }>\n}\n\n// ============================================================================\n// getQualifiedRowId - Unique ID Generation\n// ============================================================================\n\n/**\n * Submenu node info passed in breadcrumbs context.\n * Contains the full submenu definition for maximum flexibility.\n */\nexport interface BreadcrumbNode {\n /** The submenu node definition */\n node: SubmenuDef\n /** The submenu's value */\n value: string\n /** The submenu's explicit id (if provided) */\n id?: string\n}\n\n/**\n * Context passed to the getQualifiedRowId function.\n * Provides all information needed to generate a unique ID for a row.\n */\nexport interface GetQualifiedRowIdContext {\n /** The node definition */\n node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef\n\n /** The node's value (node.value) - used for search/filtering and as fallback identifier */\n value: string\n\n /** The node's explicit id (node.id) - if provided, treated as globally unique */\n id: string | undefined\n\n /** Position in the flattened display list (0-based) */\n index: number\n\n /**\n * Breadcrumb nodes from root to parent.\n * Contains full submenu node definitions for maximum flexibility.\n */\n breadcrumbs: BreadcrumbNode[]\n\n /** Whether deep search is currently active (search query meets minLength threshold) */\n isDeepSearching: boolean\n\n /** Search context, null if browsing */\n search: { query: string; score: number } | null\n\n /** Whether surfaced via deep search (rendered outside its home menu) */\n isDeepSearchResult: boolean\n\n /** Group context, if any */\n group: { id: string; label?: string } | null\n\n /** Radio group context, if any */\n radioGroup: { id: string; label?: string } | null\n}\n\n/**\n * Function that generates a unique qualified ID for a row.\n * Used for React keys, store registration, and DOM id attributes.\n *\n * Default behavior:\n * - If node.id is provided, use it as-is (treat as globally unique)\n * - Otherwise, compute from breadcrumbs + value when deep searching\n *\n * @example\n * ```ts\n * // Custom implementation\n * const getQualifiedRowId: GetQualifiedRowIdFn = (ctx) => {\n * // Use explicit id if provided\n * if (ctx.id) return ctx.id\n *\n * // Otherwise, build from breadcrumbs + value\n * const path = ctx.breadcrumbs.map(b => b.id ?? slugify(b.value))\n * return [...path, slugify(ctx.value)].join('.')\n * }\n * ```\n */\nexport type GetQualifiedRowIdFn = (context: GetQualifiedRowIdContext) => string\n\n// ============================================================================\n// Render Context - passed to all render functions\n// ============================================================================\n\n/**\n * Context passed to item and submenu render functions.\n * Provides information about the current rendering context (search, breadcrumbs, state).\n */\nexport interface RowRenderContext {\n /**\n * Search context - the query in the menu where this row is being rendered.\n * `null` if no active search (browsing mode).\n */\n search: {\n /** Current search query */\n query: string\n /** Match score for this row (0-1, higher = better match) */\n score: number\n } | null\n\n /**\n * Full path of submenu nodes from root to this row's parent.\n * Contains the full submenu node definitions for maximum flexibility.\n * Empty array [] for items directly in root menu.\n */\n breadcrumbs: BreadcrumbNode[]\n\n /**\n * True if this row is being rendered outside its \"home\" menu\n * (surfaced via deep search from an ancestor menu).\n */\n isDeepSearchResult: boolean\n\n /** Whether this row is currently highlighted/focused */\n highlighted: boolean\n\n /** Whether this row is disabled */\n disabled: boolean\n\n /**\n * The group this item belongs to, if any.\n * `null` if the item is not inside a group.\n */\n group: { id: string; label?: string } | null\n}\n\n// ============================================================================\n// Item Render Params\n// ============================================================================\n\n/**\n * Props to spread onto the Item component.\n * Derived from PopupMenuItemProps.\n */\nexport type ItemRenderProps = {\n /**\n * Qualified unique ID for the item.\n * Must be passed to the rendered component for navigation to work.\n * This is the computed qualified ID (includes breadcrumb path for deep search results).\n */\n id: string\n /**\n * The original value from the node definition.\n * Use this for display, search matching, or any logic that needs the raw value.\n */\n value: string\n} & Required<Pick<PopupMenuItemProps, 'disabled'>> &\n Pick<PopupMenuItemProps, 'closeOnClick' | 'onSelect' | 'shortcut'>\n\n/**\n * Parameters passed to item render functions.\n */\nexport interface ItemRenderParams {\n /** Props to spread onto the Item component */\n props: ItemRenderProps\n /** Context for conditional rendering (includes props values for convenience) */\n context: RowRenderContext & {\n /** The node's value (ItemDef.value) */\n value: string\n disabled: boolean\n }\n}\n\n// ============================================================================\n// Radio Item Render Params\n// ============================================================================\n\n/**\n * Props to spread onto the RadioItem component.\n * Derived from PopupMenuRadioItemProps.\n */\nexport type RadioItemRenderProps = {\n /**\n * Qualified unique ID for the radio item.\n * Must be passed to the rendered component for navigation to work.\n */\n id: string\n} & Required<Pick<PopupMenuRadioItemProps, 'value' | 'disabled'>> &\n Pick<PopupMenuRadioItemProps, 'closeOnClick' | 'onSelect' | 'shortcut'>\n\n/**\n * Parameters passed to radio item render functions.\n */\nexport interface RadioItemRenderParams {\n /** Props to spread onto the RadioItem component */\n props: RadioItemRenderProps\n /** Context for conditional rendering (includes props values for convenience) */\n context: RowRenderContext & {\n /** The node's value (RadioItemDef.value) */\n value: string\n disabled: boolean\n }\n}\n\n// ============================================================================\n// Submenu Render Params\n// ============================================================================\n\n/**\n * Props to spread onto the SubmenuTrigger component.\n * Derived from PopupMenuSubmenuTriggerProps.\n */\nexport type SubmenuRenderProps = {\n /**\n * Qualified unique ID for the submenu trigger.\n * Must be passed to the rendered component for navigation to work.\n */\n id: string\n /**\n * The original value from the node definition.\n */\n value: string\n} & Required<Pick<PopupMenuSubmenuTriggerProps, 'disabled'>>\n\n/**\n * Parameters passed to submenu render functions.\n * Includes context plus the submenu's child nodes and render function.\n */\nexport interface SubmenuRenderParams {\n /** Props to spread onto the SubmenuTrigger */\n props: SubmenuRenderProps\n /** Context for conditional rendering (includes props values for convenience) */\n context: RowRenderContext & {\n /** The node's value (SubmenuDef.value) */\n value: string\n disabled: boolean\n /** Async loading state (if asyncNodes configured) */\n async?: AsyncRenderState\n }\n /**\n * The submenu's static child node definitions.\n * Does NOT include async results - use `asyncContent` for that.\n */\n nodes: NodeDef[]\n /**\n * Async content configuration for this submenu.\n * Pass this to the submenu's DataSurface to enable async loading\n * with the submenu's own search query (independent of parent search).\n */\n asyncContent?: AsyncNodesConfig\n /**\n * Function to render a child node.\n * Call this for each node in the submenu's list.\n */\n renderNode: (node: NodeDef) => React.ReactNode\n}\n\n// ============================================================================\n// Group Render Types\n// ============================================================================\n\n/**\n * Context passed to group render functions.\n * Contains information about the group's state during search.\n */\nexport interface GroupRenderContext {\n /**\n * Search context with the best match score among items in this group.\n * `null` if no active search (browsing mode).\n */\n search: {\n /** Current search query */\n query: string\n /** Best match score among items in this group (0-1) */\n bestScore: number\n } | null\n\n /** Number of matching items in this group */\n matchCount: number\n\n /**\n * Breadcrumb nodes if this group is from a surfaced submenu.\n * Empty array [] for groups in the root menu.\n */\n breadcrumbs: BreadcrumbNode[]\n\n /** Whether this group is from deep search (surfaced from a submenu) */\n isDeepSearchResult: boolean\n}\n\n/**\n * Parameters passed to group render functions.\n */\nexport interface GroupRenderParams {\n /** Props (empty for groups, but consistent structure) */\n props: Record<string, never>\n /** Context for conditional rendering (includes label for convenience) */\n context: GroupRenderContext & {\n /** The group's label */\n label?: string\n }\n /** Pre-rendered matching children */\n children: React.ReactNode\n}\n\n// ============================================================================\n// Checkbox Item Types\n// ============================================================================\n\n/**\n * Props to spread onto the CheckboxItem component.\n * Derived from PopupMenuCheckboxItemProps.\n */\nexport type CheckboxItemRenderProps = {\n /**\n * Qualified unique ID for the checkbox item.\n * Must be passed to the rendered component for navigation to work.\n */\n id: string\n /**\n * The original value from the node definition.\n */\n value: string\n} & Required<Pick<PopupMenuCheckboxItemProps, 'disabled'>> &\n Pick<\n PopupMenuCheckboxItemProps,\n 'checked' | 'onCheckedChange' | 'closeOnClick'\n >\n\n/**\n * Parameters passed to checkbox item render functions.\n */\nexport interface CheckboxItemRenderParams {\n /** Props to spread onto the CheckboxItem component */\n props: CheckboxItemRenderProps\n /** Context for conditional rendering (includes props values for convenience) */\n context: RowRenderContext & {\n /** The node's value (CheckboxItemDef.value) */\n value: string\n checked?: boolean\n disabled: boolean\n }\n}\n\n// ============================================================================\n// Radio Group Types\n// ============================================================================\n\n/**\n * Props to spread onto the RadioGroup component.\n * Derived from PopupMenuRadioGroupProps.\n */\nexport type RadioGroupRenderProps = Required<\n Pick<PopupMenuRadioGroupProps, 'disabled'>\n> &\n Pick<PopupMenuRadioGroupProps, 'value' | 'onValueChange'>\n\n/**\n * Parameters passed to radio group render functions.\n */\nexport interface RadioGroupRenderParams {\n /** Props to spread onto the RadioGroup component */\n props: RadioGroupRenderProps\n /** Context for conditional rendering */\n context: GroupRenderContext & {\n /** The radio group's label */\n label?: string\n /** Current selected value */\n value?: string\n /** Whether the radio group is disabled */\n disabled: boolean\n }\n /** Pre-rendered radio items */\n children: React.ReactNode\n}\n\n// ============================================================================\n// Node Definitions\n// ============================================================================\n\n/**\n * Base properties shared by all node types.\n */\ninterface BaseNodeDef {\n /**\n * Unique identifier for this node.\n * If not provided, a composite ID is generated from the `value` and breadcrumbs\n * using the `getItemId` function.\n */\n id?: string\n /** Whether this node is hidden */\n hidden?: boolean\n}\n\n/**\n * Item node definition.\n * Represents a selectable menu item.\n * Props derived from PopupMenuItemProps.\n */\nexport interface ItemDef\n extends BaseNodeDef,\n Required<Pick<PopupMenuItemProps, 'value'>>,\n Pick<\n PopupMenuItemProps,\n 'keywords' | 'disabled' | 'onSelect' | 'closeOnClick' | 'shortcut'\n > {\n kind: 'item'\n /**\n * Render function for this item row.\n * Returns the JSX for the item.\n */\n render: (params: ItemRenderParams) => React.ReactNode\n}\n\n/**\n * Radio item node definition.\n * Represents a selectable radio menu item for use within RadioGroupDef.\n * Props derived from PopupMenuRadioItemProps.\n */\nexport interface RadioItemDef\n extends BaseNodeDef,\n Required<Pick<PopupMenuRadioItemProps, 'value'>>,\n Pick<\n PopupMenuRadioItemProps,\n 'keywords' | 'disabled' | 'onSelect' | 'closeOnClick' | 'shortcut'\n > {\n kind: 'radio-item'\n /**\n * Render function for this radio item row.\n * Returns the JSX for the radio item.\n */\n render: (params: RadioItemRenderParams) => React.ReactNode\n}\n\n/**\n * Checkbox item node definition.\n * Represents a toggleable checkbox menu item.\n * Props derived from PopupMenuCheckboxItemProps.\n */\nexport interface CheckboxItemDef\n extends BaseNodeDef,\n Pick<\n PopupMenuCheckboxItemProps,\n 'keywords' | 'disabled' | 'checked' | 'onCheckedChange' | 'closeOnClick'\n > {\n kind: 'checkbox-item'\n /**\n * Primary identifier and search text for this checkbox item.\n * Used for search matching and as the default identifier.\n */\n value: string\n /**\n * Render function for this checkbox item row.\n * Returns the JSX for the checkbox item.\n */\n render: (params: CheckboxItemRenderParams) => React.ReactNode\n}\n\n/**\n * Submenu node definition.\n * Represents a submenu trigger that opens a nested menu.\n * Props derived from PopupMenuSubmenuTriggerProps.\n */\nexport interface SubmenuDef\n extends BaseNodeDef,\n Required<Pick<PopupMenuSubmenuTriggerProps, 'value'>>,\n Pick<PopupMenuSubmenuTriggerProps, 'keywords' | 'disabled'> {\n kind: 'submenu'\n\n /** Static child nodes */\n nodes?: NodeDef[]\n\n /**\n * Async child nodes configuration.\n * When provided, the Loader component will be rendered to fetch async data.\n * Async nodes are merged with static nodes.\n */\n asyncNodes?: AsyncNodesConfig\n\n /**\n * Whether to include this submenu's children in deep search.\n * @default true\n */\n deepSearch?: boolean\n\n /**\n * Render function for the entire submenu structure.\n * Should return the complete submenu: trigger, portal, positioner, popup, surface, list.\n */\n render: (params: SubmenuRenderParams) => React.ReactNode\n}\n\n/**\n * Render params for separator nodes.\n */\nexport interface SeparatorRenderParams {\n /** Props to spread on the separator element */\n props: {\n /** Unique identifier */\n id?: string\n }\n}\n\n/**\n * Separator node definition.\n * Represents a visual separator between items.\n */\nexport interface SeparatorDef {\n kind: 'separator'\n /** Optional identifier */\n id?: string\n /** Optional render function for custom separator rendering */\n render?: (params: SeparatorRenderParams) => React.ReactNode\n}\n\n/**\n * Group node definition.\n * Represents a group of items with an optional label.\n */\nexport interface GroupDef {\n kind: 'group'\n /** Unique identifier for this group */\n id: string\n /** Optional group heading/label */\n label?: string\n /** Child nodes in this group */\n nodes: NodeDef[]\n /** Optional render function for the group container */\n render?: (params: GroupRenderParams) => React.ReactNode\n}\n\n/**\n * Radio group node definition.\n * Represents a group of radio items where only one can be selected.\n * Props derived from PopupMenuRadioGroupProps.\n */\nexport interface RadioGroupDef\n extends Pick<\n PopupMenuRadioGroupProps,\n 'value' | 'onValueChange' | 'disabled'\n > {\n kind: 'radio-group'\n /** Unique identifier for this radio group */\n id: string\n /** Optional group heading/label */\n label?: string\n /** Whether the radio group is hidden */\n hidden?: boolean\n /** Child nodes in this radio group - must be RadioItemDef nodes */\n nodes: RadioItemDef[]\n /** Optional render function for the radio group container */\n render?: (params: RadioGroupRenderParams) => React.ReactNode\n}\n\n/**\n * Helper function to create a radio group definition with proper typing.\n */\nexport function defineRadioGroup(def: RadioGroupDef): RadioGroupDef {\n return def\n}\n\n/**\n * Union of all node definition types.\n */\nexport type NodeDef =\n | ItemDef\n | RadioItemDef\n | CheckboxItemDef\n | SubmenuDef\n | SeparatorDef\n | GroupDef\n | RadioGroupDef\n\n// ============================================================================\n// Scored Node - internal type for search results\n// ============================================================================\n\n/**\n * A node with its search score and breadcrumb path.\n * Used internally during filtering and scoring.\n */\nexport interface ScoredNode {\n /** The original node definition */\n node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef\n /** Search match score (0-1) */\n score: number\n /**\n * Breadcrumb nodes leading to this node.\n * Contains the full submenu definitions for maximum flexibility.\n */\n breadcrumbs: BreadcrumbNode[]\n /** The group this node belongs to, if any */\n group: { id: string; label?: string; groupDef: GroupDef } | null\n /** The radio group this node belongs to, if any */\n radioGroup: {\n id: string\n label?: string\n radioGroupDef: RadioGroupDef\n } | null\n}\n\n// ============================================================================\n// Display Node - node with render context attached\n// ============================================================================\n\n/**\n * A row node ready for display with its render context.\n * Used for items, radio items, checkbox items, and submenu triggers.\n */\nexport interface DisplayRowNode {\n /** The original node definition */\n node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef\n /** Pre-computed render context for this node */\n context: RowRenderContext\n /** Radio group this node belongs to, if rendering inside one */\n radioGroup?: { id: string; label?: string }\n /**\n * Computed composite ID for this node.\n * Includes breadcrumb path for deep search results (e.g., \"status.in-progress\").\n * Set after filtering via `computeItemIds`.\n */\n compositeId?: string\n}\n\n/**\n * A group node ready for display with its render context.\n * Contains the group definition and its matching items.\n */\nexport interface DisplayGroupNode {\n kind: 'group'\n /** The group definition */\n group: GroupDef\n /** Pre-computed render context for this group */\n context: GroupRenderContext\n /** Display nodes for items within this group */\n items: DisplayRowNode[]\n /** Best match score among items in this group */\n bestScore: number\n}\n\n/**\n * A radio group node ready for display with its render context.\n * Contains the radio group definition and its items.\n */\nexport interface DisplayRadioGroupNode {\n kind: 'radio-group'\n /** The radio group definition */\n radioGroup: RadioGroupDef\n /** Pre-computed render context for this radio group */\n context: GroupRenderContext\n /** Display nodes for items within this radio group */\n items: DisplayRowNode[]\n /** Best match score among items in this radio group */\n bestScore: number\n}\n\n/**\n * A separator node ready for display.\n */\nexport interface DisplaySeparatorNode {\n kind: 'separator'\n /** The separator definition */\n separator: SeparatorDef\n}\n\n/**\n * Union of all display node types.\n * Can be a row node (item/submenu), group node, radio group node, or separator.\n */\nexport type DisplayNode =\n | DisplayRowNode\n | DisplayGroupNode\n | DisplayRadioGroupNode\n | DisplaySeparatorNode\n\n/**\n * Type guard for DisplayGroupNode.\n */\nexport function isDisplayGroupNode(\n node: DisplayNode,\n): node is DisplayGroupNode {\n return 'kind' in node && node.kind === 'group'\n}\n\n/**\n * Type guard for DisplayRadioGroupNode.\n */\nexport function isDisplayRadioGroupNode(\n node: DisplayNode,\n): node is DisplayRadioGroupNode {\n return 'kind' in node && node.kind === 'radio-group'\n}\n\n/**\n * Type guard for DisplaySeparatorNode.\n */\nexport function isDisplaySeparatorNode(\n node: DisplayNode,\n): node is DisplaySeparatorNode {\n return 'kind' in node && node.kind === 'separator'\n}\n\n/**\n * Type guard for DisplayRowNode (items, checkbox items, submenus).\n */\nexport function isDisplayRowNode(node: DisplayNode): node is DisplayRowNode {\n return !('kind' in node)\n}\n\n// ============================================================================\n// Deep Search Configuration\n// ============================================================================\n\n/**\n * Defines how groups behave during deep search.\n * - 'flatten': Groups become invisible, items shown in flat list by score.\n * - 'preserve': Groups are shown as containers with their matching items.\n * Note: Radio groups are ALWAYS preserved regardless of this setting.\n */\nexport type GroupBehavior = 'flatten' | 'preserve'\n\n/**\n * Defines how radio groups behave during deep search.\n * - 'flatten': Radio group items are shown individually in the flat list (not recommended).\n * - 'preserve': Radio group is shown with only matching items visible.\n * - 'preserve-show-all': Radio group is shown with ALL items visible when any item matches.\n * This is useful when you want users to see all options in a radio group.\n */\nexport type RadioGroupBehavior = 'flatten' | 'preserve' | 'preserve-show-all'\n\n/**\n * Configuration for deep search behavior.\n */\nexport interface DeepSearchConfig {\n /** Whether deep search is enabled */\n enabled?: boolean\n /** Minimum query length before deep search activates */\n minLength?: number\n /**\n * How groups behave during search results.\n * Only affects search mode - groups are always shown in browse mode.\n * Note: Radio groups have their own behavior controlled by radioGroupSearchBehavior.\n * @default 'preserve'\n */\n groupSearchBehavior?: GroupBehavior\n /**\n * How radio groups behave during search results.\n * - 'flatten': Radio items shown individually (not recommended).\n * - 'preserve': Only matching radio items are shown (default).\n * - 'preserve-show-all': All radio items are shown when any item matches.\n * @default 'preserve'\n */\n radioGroupSearchBehavior?: RadioGroupBehavior\n /**\n * Whether to sort groups by their best-matching item's score.\n * Only applies when groupSearchBehavior: 'preserve'.\n * @default true\n */\n sortGroups?: boolean\n}\n\n// ============================================================================\n// Data Surface Props\n// ============================================================================\n\n/**\n * Props for the DataSurface component.\n */\nexport interface DataSurfaceProps {\n /** The menu content (node definitions with render functions) */\n content?: NodeDef[]\n\n /**\n * Async content configuration for root-level async loading.\n * When provided, the Loader component will be rendered to fetch async data.\n * Async content is merged with static content.\n */\n asyncContent?: AsyncLoaderConfig\n\n /** Deep search configuration */\n deepSearch?: DeepSearchConfig | boolean\n\n /** Filter function or false to disable filtering */\n filter?:\n | ((value: string, search: string, keywords?: string[]) => number)\n | false\n\n /** Controlled search value */\n search?: string\n\n /** Callback when search value changes */\n onSearchChange?: (search: string) => void\n\n /** Default search value for uncontrolled usage */\n defaultSearch?: string\n\n /** Whether navigation should loop */\n loop?: boolean\n\n /** Auto-highlight behavior when menu opens */\n autoHighlightFirst?: boolean | string\n\n /**\n * Whether to clear search on close.\n * - `true`: clear immediately when menu closes (default)\n * - `false`: preserve search when menu closes\n * - `'after-exit'`: clear after exit animation completes\n */\n clearSearchOnClose?: boolean | 'after-exit'\n\n /**\n * Function to generate qualified IDs for row items.\n * Called for each item when rendering to produce IDs for:\n * - React keys\n * - Store registration\n * - DOM id attributes\n *\n * @default Uses node.id if provided, otherwise qualifies with breadcrumbs + slugified value\n */\n getQualifiedRowId?: GetQualifiedRowIdFn\n\n /** Children (Input, List, etc.) */\n children: React.ReactNode\n}\n\n// ============================================================================\n// Data List Props\n// ============================================================================\n\n/**\n * State passed to the DataList render function.\n */\nexport interface DataListChildrenState {\n /** Current search query (empty string if browsing) */\n search: string\n\n /**\n * Display nodes (filtered and scored if searching).\n * Can include groups (DisplayGroupNode) or radio groups (DisplayRadioGroupNode)\n * when groupSearchBehavior: 'preserve'.\n */\n nodes: DisplayNode[]\n\n /**\n * Function to render a node.\n * Handles items, submenus, groups, and radio groups, calling their render functions with context.\n */\n renderNode: (displayNode: DisplayNode) => React.ReactNode\n\n /** Number of visible items (counting items inside groups) */\n count: number\n\n /** Whether deep search is active (query length >= minLength) */\n isDeepSearching: boolean\n\n /** Aggregate async loading state across all menus */\n async: AsyncState\n}\n\n/**\n * Props for the DataList component.\n */\nexport interface DataListProps {\n /**\n * Render function for the list content.\n * Receives the current state and returns JSX.\n */\n children: (state: DataListChildrenState) => React.ReactNode\n\n /** Accessible label for the listbox */\n label?: string\n\n /** Additional class name */\n className?: string\n\n /** Additional styles */\n style?: React.CSSProperties\n\n /**\n * When true, measures row widths and applies `--row-width` CSS variable.\n * Keeps the list at the maximum width seen while scrolling.\n * Useful for virtualized lists where content width varies.\n * @default true\n */\n measureRowWidth?: boolean\n\n /**\n * Maximum width cap for row measurement (in pixels).\n * Only used when `measureRowWidth` is true.\n */\n maxRowWidth?: number\n}\n","import { commandScore } from '../../listbox/utils/command-score.js'\nimport { normalizeValue, slugify } from '../../listbox/utils/normalize.js'\nimport type {\n AsyncNodesConfig,\n BreadcrumbNode,\n CheckboxItemDef,\n DisplayGroupNode,\n DisplayNode,\n DisplayRadioGroupNode,\n DisplayRowNode,\n GetQualifiedRowIdContext,\n GroupBehavior,\n GroupDef,\n GroupRenderContext,\n ItemDef,\n NodeDef,\n RadioGroupBehavior,\n RadioGroupDef,\n RadioItemDef,\n RowRenderContext,\n ScoredNode,\n SeparatorDef,\n SubmenuDef,\n} from './types.js'\nimport {\n isDisplayGroupNode,\n isDisplayRadioGroupNode,\n isDisplaySeparatorNode,\n} from './types.js'\n\n// ============================================================================\n// Default getQualifiedRowId Implementation\n// ============================================================================\n\n/**\n * Default function to generate qualified unique IDs for rows.\n *\n * Logic:\n * - If node.id is provided, use it as-is (treat as globally unique)\n * - Otherwise, when deep searching, qualify with breadcrumb path + value\n * - When not deep searching, just use the slugified value\n *\n * @example\n * // With explicit id:\n * // { id: 'my-unique-id', value: 'In Progress' }\n * // => 'my-unique-id'\n *\n * // Without id, deep searching in \"Status\" submenu:\n * // { value: 'In Progress' } in Status submenu\n * // => 'status.in-progress'\n *\n * // Without id, not deep searching:\n * // { value: 'In Progress' }\n * // => 'in-progress'\n */\nexport function defaultGetQualifiedRowId(\n ctx: GetQualifiedRowIdContext,\n): string {\n // If explicit id is provided, use it as-is (treat as globally unique)\n if (ctx.id) {\n return ctx.id\n }\n\n // Otherwise, compute from breadcrumbs + value\n const slugValue = slugify(ctx.value)\n\n // Only qualify with breadcrumbs when deep searching\n if (ctx.isDeepSearching && ctx.breadcrumbs.length > 0) {\n const slugBreadcrumbs = ctx.breadcrumbs\n .map((b) => b.id ?? slugify(b.value))\n .filter(Boolean)\n if (slugBreadcrumbs.length > 0) {\n return [...slugBreadcrumbs, slugValue].join('.')\n }\n }\n\n return slugValue\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nexport function isItemDef(node: NodeDef): node is ItemDef {\n return node.kind === 'item'\n}\n\nexport function isRadioItemDef(node: NodeDef): node is RadioItemDef {\n return node.kind === 'radio-item'\n}\n\nexport function isCheckboxItemDef(node: NodeDef): node is CheckboxItemDef {\n return node.kind === 'checkbox-item'\n}\n\nexport function isSubmenuDef(node: NodeDef): node is SubmenuDef {\n return node.kind === 'submenu'\n}\n\nexport function isGroupDef(node: NodeDef): node is GroupDef {\n return node.kind === 'group'\n}\n\nexport function isRadioGroupDef(node: NodeDef): node is RadioGroupDef {\n return node.kind === 'radio-group'\n}\n\nexport function isSeparatorDef(\n node: NodeDef,\n): node is { kind: 'separator'; id?: string } {\n return node.kind === 'separator'\n}\n\n// ============================================================================\n// Flatten Nodes for Search\n// ============================================================================\n\ninterface FlattenOptions {\n /** Whether to include children of submenus (deep search) */\n deep?: boolean\n /** Parent breadcrumb nodes (submenu nodes from root to parent) */\n breadcrumbs?: BreadcrumbNode[]\n /** Current group context (nested groups not supported) */\n group?: { id: string; label?: string; groupDef: GroupDef } | null\n /** Current radio group context */\n radioGroup?: {\n id: string\n label?: string\n radioGroupDef: RadioGroupDef\n } | null\n}\n\ninterface FlattenedNode {\n node: ItemDef | RadioItemDef | CheckboxItemDef | SubmenuDef\n /** Breadcrumb nodes (submenu nodes from root to parent) */\n breadcrumbs: BreadcrumbNode[]\n /** The group this node belongs to, if any */\n group: { id: string; label?: string; groupDef: GroupDef } | null\n /** The radio group this node belongs to, if any */\n radioGroup: {\n id: string\n label?: string\n radioGroupDef: RadioGroupDef\n } | null\n}\n\n/**\n * Flattens a tree of node definitions into a flat array.\n * When deep=true, includes children of submenus with their breadcrumb paths.\n * Tracks group and radio group membership for each node.\n */\nexport function flattenNodes(\n nodes: NodeDef[],\n options: FlattenOptions = {},\n): FlattenedNode[] {\n const {\n deep = false,\n breadcrumbs = [],\n group = null,\n radioGroup = null,\n } = options\n const result: FlattenedNode[] = []\n\n for (const node of nodes) {\n if (node.kind === 'separator') {\n // Skip separators during search\n continue\n }\n\n if (node.kind === 'group') {\n // Groups are containers - recurse into their children with group context\n // Note: Nested groups are not supported, so we pass this group directly\n const groupInfo = { id: node.id, label: node.label, groupDef: node }\n result.push(\n ...flattenNodes(node.nodes, {\n deep,\n breadcrumbs,\n group: groupInfo,\n radioGroup: null, // Reset radio group when entering a regular group\n }),\n )\n continue\n }\n\n if (node.kind === 'radio-group') {\n // Radio groups are containers - recurse into their children with radio group context\n if (node.hidden) continue\n\n const radioGroupInfo = {\n id: node.id,\n label: node.label,\n radioGroupDef: node,\n }\n result.push(\n ...flattenNodes(node.nodes, {\n deep,\n breadcrumbs,\n group: null, // Reset regular group when entering a radio group\n radioGroup: radioGroupInfo,\n }),\n )\n continue\n }\n\n if (node.hidden) {\n continue\n }\n\n if (\n node.kind === 'item' ||\n node.kind === 'radio-item' ||\n node.kind === 'checkbox-item'\n ) {\n result.push({\n node,\n breadcrumbs,\n group,\n radioGroup,\n })\n continue\n }\n\n if (node.kind === 'submenu') {\n // Always include the submenu trigger itself\n result.push({\n node,\n breadcrumbs,\n group,\n radioGroup,\n })\n\n // If deep search enabled and submenu allows it, include children\n if (deep && node.deepSearch !== false && node.nodes) {\n // Create breadcrumb node for this submenu\n const submenuBreadcrumb: BreadcrumbNode = {\n node,\n value: node.value,\n id: node.id,\n }\n const childBreadcrumbs: BreadcrumbNode[] = [\n ...breadcrumbs,\n submenuBreadcrumb,\n ]\n\n result.push(\n ...flattenNodes(node.nodes, {\n deep,\n breadcrumbs: childBreadcrumbs,\n // Reset group and radio group context when entering a submenu\n group: null,\n radioGroup: null,\n }),\n )\n }\n }\n }\n\n return result\n}\n\n// ============================================================================\n// Score Nodes\n// ============================================================================\n\n/**\n * Scores nodes against a search query.\n * Returns only nodes with a score > 0.\n */\nexport function scoreNodes(\n flattenedNodes: FlattenedNode[],\n query: string,\n): ScoredNode[] {\n if (!query) {\n // No query - return all nodes with score 1\n return flattenedNodes.map(\n ({ node, breadcrumbs, group, radioGroup }): ScoredNode => ({\n node,\n score: 1,\n breadcrumbs,\n group,\n radioGroup,\n }),\n )\n }\n\n const results: ScoredNode[] = []\n\n for (const { node, breadcrumbs, group, radioGroup } of flattenedNodes) {\n // Normalize value and keywords to match cmdk's behavior\n const normalizedValue = normalizeValue(node.value)\n const normalizedKeywords = node.keywords\n ?.map((k) => normalizeValue(k))\n .filter(Boolean)\n\n const score = commandScore(normalizedValue, query, normalizedKeywords)\n\n if (score > 0) {\n results.push({\n node,\n score,\n breadcrumbs,\n group,\n radioGroup,\n })\n }\n }\n\n return results\n}\n\n// ============================================================================\n// Sort Nodes\n// ============================================================================\n\n/**\n * Sorts scored nodes by score (descending).\n */\nexport function sortByScore(nodes: ScoredNode[]): ScoredNode[] {\n return [...nodes].sort((a, b) => b.score - a.score)\n}\n\n/**\n * Partitions nodes: items first, then submenu triggers.\n * This ensures items appear before submenu triggers in search results.\n */\nexport function partitionByKind(nodes: ScoredNode[]): ScoredNode[] {\n const items = nodes.filter(\n (n) =>\n n.node.kind === 'item' ||\n n.node.kind === 'radio-item' ||\n n.node.kind === 'checkbox-item',\n )\n const submenus = nodes.filter((n) => n.node.kind === 'submenu')\n return [...items, ...submenus]\n}\n\n/**\n * Deduplicates nodes by their composite ID (breadcrumbs + node.value).\n * This handles the case where the same node appears multiple times in the tree.\n * Values are normalized (trimmed) for consistent deduplication.\n */\nexport function deduplicateNodes(nodes: ScoredNode[]): ScoredNode[] {\n const seen = new Set<string>()\n const result: ScoredNode[] = []\n\n for (const scoredNode of nodes) {\n // Normalize value for consistent deduplication\n // Note: breadcrumbs are already normalized in flattenNodes\n const compositeId = [\n ...scoredNode.breadcrumbs,\n normalizeValue(scoredNode.node.value),\n ].join('.')\n if (!seen.has(compositeId)) {\n seen.add(compositeId)\n result.push(scoredNode)\n }\n }\n\n return result\n}\n\n// ============================================================================\n// Build Display Nodes\n// ============================================================================\n\n/**\n * Converts scored nodes to display row nodes with render context.\n * Used for flatten mode where groups are invisible.\n */\nexport function buildDisplayRowNodes(\n scoredNodes: ScoredNode[],\n query: string,\n highlightedId: string | null,\n): DisplayRowNode[] {\n return scoredNodes.map((scoredNode) => {\n const isDeepSearchResult = scoredNode.breadcrumbs.length > 0\n\n const context: RowRenderContext = {\n search: query\n ? {\n query,\n score: scoredNode.score,\n }\n : null,\n breadcrumbs: scoredNode.breadcrumbs,\n // breadcrumbs already set above\n isDeepSearchResult,\n highlighted: scoredNode.node.id === highlightedId,\n disabled: scoredNode.node.disabled ?? false,\n group: scoredNode.group\n ? { id: scoredNode.group.id, label: scoredNode.group.label }\n : null,\n }\n\n return {\n node: scoredNode.node,\n context,\n radioGroup: scoredNode.radioGroup\n ? { id: scoredNode.radioGroup.id, label: scoredNode.radioGroup.label }\n : undefined,\n }\n })\n}\n\n/**\n * Builds a single DisplayRowNode from a ScoredNode.\n * Helper function for building row nodes.\n */\nfunction buildDisplayRowNode(\n scoredNode: ScoredNode,\n query: string,\n highlightedId: string | null,\n): DisplayRowNode {\n const isDeepSearchResult = scoredNode.breadcrumbs.length > 0\n\n const context: RowRenderContext = {\n search: query\n ? {\n query,\n score: scoredNode.score,\n }\n : null,\n breadcrumbs: scoredNode.breadcrumbs,\n isDeepSearchResult,\n highlighted: scoredNode.node.id === highlightedId,\n disabled: scoredNode.node.disabled ?? false,\n group: scoredNode.group\n ? { id: scoredNode.group.id, label: scoredNode.group.label }\n : null,\n }\n\n return {\n node: scoredNode.node,\n context,\n radioGroup: scoredNode.radioGroup\n ? { id: scoredNode.radioGroup.id, label: scoredNode.radioGroup.label }\n : undefined,\n }\n}\n\n// ============================================================================\n// Browse Mode - Get Shallow Nodes\n// ============================================================================\n\n/**\n * Gets nodes for browse mode (no search) with flatten behavior.\n * Returns only top-level items and submenu triggers, flattening groups.\n */\nexport function getBrowseNodesFlatten(\n nodes: NodeDef[],\n highlightedId: string | null,\n group: { id: string; label?: string } | null = null,\n): DisplayRowNode[] {\n const result: DisplayRowNode[] = []\n\n for (const node of nodes) {\n if (node.kind === 'separator') {\n // Skip separators - they're not focusable\n continue\n }\n\n if (node.kind === 'group') {\n // Recurse into groups, passing group context\n const groupInfo = { id: node.id, label: node.label }\n result.push(\n ...getBrowseNodesFlatten(node.nodes, highlightedId, groupInfo),\n )\n continue\n }\n\n if (node.kind === 'radio-group') {\n // Radio groups should not be flattened - skip in flatten mode\n // They will be handled by getBrowseNodesPreserve\n continue\n }\n\n if (node.hidden) {\n continue\n }\n\n const context: RowRenderContext = {\n search: null,\n breadcrumbs: [],\n isDeepSearchResult: false,\n highlighted: node.id === highlightedId,\n disabled: node.disabled ?? false,\n group,\n }\n\n result.push({ node, context })\n }\n\n return result\n}\n\n/**\n * Gets nodes for browse mode (no search) with preserve behavior.\n * Keeps group structure intact, showing group containers with their items.\n */\nexport function getBrowseNodesPreserve(\n nodes: NodeDef[],\n highlightedId: string | null,\n): DisplayNode[] {\n const result: DisplayNode[] = []\n\n for (const node of nodes) {\n if (node.kind === 'separator') {\n // Include separators in browse mode for visual separation\n result.push({ kind: 'separator', separator: node })\n continue\n }\n\n if (node.kind === 'group') {\n // Build group items\n const groupItems: DisplayRowNode[] = []\n for (const child of node.nodes) {\n // Skip non-row nodes\n if (\n child.kind === 'separator' ||\n child.kind === 'group' ||\n child.kind === 'radio-group'\n ) {\n continue\n }\n if (child.hidden) continue\n\n const itemContext: RowRenderContext = {\n search: null,\n breadcrumbs: [],\n isDeepSearchResult: false,\n highlighted: child.id === highlightedId,\n disabled: child.disabled ?? false,\n group: { id: node.id, label: node.label },\n }\n\n groupItems.push({ node: child, context: itemContext })\n }\n\n // Only include group if it has items\n if (groupItems.length > 0) {\n const groupContext: GroupRenderContext = {\n search: null,\n matchCount: groupItems.length,\n breadcrumbs: [],\n isDeepSearchResult: false,\n }\n\n result.push({\n kind: 'group',\n group: node,\n context: groupContext,\n items: groupItems,\n bestScore: 1,\n })\n }\n continue\n }\n\n if (node.kind === 'radio-group') {\n if (node.hidden) continue\n\n // Build radio group items\n const radioItems: DisplayRowNode[] = []\n for (const child of node.nodes) {\n // RadioGroupDef.nodes only contains ItemDef | SubmenuDef | CheckboxItemDef\n if (child.hidden) continue\n\n const itemContext: RowRenderContext = {\n search: null,\n breadcrumbs: [],\n isDeepSearchResult: false,\n highlighted: child.id === highlightedId,\n disabled: child.disabled ?? false,\n group: null, // Radio items don't belong to a regular group\n }\n\n radioItems.push({\n node: child,\n context: itemContext,\n radioGroup: { id: node.id, label: node.label },\n })\n }\n\n // Only include radio group if it has items\n if (radioItems.length > 0) {\n const groupContext: GroupRenderContext = {\n search: null,\n matchCount: radioItems.length,\n breadcrumbs: [],\n isDeepSearchResult: false,\n }\n\n result.push({\n kind: 'radio-group',\n radioGroup: node,\n context: groupContext,\n items: radioItems,\n bestScore: 1,\n })\n }\n continue\n }\n\n if (node.hidden) {\n continue\n }\n\n // Ungrouped item/submenu\n const context: RowRenderContext = {\n search: null,\n breadcrumbs: [],\n isDeepSearchResult: false,\n highlighted: node.id === highlightedId,\n disabled: node.disabled ?? false,\n group: null,\n }\n\n result.push({ node, context })\n }\n\n return result\n}\n\n// ============================================================================\n// Full Pipeline\n// ============================================================================\n\nexport interface FilterNodesOptions {\n /** The search query */\n query: string\n /** The node definitions to filter */\n nodes: NodeDef[]\n /** Currently highlighted node ID */\n highlightedId: string | null\n /** Whether deep search is enabled */\n deepSearch?: boolean\n /** Minimum query length for deep search */\n minLength?: number\n /** How groups behave during search (only applies when searching, not browse mode) */\n groupSearchBehavior?: GroupBehavior\n /** How radio groups behave during search */\n radioGroupSearchBehavior?: RadioGroupBehavior\n /** Whether to sort groups by best score */\n sortGroups?: boolean\n}\n\n/**\n * Filters nodes with 'flatten' group behavior.\n * Groups are invisible, items shown in flat list.\n * Radio group behavior is controlled by radioGroupSearchBehavior.\n */\nfunction filterNodesFlatten(options: FilterNodesOptions): {\n displayNodes: DisplayNode[]\n isDeepSearching: boolean\n} {\n const {\n query,\n nodes,\n highlightedId,\n deepSearch = true,\n minLength = 0,\n radioGroupSearchBehavior = 'preserve',\n } = options\n\n // Determine if deep search should activate\n const shouldDeepSearch = deepSearch && query.length >= minLength\n\n // Flatten nodes\n const flattened = flattenNodes(nodes, { deep: shouldDeepSearch })\n\n // For preserve-show-all, we need to track ALL radio group items before scoring\n // Maps radio group ID -> all flattened nodes for that group\n const allRadioGroupItems = new Map<\n string,\n {\n radioGroupDef: RadioGroupDef\n items: FlattenedNode[]\n breadcrumbs: BreadcrumbNode[]\n }\n >()\n\n if (radioGroupSearchBehavior === 'preserve-show-all') {\n for (const flatNode of flattened) {\n if (flatNode.radioGroup) {\n const existing = allRadioGroupItems.get(flatNode.radioGroup.id)\n if (existing) {\n existing.items.push(flatNode)\n } else {\n allRadioGroupItems.set(flatNode.radioGroup.id, {\n radioGroupDef: flatNode.radioGroup.radioGroupDef,\n items: [flatNode],\n breadcrumbs: flatNode.breadcrumbs,\n })\n }\n }\n }\n }\n\n // Score nodes\n const scored = scoreNodes(flattened, query)\n\n // Separate radio group items from regular items\n const radioGroupItems = new Map<\n string,\n {\n radioGroupDef: RadioGroupDef\n items: ScoredNode[]\n breadcrumbs: BreadcrumbNode[]\n }\n >()\n const regularItems: ScoredNode[] = []\n\n for (const scoredNode of scored) {\n if (scoredNode.radioGroup) {\n // For 'flatten' behavior, treat radio items as regular items\n if (radioGroupSearchBehavior === 'flatten') {\n regularItems.push(scoredNode)\n } else {\n // For 'preserve' and 'preserve-show-all', group them\n const existing = radioGroupItems.get(scoredNode.radioGroup.id)\n if (existing) {\n existing.items.push(scoredNode)\n } else {\n radioGroupItems.set(scoredNode.radioGroup.id, {\n radioGroupDef: scoredNode.radioGroup.radioGroupDef,\n items: [scoredNode],\n breadcrumbs: scoredNode.breadcrumbs,\n })\n }\n }\n } else {\n regularItems.push(scoredNode)\n }\n }\n\n // Sort regular items by score\n const sorted = sortByScore(regularItems)\n\n // Partition (items first, then submenus)\n const partitioned = partitionByKind(sorted)\n\n // Deduplicate\n const unique = deduplicateNodes(partitioned)\n\n // Build display nodes for regular items\n const regularDisplayNodes: DisplayRowNode[] = buildDisplayRowNodes(\n unique,\n query,\n highlightedId,\n )\n\n // Build display nodes for radio groups\n const radioGroupDisplayNodes: DisplayRadioGroupNode[] = []\n\n if (radioGroupSearchBehavior !== 'flatten') {\n for (const [\n radioGroupId,\n { radioGroupDef, items: matchingItems, breadcrumbs },\n ] of radioGroupItems) {\n let itemsToDisplay: ScoredNode[]\n\n if (radioGroupSearchBehavior === 'preserve-show-all') {\n // Include ALL items from this radio group, not just matching ones\n const allItems = allRadioGroupItems.get(radioGroupId)\n if (allItems) {\n // Create scored nodes for all items, using 0 for non-matching\n const matchingIds = new Set(matchingItems.map((item) => item.node.id))\n const matchingScores = new Map(\n matchingItems.map((item) => [item.node.id, item.score]),\n )\n\n itemsToDisplay = allItems.items.map((flatNode) => ({\n node: flatNode.node,\n score: matchingScores.get(flatNode.node.id) ?? 0,\n breadcrumbs: flatNode.breadcrumbs,\n group: flatNode.group,\n radioGroup: flatNode.radioGroup,\n }))\n } else {\n itemsToDisplay = matchingItems\n }\n } else {\n // 'preserve' - only show matching items\n itemsToDisplay = matchingItems\n }\n\n // Sort items: matching items first (by score), then non-matching\n itemsToDisplay.sort((a, b) => b.score - a.score)\n\n const bestScore = Math.max(...itemsToDisplay.map((item) => item.score), 0)\n const isDeepSearchResult = breadcrumbs.length > 0\n\n const groupContext: GroupRenderContext = {\n search: query ? { query, bestScore } : null,\n matchCount: matchingItems.length,\n breadcrumbs,\n isDeepSearchResult,\n }\n\n radioGroupDisplayNodes.push({\n kind: 'radio-group',\n radioGroup: radioGroupDef,\n context: groupContext,\n items: itemsToDisplay.map((item) =>\n buildDisplayRowNode(item, query, highlightedId),\n ),\n bestScore,\n })\n }\n }\n\n // Merge regular items and radio groups, sorted by score\n type SortableNode = { node: DisplayNode; score: number }\n\n const allNodes: SortableNode[] = [\n ...regularDisplayNodes.map((r) => ({\n node: r as DisplayNode,\n score: r.context.search?.score ?? 0,\n })),\n ...radioGroupDisplayNodes.map((r) => ({\n node: r as DisplayNode,\n score: r.bestScore,\n })),\n ]\n\n allNodes.sort((a, b) => b.score - a.score)\n\n return {\n displayNodes: allNodes.map((n) => n.node),\n isDeepSearching: shouldDeepSearch,\n }\n}\n\n/**\n * Filters nodes with 'preserve' group behavior.\n * Groups are shown as containers with their matching items.\n * Groups and ungrouped items are mixed by score.\n * Radio group behavior is controlled by radioGroupSearchBehavior.\n */\nfunction filterNodesPreserve(options: FilterNodesOptions): {\n displayNodes: DisplayNode[]\n isDeepSearching: boolean\n} {\n const {\n query,\n nodes,\n highlightedId,\n deepSearch = true,\n minLength = 0,\n sortGroups = true,\n radioGroupSearchBehavior = 'preserve',\n } = options\n\n // Determine if deep search should activate\n const shouldDeepSearch = deepSearch && query.length >= minLength\n\n // Flatten nodes (tracking group and radio group membership)\n const flattened = flattenNodes(nodes, { deep: shouldDeepSearch })\n\n // For preserve-show-all, we need to track ALL radio group items before scoring\n const allRadioGroupItems = new Map<\n string,\n {\n radioGroupDef: RadioGroupDef\n items: FlattenedNode[]\n breadcrumbs: BreadcrumbNode[]\n }\n >()\n\n if (radioGroupSearchBehavior === 'preserve-show-all') {\n for (const flatNode of flattened) {\n if (flatNode.radioGroup) {\n const existing = allRadioGroupItems.get(flatNode.radioGroup.id)\n if (existing) {\n existing.items.push(flatNode)\n } else {\n allRadioGroupItems.set(flatNode.radioGroup.id, {\n radioGroupDef: flatNode.radioGroup.radioGroupDef,\n items: [flatNode],\n breadcrumbs: flatNode.breadcrumbs,\n })\n }\n }\n }\n }\n\n // Score nodes\n const scored = scoreNodes(flattened, query)\n\n // Partition into groups, radio groups, and ungrouped\n const groupedItems = new Map<\n string,\n { groupDef: GroupDef; items: ScoredNode[]; breadcrumbs: BreadcrumbNode[] }\n >()\n const radioGroupedItems = new Map<\n string,\n {\n radioGroupDef: RadioGroupDef\n items: ScoredNode[]\n breadcrumbs: BreadcrumbNode[]\n }\n >()\n const ungroupedItems: ScoredNode[] = []\n\n for (const scoredNode of scored) {\n if (scoredNode.radioGroup) {\n // For 'flatten' behavior, treat radio items as ungrouped\n if (radioGroupSearchBehavior === 'flatten') {\n ungroupedItems.push(scoredNode)\n } else {\n const existing = radioGroupedItems.get(scoredNode.radioGroup.id)\n if (existing) {\n existing.items.push(scoredNode)\n } else {\n radioGroupedItems.set(scoredNode.radioGroup.id, {\n radioGroupDef: scoredNode.radioGroup.radioGroupDef,\n items: [scoredNode],\n breadcrumbs: scoredNode.breadcrumbs,\n })\n }\n }\n } else if (scoredNode.group) {\n const existing = groupedItems.get(scoredNode.group.id)\n if (existing) {\n existing.items.push(scoredNode)\n } else {\n groupedItems.set(scoredNode.group.id, {\n groupDef: scoredNode.group.groupDef,\n items: [scoredNode],\n breadcrumbs: scoredNode.breadcrumbs,\n })\n }\n } else {\n ungroupedItems.push(scoredNode)\n }\n }\n\n // Build display nodes for groups (with items sorted by score)\n const groupDisplayNodes: DisplayGroupNode[] = []\n for (const [_groupId, { groupDef, items, breadcrumbs }] of groupedItems) {\n // Sort items within group by score\n items.sort((a, b) => b.score - a.score)\n\n const bestScore = items[0]?.score ?? 0\n const isDeepSearchResult = breadcrumbs.length > 0\n\n const groupContext: GroupRenderContext = {\n search: query ? { query, bestScore } : null,\n matchCount: items.length,\n breadcrumbs,\n isDeepSearchResult,\n }\n\n groupDisplayNodes.push({\n kind: 'group',\n group: groupDef,\n context: groupContext,\n items: items.map((item) =>\n buildDisplayRowNode(item, query, highlightedId),\n ),\n bestScore,\n })\n }\n\n // Build display nodes for radio groups\n const radioGroupDisplayNodes: DisplayRadioGroupNode[] = []\n\n if (radioGroupSearchBehavior !== 'flatten') {\n for (const [\n radioGroupId,\n { radioGroupDef, items: matchingItems, breadcrumbs },\n ] of radioGroupedItems) {\n let itemsToDisplay: ScoredNode[]\n\n if (radioGroupSearchBehavior === 'preserve-show-all') {\n // Include ALL items from this radio group, not just matching ones\n const allItems = allRadioGroupItems.get(radioGroupId)\n if (allItems) {\n // Create scored nodes for all items, using 0 for non-matching\n const matchingScores = new Map(\n matchingItems.map((item) => [item.node.id, item.score]),\n )\n\n itemsToDisplay = allItems.items.map((flatNode) => ({\n node: flatNode.node,\n score: matchingScores.get(flatNode.node.id) ?? 0,\n breadcrumbs: flatNode.breadcrumbs,\n group: flatNode.group,\n radioGroup: flatNode.radioGroup,\n }))\n } else {\n itemsToDisplay = matchingItems\n }\n } else {\n // 'preserve' - only show matching items\n itemsToDisplay = matchingItems\n }\n\n // Sort items: matching items first (by score), then non-matching\n itemsToDisplay.sort((a, b) => b.score - a.score)\n\n const bestScore = Math.max(...itemsToDisplay.map((item) => item.score), 0)\n const isDeepSearchResult = breadcrumbs.length > 0\n\n const groupContext: GroupRenderContext = {\n search: query ? { query, bestScore } : null,\n matchCount: matchingItems.length,\n breadcrumbs,\n isDeepSearchResult,\n }\n\n radioGroupDisplayNodes.push({\n kind: 'radio-group',\n radioGroup: radioGroupDef,\n context: groupContext,\n items: itemsToDisplay.map((item) =>\n buildDisplayRowNode(item, query, highlightedId),\n ),\n bestScore,\n })\n }\n }\n\n // Build display nodes for ungrouped items\n const ungroupedDisplayNodes: DisplayRowNode[] = ungroupedItems\n .sort((a, b) => b.score - a.score)\n .map((item) => buildDisplayRowNode(item, query, highlightedId))\n\n // Merge groups, radio groups, and ungrouped items, sorted by best score\n type SortableNode = { node: DisplayNode; score: number }\n\n const allNodes: SortableNode[] = [\n ...groupDisplayNodes.map((g) => ({\n node: g as DisplayNode,\n score: g.bestScore,\n })),\n ...radioGroupDisplayNodes.map((r) => ({\n node: r as DisplayNode,\n score: r.bestScore,\n })),\n ...ungroupedDisplayNodes.map((r) => ({\n node: r as DisplayNode,\n score: r.context.search?.score ?? 0,\n })),\n ]\n\n if (sortGroups) {\n allNodes.sort((a, b) => b.score - a.score)\n }\n\n return {\n displayNodes: allNodes.map((n) => n.node),\n isDeepSearching: shouldDeepSearch,\n }\n}\n\n/**\n * Main filtering pipeline.\n * Handles both browse mode and search mode (shallow and deep).\n * Respects groupSearchBehavior configuration (only applies during search).\n * Note: Radio groups are ALWAYS preserved regardless of groupSearchBehavior.\n */\nexport function filterNodes(options: FilterNodesOptions): {\n displayNodes: DisplayNode[]\n isDeepSearching: boolean\n} {\n const {\n query,\n nodes,\n highlightedId,\n groupSearchBehavior = 'preserve',\n } = options\n\n // Browse mode - no query\n // Always preserve groups in browse mode (groupSearchBehavior only affects search)\n if (!query) {\n return {\n displayNodes: getBrowseNodesPreserve(nodes, highlightedId),\n isDeepSearching: false,\n }\n }\n\n // Search mode - dispatch based on group search behavior\n if (groupSearchBehavior === 'preserve') {\n return filterNodesPreserve(options)\n }\n\n return filterNodesFlatten(options)\n}\n\n// ============================================================================\n// Get Navigable IDs\n// ============================================================================\n\n/**\n * Gets the IDs of all navigable (non-disabled) nodes.\n * Handles row nodes, group nodes, and radio group nodes (extracts item IDs).\n * Separators are skipped as they're not navigable.\n * Used for keyboard navigation.\n *\n * Note: Uses `node.id ?? node.value` as the identifier. For proper ID handling\n * with custom getItemId functions, use `getOrderedItemIds` from DataList instead.\n */\nexport function getNavigableIds(displayNodes: DisplayNode[]): string[] {\n const ids: string[] = []\n\n for (const node of displayNodes) {\n if (isDisplayGroupNode(node)) {\n // Add IDs of items within the group\n for (const item of node.items) {\n if (!item.node.disabled) {\n ids.push(item.node.id ?? item.node.value)\n }\n }\n } else if (isDisplayRadioGroupNode(node)) {\n // Add IDs of items within the radio group\n for (const item of node.items) {\n if (!item.node.disabled) {\n ids.push(item.node.id ?? item.node.value)\n }\n }\n } else if (isDisplaySeparatorNode(node)) {\n // Separators are not navigable\n } else {\n // Row node (item, checkbox item, or submenu)\n if (!node.node.disabled) {\n ids.push(node.node.id ?? node.node.value)\n }\n }\n }\n\n return ids\n}\n\n/**\n * Gets the first navigable node ID.\n */\nexport function getFirstNavigableId(\n displayNodes: DisplayNode[],\n): string | null {\n const ids = getNavigableIds(displayNodes)\n return ids[0] ?? null\n}\n\n// ============================================================================\n// Async Node Collection & Merging\n// ============================================================================\n\n/**\n * Info about an async submenu for registration with coordinator.\n */\nexport interface AsyncSubmenuInfo {\n /** Unique identifier (uses node value and breadcrumbs) */\n id: string\n /** Breadcrumbs path to this submenu */\n breadcrumbs: string[]\n /** The submenu node definition */\n node: SubmenuDef\n /** The async configuration */\n config: AsyncNodesConfig\n}\n\n/**\n * Collects all async submenus from a node tree.\n * Recursively traverses groups and submenus to find all async configurations.\n */\nexport function collectAsyncSubmenus(\n nodes: NodeDef[],\n breadcrumbs: string[] = [],\n): AsyncSubmenuInfo[] {\n const result: AsyncSubmenuInfo[] = []\n\n for (const node of nodes) {\n if (node.kind === 'separator') {\n continue\n }\n\n if (node.kind === 'group') {\n // Recurse into groups\n result.push(...collectAsyncSubmenus(node.nodes, breadcrumbs))\n continue\n }\n\n if (node.kind === 'radio-group') {\n if (node.hidden) continue\n // Recurse into radio groups\n result.push(...collectAsyncSubmenus(node.nodes, breadcrumbs))\n continue\n }\n\n if (node.kind === 'submenu') {\n if (node.hidden) continue\n\n // If this submenu has async nodes, add it to the result\n if (node.asyncNodes) {\n const id = [...breadcrumbs, normalizeValue(node.value)].join('.')\n result.push({\n id,\n breadcrumbs,\n node,\n config: node.asyncNodes,\n })\n }\n\n // Recurse into submenu's static nodes\n if (node.nodes) {\n const childBreadcrumbs = [...breadcrumbs, normalizeValue(node.value)]\n result.push(...collectAsyncSubmenus(node.nodes, childBreadcrumbs))\n }\n }\n }\n\n return result\n}\n\n/**\n * Merges async nodes into a submenu's node list.\n * Static nodes come first, async nodes are appended.\n */\nexport function mergeSubmenuNodes(\n staticNodes: NodeDef[] | undefined,\n asyncNodes: NodeDef[] | undefined,\n): NodeDef[] {\n const static_ = staticNodes ?? []\n const async_ = asyncNodes ?? []\n return [...static_, ...async_]\n}\n\n/**\n * Async data from the coordinator ready for merging.\n */\ninterface AsyncNodeData {\n id: string\n breadcrumbs: string[]\n nodes: NodeDef[]\n}\n\n/**\n * Creates a merged content tree with async nodes injected at their proper locations.\n * This function modifies the tree to include async nodes where they belong.\n */\nexport function mergeAsyncNodesIntoTree(\n staticContent: NodeDef[],\n asyncData: AsyncNodeData[],\n): NodeDef[] {\n // If no async data, return static content as-is\n if (asyncData.length === 0) {\n return staticContent\n }\n\n // Build a map of async data by breadcrumb path\n const asyncMap = new Map<string, NodeDef[]>()\n for (const data of asyncData) {\n // The id is the full path including the submenu value\n // We need to find the parent path to inject into\n asyncMap.set(data.id, data.nodes)\n }\n\n // Recursively merge async nodes into the tree\n function mergeRecursive(\n nodes: NodeDef[],\n currentBreadcrumbs: string[],\n ): NodeDef[] {\n return nodes.map((node) => {\n if (node.kind === 'submenu') {\n const submenuPath = [\n ...currentBreadcrumbs,\n normalizeValue(node.value),\n ].join('.')\n const asyncNodes = asyncMap.get(submenuPath)\n\n // Get merged child nodes\n const mergedStaticChildren = node.nodes\n ? mergeRecursive(node.nodes, [\n ...currentBreadcrumbs,\n normalizeValue(node.value),\n ])\n : undefined\n\n // If there are async nodes for this submenu, merge them\n if (asyncNodes) {\n return {\n ...node,\n nodes: mergeSubmenuNodes(mergedStaticChildren, asyncNodes),\n }\n }\n\n // If children were modified, return updated node\n if (mergedStaticChildren !== node.nodes) {\n return { ...node, nodes: mergedStaticChildren }\n }\n }\n\n if (node.kind === 'group') {\n const mergedChildren = mergeRecursive(node.nodes, currentBreadcrumbs)\n if (mergedChildren !== node.nodes) {\n return { ...node, nodes: mergedChildren }\n }\n }\n\n // Radio groups contain static RadioItemDef[] and don't support async loading,\n // so we skip processing them in the async merge\n if (node.kind === 'radio-group') {\n return node\n }\n\n return node\n })\n }\n\n return mergeRecursive(staticContent, [])\n}\n\n/**\n * Checks if deep search should include this async config.\n */\nexport function shouldIncludeInDeepSearch(config: AsyncNodesConfig): boolean {\n // Default behavior:\n // - Static loaders: include by default\n // - Query loaders: include by default\n if (config.includeInDeepSearch !== undefined) {\n return config.includeInDeepSearch\n }\n return true\n}\n\n/**\n * Checks if an async loader should be rendered eagerly.\n * Eager loaders mount when the root menu opens (before their submenu is opened).\n */\nexport function shouldLoadEagerly(config: AsyncNodesConfig): boolean {\n // Both static and query loaders use explicit loadStrategy\n return config.loadStrategy === 'eager'\n}\n","'use client'\n\nimport * as React from 'react'\nimport { PopupMenuSurface } from '../components/surface/surface.js'\nimport { usePopupMenuContext } from '../contexts/popup-menu-context.js'\nimport { DataSurfaceContext, type DataSurfaceContextValue } from './context.js'\nimport type { DataSurfaceProps, DeepSearchConfig } from './types.js'\nimport { defaultGetQualifiedRowId } from './utils.js'\n\n// ============================================================================\n// DataSurface Component\n// ============================================================================\n\nexport interface PopupMenuDataSurfaceProps extends DataSurfaceProps {\n /** Custom class name */\n className?: string\n /** Custom styles */\n style?: React.CSSProperties\n /** Render function for custom element */\n render?: React.ReactElement\n}\n\n/**\n * DataSurface provides deep search functionality for popup menus.\n * It wraps the standard Surface and adds data-first search capabilities.\n *\n * Place inside PopupMenu.Popup to enable deep search functionality.\n * Renders a `<div>` element.\n */\nexport const PopupMenuDataSurface = React.forwardRef<\n HTMLDivElement,\n PopupMenuDataSurface.Props\n>(function PopupMenuDataSurface(props, forwardedRef) {\n const {\n content,\n asyncContent,\n deepSearch = true,\n filter,\n search: searchProp,\n onSearchChange,\n defaultSearch = '',\n loop = true,\n autoHighlightFirst = true,\n clearSearchOnClose = true,\n getQualifiedRowId: getQualifiedRowIdProp,\n className,\n style,\n render,\n children,\n } = props\n\n // Get getQualifiedRowId from popup menu context (set at Root level), or use prop, or use default\n const popupMenuContext = usePopupMenuContext()\n const getQualifiedRowId =\n getQualifiedRowIdProp ??\n popupMenuContext.getQualifiedRowId ??\n defaultGetQualifiedRowId\n\n // Parse deep search config\n const deepSearchConfig: DeepSearchConfig = React.useMemo(() => {\n if (typeof deepSearch === 'boolean') {\n return {\n enabled: deepSearch,\n minLength: 0,\n groupSearchBehavior: 'preserve',\n radioGroupSearchBehavior: 'preserve',\n sortGroups: true,\n }\n }\n return {\n enabled: deepSearch.enabled ?? true,\n minLength: deepSearch.minLength ?? 0,\n groupSearchBehavior: deepSearch.groupSearchBehavior ?? 'preserve',\n radioGroupSearchBehavior:\n deepSearch.radioGroupSearchBehavior ?? 'preserve',\n sortGroups: deepSearch.sortGroups ?? true,\n }\n }, [deepSearch])\n\n // Generate stable list ID\n const listId = React.useId()\n\n // Create DataSurface context value\n // Note: The actual filtering happens in DataList which has access to the store's search\n const contextValue: DataSurfaceContextValue = React.useMemo(\n () => ({\n content: content ?? [],\n asyncContent,\n deepSearchConfig,\n listId,\n getQualifiedRowId,\n }),\n [content, asyncContent, deepSearchConfig, listId, getQualifiedRowId],\n )\n\n return (\n <DataSurfaceContext.Provider value={contextValue}>\n <PopupMenuSurface\n ref={forwardedRef}\n // Disable Surface's built-in filtering - DataList handles filtering via filterNodes()\n filter={false}\n search={searchProp}\n onSearchChange={onSearchChange}\n defaultSearch={defaultSearch}\n loop={loop}\n autoHighlightFirst={autoHighlightFirst}\n clearSearchOnClose={clearSearchOnClose}\n className={className}\n style={style}\n render={render}\n >\n {children}\n </PopupMenuSurface>\n </DataSurfaceContext.Provider>\n )\n})\n\nexport namespace PopupMenuDataSurface {\n export interface Props extends PopupMenuDataSurfaceProps {}\n}\n"],"mappings":"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","names":["popup_menu_exports","__export","AimGuardCtx","AimGuardProvider","AsyncMenuCoordinatorContext","AsyncMenuCoordinatorProvider","CheckboxItemContext","ComponentNameContext","DataSurfaceContext","FocusOwnerContext","FocusOwnerStore","OpenChainContext","OpenChainStore","PopupMenuArrow","PopupMenuArrowDataAttributes","PopupMenuBackdrop","PopupMenuBackdropDataAttributes","PopupMenuCheckboxItem","PopupMenuCheckboxItemDataAttributes","PopupMenuCheckboxItemIndicator","PopupMenuContext","PopupMenuInput","PopupMenuDataList","PopupMenuDataSurface","PopupMenuEmpty","PopupMenuGroup","PopupMenuGroupLabel","PopupMenuIcon","PopupMenuIconDataAttributes","PopupMenuItem","PopupMenuItemDataAttributes","PopupMenuList","PopupMenuListCssVars","PopupMenuListDataAttributes","PopupMenuPopup","PopupMenuPopupDataAttributes","PopupMenuPortal","PopupMenuPositioner","PopupMenuPositionerCssVars","PopupMenuPositionerDataAttributes","PopupMenuProviders","PopupMenuRadioGroup","PopupMenuRadioGroupDataAttributes","PopupMenuRadioGroupValue","PopupMenuRadioItem","PopupMenuRadioItemDataAttributes","PopupMenuRadioItemIndicator","PopupMenuScrollArrow","PopupMenuScrollArrowDataAttributes","PopupMenuScrollDownArrow","PopupMenuScrollUpArrow","PopupMenuSeparator","PopupMenuShortcut","PopupMenuShortcutDataAttributes","PopupMenuSubmenuRoot","PopupMenuSubmenuTrigger","PopupMenuSubmenuTriggerDataAttributes","PopupMenuSubmenuTriggerIndicator","PopupMenuSurface","PopupSurfaceIdContext","RadioGroupContext","RadioItemContext","SubmenuContext","buildDisplayRowNodes","collectAsyncSubmenus","deduplicateNodes","defaultGetQualifiedRowId","defineRadioGroup","filterNodes","flattenNodes","getBrowseNodesFlatten","getBrowseNodesPreserve","getFirstNavigableId","getNavigableIds","getSlotAttribute","getSmoothedHeading","isCheckboxItemDef","isDisplayGroupNode","isDisplayRadioGroupNode","isDisplayRowNode","isDisplaySeparatorNode","isGroupDef","isItemDef","isRadioGroupDef","isRadioItemDef","isSeparatorDef","isSubmenuDef","mergeAsyncNodesIntoTree","mergeSubmenuNodes","partitionByKind","resolveAnchorSide","scoreNodes","shouldIncludeInDeepSearch","shouldLoadEagerly","sortByScore","useAimGuard","useAsyncMenuCoordinator","useCheckboxItemContext","useComponentName","useDataSurfaceContext","useFocusOwner","useMaybeAsyncMenuCoordinator","useMaybeComponentName","useMaybeDataSurfaceContext","useMaybeFocusOwner","useMaybeOpenChain","useMaybePopupMenuContext","useMaybeSubmenuContext","useMouseTrail","useOpenChain","usePopupMenuContext","usePopupMenuItem","usePopupMenuKeyboard","usePopupMenuRoot","usePopupSurfaceId","useRadioGroupContext","useRadioItemContext","useSubmenuContext","willHitSubmenu","__toCommonJS","React","ComponentNameContext","useComponentName","context","useMaybeComponentName","getSlotAttribute","componentName","partName","React","FocusOwnerContext","useFocusOwner","context","useMaybeFocusOwner","React","OpenChainContext","useOpenChain","context","useMaybeOpenChain","React","PopupMenuContext","usePopupMenuContext","context","useMaybePopupMenuContext","React","PopupSurfaceIdContext","usePopupSurfaceId","React","SubmenuContext","useSubmenuContext","context","useMaybeSubmenuContext","React","import_jsx_runtime","AimGuardCtx","useAimGuard","AimGuardProvider","children","aimGuardActive","setAimGuardActive","guardedTriggerId","setGuardedTriggerId","guardedDepth","setGuardedDepth","guardedSubmenuSurfaceId","setGuardedSubmenuSurfaceId","aimGuardActiveRef","guardedTriggerIdRef","guardedDepthRef","guardedSubmenuSurfaceIdRef","guardTimerRef","clearAimGuard","activateAimGuard","triggerId","depth","submenuSurfaceId","timeoutMs","isGuardBlocking","rowId","value","import_store","selectors","state","surfaceId","FocusOwnerStore","id","import_store","selectors","state","surfaceId","depth","OpenChainStore","newChain","id","resolveAnchorSide","rect","tRect","mx","tx","dL","dR","getSmoothedHeading","trail","exitX","exitY","anchor","dx","dy","n","i","x1","y1","x2","y2","ty","edgeX","edgeCy","willHitSubmenu","heading","triggerRect","t","yAtEdge","baseBand","extra","top","bottom","React","useMouseTrail","n","trailRef","onMove","e","a","React","reason_parts_exports","__export","auto","clearPress","closePress","escapeKey","focusOut","imperativeAction","inputChange","inputClear","itemKeyboardSelect","itemPress","keyboard","listNavigation","none","outsidePress","pointer","siblingOpen","submenuTrigger","triggerContextMenu","triggerFocus","triggerHover","triggerPress","createChangeEventDetails","reason","event","trigger","customProperties","canceled","propagationAllowed","createGenericEventDetails","React","GroupContext","useGroupContext","React","ItemContext","useItemContext","context","React","ListboxContext","useListboxContext","context","useMaybeListboxContext","React","RowWidthContext","useMaybeRowWidthContext","RowWidthContext","React","SurfaceContext","useSurfaceContext","context","React","normalizeValue","value","slugify","useListboxItem","params","idProp","valueProp","keywords","disabled","forceMount","shortcut","isSubmenuTrigger","onSelect","closeOnClick","onAfterSelect","children","aimGuard","store","useSurfaceContext","groupContext","useGroupContext","depth","useListboxContext","ref","inferredValue","setInferredValue","textContent","registrationId","normalizeValue","generatedDomId","domId","normalizedKeywords","k","keywordsKey","rowWidthContext","useMaybeRowWidthContext","search","isHighlighted","score","filterDisabled","hasSearch","isVisible","handleClick","event","handlePointerDown","handlePointerMove","aimGuardActiveRef","guardedDepthRef","contextValue","registerSelect","handler","handlers","React","useListboxKeyboard","params","store","surfaceId","enabled","onKeyDown","onSelect","closeAll","focusOwner","depth","submenuContext","enableTypeToSearch","skipFocusOwnerCheck","focusOwnerIsOwner","isOwner","event","hideUntilActive","inputActive","shortcutItemId","item","selectedId","hasActiveSearch","itemId","React","DEBUG_ROW_WIDTH","DEBUG_FREEZE_MEASUREMENT","debugLog","args","px","n","useStickyRowWidth","options","listRef","targetRef","maxWidth","enabled","getTargetElement","maxSeenRef","readQueue","writeQueue","scheduled","measuredIds","applyVar","width","el","capped","schedule","measurements","foundNewMax","element","id","prevWidth","prevMaxWidth","w","computed","rect","write","queueMeasurement","resetMeasurements","prevMax","prevCount","container","rafId","ro","entries","import_store","import_useRefWithInit","IS_GAP_REGEXP","COUNT_GAPS_REGEXP","IS_SPACE_REGEXP","COUNT_SPACE_REGEXP","commandScoreInner","string","abbreviation","lowerString","lowerAbbreviation","stringIndex","abbreviationIndex","memoizedResults","memoizeKey","abbreviationChar","index","highScore","score","transposedScore","wordBreaks","spaceBreaks","formatInput","commandScore","keywords","fullString","defaultFilter","selectors","state","itemId","groupId","ListboxStore","_ListboxStore","initialState","context","defaultContext","commandScore","createInitialState","open","deferInputHide","search","prevSearch","reason","reason_parts_exports","event","eventDetails","createChangeEventDetails","id","cause","onHighlightChange","index","createGenericEventDetails","refs","listEl","itemEl","hasInput","active","enabled","virtualized","items","prevItems","prevFirstItem","item","firstItemChanged","firstRegisteredItem","orderedItems","callback","ref","x","y","last","dx","dy","virtualItems","registration","existing","groupItems","key","onSelect","onOpen","onClose","exceptId","visibleIds","nextIndex","nextId","prevIndex","prevId","score","autoHighlight","value","highlightedId","result","filteredItems","unregisteredItems","options","forceFirst","newSearch","optionsPrevSearch","effectiveSearch","searchChanged","currentHighlight","filter","shouldForceFirst","isCurrentValid","isVisible","virtualItem","v","isDisabled","isRegistered","inVirtualItems","newHighlightId","groups","visibleGroups","filteredCount","_","filterFn","externalStore","usePopupMenuRoot","params","onOpenChange","defaultOpen","virtualized","itemsProp","onHighlightChange","closeOnOutsidePress","outsidePointerEventRef","stableOnOpenChange","open","eventDetails","reason_parts_exports","pointerEvent","convertedDetails","createChangeEventDetails","store","ListboxStore","isOpen","focusOwnerStoreRef","FocusOwnerStore","focusOwnerStore","openChainStoreRef","OpenChainStore","openChainStore","surfaceRegistryRef","registerSurface","depth","setOpen","id","closeAll","reason","event","surfaces","a","b","surface","closeAllRef","handlePointerDown","target","isInsidePopup","isInsideTrigger","handleOpenChange","newOpen","virtualization","PopupMenuArrowDataAttributes","import_popover","React","import_jsx_runtime","PopupMenuArrow","props","forwardedRef","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","PopupMenuBackdropDataAttributes","import_popover","React","import_jsx_runtime","PopupMenuBackdrop","props","forwardedRef","showOnProp","rest","submenuContext","useMaybeSubmenuContext","openChainStore","useOpenChain","focusOwnerStore","useFocusOwner","isSubmenu","surfaceId","showOn","isInOpenChain","isLastInChain","isFocusOwner","shouldShow","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","style","PopupMenuPopupDataAttributes","import_popover","React","React","ComboboxContext","useMaybeComboboxContext","ComboboxContext","import_jsx_runtime","PopupMenuPopup","props","forwardedRef","children","classNameProp","rest","submenuContext","useMaybeSubmenuContext","clearAimGuard","aimGuardActiveRef","guardedSubmenuSurfaceIdRef","useAimGuard","focusOwnerStore","useFocusOwner","openChainStore","useOpenChain","depth","useMaybePopupMenuContext","comboboxContext","useMaybeComboboxContext","generatedSurfaceId","surfaceId","openTimeRef","isFocused","hasOpenSubmenu","popupRef","combinedRef","node","handlePointerMove","handleFocusTransferOnMove","event","target","targetElement","closestPopup","initialFocus","finalFocus","isInputEmbedded","isSubmenu","className","baseState","extendedState","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","PopupSurfaceIdContext","import_popover","PopupMenuPortal","PopupMenuPositionerCssVars","PopupMenuPositionerDataAttributes","import_popover","React","import_jsx_runtime","getDefaultCollisionAvoidance","side","isHorizontalSide","PopupMenuPositioner","props","ref","sideProp","alignProp","alignOffsetProp","collisionAvoidanceProp","virtualAnchorProp","styleProp","rest","depth","contextVirtualAnchor","menuType","usePopupMenuContext","submenuContext","useMaybeSubmenuContext","listStartOffsetRef","hasMeasuredRef","forceUpdate","x","isSubmenu","virtualAnchor","align","useListStartAlign","baseUIAlign","isOpen","measureListStartOffset","contentEl","contentRect","listEl","listRect","listStyles","listPaddingTop","offset","effectiveAlignOffset","collisionAvoidance","anchorProps","style","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","React","import_jsx_runtime","PopupMenuProviders","props","store","focusOwnerStore","openChainStore","depth","closeAll","registerSurface","virtualization","virtualAnchor","menuType","closeOnOutsidePress","getQualifiedRowId","componentName","children","popupMenuContextValue","listboxContextValue","ComponentNameContext","PopupMenuContext","ListboxContext","AimGuardProvider","FocusOwnerContext","OpenChainContext","React","usePopupMenuItem","params","closeOnClick","rest","aimGuardActiveRef","guardedDepthRef","useAimGuard","closeAll","useListboxContext","aimGuard","handleAfterSelect","itemId","useListboxItem","React","usePopupMenuKeyboard","params","store","surfaceId","focusOwnerStore","depth","submenuContext","enabled","enableTypeToSearch","onKeyDown","closeAll","skipFocusOwnerCheck","submenuInterface","handleSelect","details","useListboxKeyboard","PopupMenuIconDataAttributes","import_use_render","React","resolveLabel","value","itemToStringLabel","label","stringifyAsValue","itemToStringValue","stateAttributesMapping","value","PopupMenuIconDataAttributes","PopupMenuIcon","props","forwardedRef","render","className","style","children","onPointerDown","onClick","rest","store","usePopupMenuContext","open","comboboxContext","useMaybeComboboxContext","state","handlePointerDown","event","handleClick","valueKey","stringifyAsValue","labelValue","resolveLabel","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_use_render","React","PopupMenuEmpty","props","forwardedRef","render","className","style","children","rest","store","useSurfaceContext","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","import_use_render","React","PopupMenuInput","props","forwardedRef","controlledValue","onValueChange","hideUntilActive","render","className","style","onKeyDown","rest","store","surfaceId","useSurfaceContext","depth","closeAll","useListboxContext","submenuContext","useMaybeSubmenuContext","focusOwnerStore","useFocusOwner","internalRef","search","highlightedId","listId","inputId","inputActive","pendingSearch","shouldRender","displayValue","handleChange","event","newValue","handleKeyDown","usePopupMenuKeyboard","state","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","import_use_render","React","PopupMenuListCssVars","PopupMenuListDataAttributes","import_jsx_runtime","PopupMenuList","props","forwardedRef","children","label","measureRowWidth","maxRowWidth","render","className","style","onKeyDown","onPointerDown","rest","store","surfaceId","useSurfaceContext","depth","closeAll","useListboxContext","submenuContext","useMaybeSubmenuContext","focusOwnerStore","useFocusOwner","comboboxContext","useMaybeComboboxContext","internalRef","popupRef","popup","queueMeasurement","resetMeasurements","useStickyRowWidth","rowWidthContextValue","search","filteredCount","hasInput","highlightedId","listId","shouldHandleKeyboard","handleKeyDown","usePopupMenuKeyboard","handlePointerDown","event","childrenState","renderedChildren","wrappedChildren","RowWidthContext","isInputEmbedded","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","PopupMenuScrollArrowDataAttributes","import_use_render","React","import_jsx_runtime","stateAttributesMapping","value","PopupMenuScrollArrowDataAttributes","PopupMenuScrollArrow","props","forwardedRef","direction","keepMounted","scrollSpeed","render","className","style","children","rest","store","useSurfaceContext","visible","setVisible","scrollingRef","rafRef","checkVisibility","list","atBottom","resizeObserver","filteredCount","startScrolling","scroll","delta","stopScrolling","state","shouldRender","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","event","PopupMenuScrollUpArrow","PopupMenuScrollDownArrow","import_use_render","import_useStableCallback","React","import_jsx_runtime","PopupMenuSurface","props","forwardedRef","filter","defaultFilter","searchProp","onSearchChange","defaultSearch","loop","autoHighlightFirst","clearSearchOnClose","skipAutoFocus","orderedItems","render","className","style","onPointerDown","onPointerMove","children","rest","store","depth","virtualization","useListboxContext","submenuContext","useMaybeSubmenuContext","focusOwnerStore","useFocusOwner","openTimeRef","listId","inputId","generatedSurfaceId","surfaceId","usePopupSurfaceId","isOwner","handleSearchChange","search","open","surfaceRef","timeoutId","input","list","focusTarget","contextValue","handlePointerDown","event","handlePointerMove","target","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","SurfaceContext","import_use_render","React","PopupMenuCheckboxItemDataAttributes","React","CheckboxItemContext","useCheckboxItemContext","context","import_jsx_runtime","stateAttributesMapping","value","PopupMenuCheckboxItem","props","forwardedRef","id","checkedProp","defaultChecked","onCheckedChange","keywords","disabled","onSelect","forceMount","closeOnClick","shortcut","render","className","style","onClick","onPointerDown","onPointerMove","children","rest","internalChecked","setInternalChecked","isControlled","checked","toggleChecked","reason","reason_parts_exports","event","newChecked","eventDetails","createChangeEventDetails","item","usePopupMenuItem","handleSelect","state","checkboxItemContextValue","handleClick","handlePointerDown","handlePointerMove","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","ItemContext","CheckboxItemContext","import_use_render","React","stateAttributesMapping","value","PopupMenuCheckboxItemIndicator","props","forwardedRef","keepMounted","render","className","style","children","rest","checked","highlighted","disabled","toggle","useCheckboxItemContext","state","shouldRender","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_use_render","React","PopupMenuItemDataAttributes","import_jsx_runtime","stateAttributesMapping","value","PopupMenuItem","props","forwardedRef","id","keywords","disabled","onSelect","forceMount","closeOnClick","shortcut","render","className","style","onClick","onPointerDown","onPointerMove","children","rest","item","usePopupMenuItem","state","handleClick","event","handlePointerDown","handlePointerMove","wrappedChildren","ItemContext","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_use_render","React","PopupMenuRadioGroupDataAttributes","React","RadioGroupContext","useRadioGroupContext","context","import_jsx_runtime","stateAttributesMapping","value","PopupMenuRadioGroup","props","forwardedRef","valueProp","defaultValue","onValueChange","disabled","forceMount","render","className","style","children","rest","store","useSurfaceContext","groupId","internalValue","setInternalValue","isControlled","setValue","newValue","reason","reason_parts_exports","event","eventDetails","createChangeEventDetails","isGroupVisible","isVisible","radioGroupContextValue","groupContextValue","state","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","RadioGroupContext","GroupContext","React","import_jsx_runtime","PopupMenuRadioGroupValue","props","value","onValueChange","disabled","children","setValue","newValue","reason","reason_parts_exports","event","eventDetails","createChangeEventDetails","contextValue","RadioGroupContext","import_use_render","React","PopupMenuRadioItemDataAttributes","React","RadioItemContext","useRadioItemContext","context","import_jsx_runtime","stateAttributesMapping","value","PopupMenuRadioItem","props","forwardedRef","id","keywords","disabledProp","onSelect","forceMount","closeOnClick","shortcut","render","className","style","onClick","onPointerDown","onPointerMove","children","rest","radioGroupContext","useRadioGroupContext","disabled","checked","item","usePopupMenuItem","handleSelect","state","radioItemContextValue","handleClick","event","handlePointerDown","handlePointerMove","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","ItemContext","RadioItemContext","import_use_render","React","stateAttributesMapping","value","PopupMenuRadioItemIndicator","props","forwardedRef","keepMounted","render","className","style","children","rest","checked","highlighted","disabled","useRadioItemContext","state","shouldRender","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_use_render","React","import_jsx_runtime","PopupMenuGroup","props","forwardedRef","forceMount","render","className","style","children","rest","store","useSurfaceContext","groupId","isGroupVisible","isVisible","groupContextValue","state","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","GroupContext","import_use_render","React","PopupMenuGroupLabel","props","forwardedRef","render","className","style","children","rest","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_use_render","React","PopupMenuSeparator","props","forwardedRef","alwaysRender","render","className","style","rest","store","useSurfaceContext","isHidden","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","import_use_render","React","PopupMenuShortcutDataAttributes","stateAttributesMapping","value","PopupMenuShortcut","props","forwardedRef","children","render","className","style","rest","shortcut","highlighted","useItemContext","state","renderedChildren","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_popover","import_useStableCallback","React","import_jsx_runtime","PopupMenuSubmenuRoot","props","openProp","onOpenChange","defaultOpen","closeRootOnEsc","virtualized","itemsProp","onHighlightChange","onOpenChangeCompleteProp","children","rest","parentListboxContext","useMaybeListboxContext","parentPopupMenuContext","useMaybePopupMenuContext","parentDepth","parentCloseAll","parentRegisterSurface","parentSurfaceId","useSurfaceContext","childSurfaceId","triggerRef","contentRef","store","ListboxStore","openChainStore","useOpenChain","open","handlePopoverOpenChange","newOpen","eventDetails","handleOpenChangeComplete","nextOpen","parentOpen","setParentOpen","parentStore","checkParentOpen","isOpen","depth","submenuContextValue","fallbackRegisterSurface","virtualization","listboxContextValue","popupMenuContextValue","SubmenuContext","PopupMenuContext","ListboxContext","import_popover","import_use_render","React","import_use_render","React","PopupMenuSubmenuTriggerDataAttributes","stateAttributesMapping","value","PopupMenuSubmenuTriggerIndicator","props","forwardedRef","render","className","style","children","rest","open","childSurfaceId","useSubmenuContext","isPopupFocused","useFocusOwner","state","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","import_jsx_runtime","stateAttributesMapping","value","PopupMenuSubmenuTrigger","props","forwardedRef","idProp","keywords","disabled","forceMount","openOnHighlight","delayProp","closeDelay","render","className","style","onPointerDown","onPointerMove","onPointerEnter","onPointerLeave","children","rest","delay","parentStore","useSurfaceContext","depth","useListboxContext","parentDepth","submenuContext","useSubmenuContext","open","setOpen","triggerRef","contentRef","childSurfaceId","openTimerRef","clearOpenTimer","suppressAutoOpenRef","focusOwnerStore","useFocusOwner","aimGuardActiveRef","guardedTriggerIdRef","guardedDepthRef","activateAimGuard","clearAimGuard","useAimGuard","mouseTrailRef","useMouseTrail","item","usePopupMenuItem","input","list","focusTarget","isPopupFocused","prevOpenRef","keyboardDelay","handlePointerDown","event","handlePointerMove","handlePointerEnter","pointerDelay","handlePointerLeave","contentRect","clientX","clientY","tRect","anchor","resolveAnchorSide","heading","getSmoothedHeading","willHitSubmenu","state","wrappedChildren","ItemContext","componentName","useMaybeComponentName","slotAttr","getSlotAttribute","element","React","import_jsx_runtime","AsyncMenuCoordinatorContext","useAsyncMenuCoordinator","useMaybeAsyncMenuCoordinator","AsyncMenuCoordinatorProvider","props","children","searchQuery","loaders","setLoaders","erroredLoaders","setErroredLoaders","registerLoader","state","prev","next","unregisterLoader","id","updateLoaderResult","result","existing","isStaticLoading","isQueryLoading","isAnyLoading","allResolved","getAsyncNodes","getAsyncState","skippedMenus","contextValue","React","DataSurfaceContext","useDataSurfaceContext","context","useMaybeDataSurfaceContext","React","defineRadioGroup","def","isDisplayGroupNode","node","isDisplayRadioGroupNode","isDisplaySeparatorNode","isDisplayRowNode","defaultGetQualifiedRowId","ctx","slugValue","slugify","slugBreadcrumbs","b","isItemDef","node","isRadioItemDef","isCheckboxItemDef","isSubmenuDef","isGroupDef","isRadioGroupDef","isSeparatorDef","flattenNodes","nodes","options","deep","breadcrumbs","group","radioGroup","result","groupInfo","radioGroupInfo","submenuBreadcrumb","childBreadcrumbs","scoreNodes","flattenedNodes","query","results","normalizedValue","normalizeValue","normalizedKeywords","k","score","commandScore","sortByScore","a","partitionByKind","items","n","submenus","deduplicateNodes","seen","scoredNode","compositeId","buildDisplayRowNodes","scoredNodes","highlightedId","isDeepSearchResult","context","buildDisplayRowNode","getBrowseNodesFlatten","getBrowseNodesPreserve","groupItems","child","itemContext","groupContext","radioItems","filterNodesFlatten","deepSearch","minLength","radioGroupSearchBehavior","shouldDeepSearch","flattened","allRadioGroupItems","flatNode","existing","scored","radioGroupItems","regularItems","sorted","partitioned","unique","regularDisplayNodes","radioGroupDisplayNodes","radioGroupId","radioGroupDef","matchingItems","itemsToDisplay","allItems","matchingIds","item","matchingScores","bestScore","allNodes","r","filterNodesPreserve","sortGroups","groupedItems","radioGroupedItems","ungroupedItems","groupDisplayNodes","_groupId","groupDef","ungroupedDisplayNodes","g","filterNodes","groupSearchBehavior","getNavigableIds","displayNodes","ids","isDisplayGroupNode","isDisplayRadioGroupNode","isDisplaySeparatorNode","getFirstNavigableId","collectAsyncSubmenus","id","mergeSubmenuNodes","staticNodes","asyncNodes","static_","async_","mergeAsyncNodesIntoTree","staticContent","asyncData","asyncMap","data","mergeRecursive","currentBreadcrumbs","submenuPath","mergedStaticChildren","mergedChildren","shouldIncludeInDeepSearch","config","shouldLoadEagerly","import_jsx_runtime","computeItemIds","displayNodes","getQualifiedRowId","isDeepSearching","index","displayNode","isDisplayGroupNode","item","isDisplayRadioGroupNode","isDisplaySeparatorNode","getOrderedItemIds","ids","AsyncLoaderRenderer","info","query","enabled","coordinator","useAsyncMenuCoordinator","config","id","breadcrumbs","node","Loader","effectiveQuery","minLength","shouldLoadEagerly","result","AsyncLoaderResultHandler","breadcrumbsRef","configRef","coordinatorRef","resultRef","prevResultRef","coord","state","prev","RootAsyncLoader","dataSurfaceCtx","useDataSurfaceContext","asyncContent","PopupMenuDataList","props","forwardedRef","children","label","className","style","render","measureRowWidth","maxRowWidth","content","deepSearchConfig","store","useSurfaceContext","search","AsyncMenuCoordinatorProvider","DataListInner","asyncSubmenus","collectAsyncSubmenus","isDeepSearchActive","shouldRenderAsyncLoaders","s","asyncNodes","mergedContent","mergeAsyncNodesIntoTree","contentWithRootAsync","rootAsyncData","n","filterNodes","prevOrderedItemIdsRef","newOrderedItemIds","orderedItemIds","current","i","renderRowNode","context","compositeId","submenuAsyncState","asyncResult","isBelowMinLength","staticNodes","submenuBreadcrumb","submenuRenderNode","childNode","groupItems","groupChildren","itemContext","groupContext","renderRadioGroup","childContext","radioGroup","isDeepSearchResult","childElements","renderNode","group","items","separator","asyncState","childrenState","renderedChildren","shouldIncludeInDeepSearch","PopupMenuList","React","import_jsx_runtime","PopupMenuDataSurface","props","forwardedRef","content","asyncContent","deepSearch","filter","searchProp","onSearchChange","defaultSearch","loop","autoHighlightFirst","clearSearchOnClose","getQualifiedRowIdProp","className","style","render","children","popupMenuContext","usePopupMenuContext","getQualifiedRowId","defaultGetQualifiedRowId","deepSearchConfig","listId","contextValue","DataSurfaceContext","PopupMenuSurface"]}