@mortenbrudvik/waveui 0.14.0 → 0.15.0
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.
- package/README.md +142 -32
- package/dist/components/data-display/InfoButton.cjs +1 -1
- package/dist/components/data-display/InfoButton.cjs.map +1 -1
- package/dist/components/data-display/InfoButton.mjs +90 -82
- package/dist/components/data-display/InfoButton.mjs.map +1 -1
- package/dist/components/data-display/InfoLabel.cjs +1 -1
- package/dist/components/data-display/InfoLabel.cjs.map +1 -1
- package/dist/components/data-display/InfoLabel.mjs +19 -18
- package/dist/components/data-display/InfoLabel.mjs.map +1 -1
- package/dist/components/feedback/MessageBarGroup.cjs +2 -0
- package/dist/components/feedback/MessageBarGroup.cjs.map +1 -0
- package/dist/components/feedback/MessageBarGroup.mjs +63 -0
- package/dist/components/feedback/MessageBarGroup.mjs.map +1 -0
- package/dist/components/feedback/ProgressBar.cjs +1 -1
- package/dist/components/feedback/ProgressBar.cjs.map +1 -1
- package/dist/components/feedback/ProgressBar.mjs +41 -39
- package/dist/components/feedback/ProgressBar.mjs.map +1 -1
- package/dist/components/feedback/Toaster.cjs +1 -1
- package/dist/components/feedback/Toaster.cjs.map +1 -1
- package/dist/components/feedback/Toaster.mjs +222 -216
- package/dist/components/feedback/Toaster.mjs.map +1 -1
- package/dist/components/layout/Accordion.cjs +1 -1
- package/dist/components/layout/Accordion.cjs.map +1 -1
- package/dist/components/layout/Accordion.mjs +124 -109
- package/dist/components/layout/Accordion.mjs.map +1 -1
- package/dist/components/layout/Carousel.cjs +1 -1
- package/dist/components/layout/Carousel.cjs.map +1 -1
- package/dist/components/layout/Carousel.mjs +207 -193
- package/dist/components/layout/Carousel.mjs.map +1 -1
- package/dist/components/layout/TabList.cjs +1 -1
- package/dist/components/layout/TabList.cjs.map +1 -1
- package/dist/components/layout/TabList.mjs +149 -108
- package/dist/components/layout/TabList.mjs.map +1 -1
- package/dist/components/layout/Tree.cjs.map +1 -1
- package/dist/components/layout/Tree.context.cjs +1 -1
- package/dist/components/layout/Tree.context.cjs.map +1 -1
- package/dist/components/layout/Tree.context.mjs +2 -1
- package/dist/components/layout/Tree.context.mjs.map +1 -1
- package/dist/components/layout/Tree.core.cjs +1 -1
- package/dist/components/layout/Tree.core.cjs.map +1 -1
- package/dist/components/layout/Tree.core.mjs +178 -165
- package/dist/components/layout/Tree.core.mjs.map +1 -1
- package/dist/components/layout/Tree.mjs.map +1 -1
- package/dist/components/navigation/Menu.popover.cjs +1 -1
- package/dist/components/navigation/Menu.popover.cjs.map +1 -1
- package/dist/components/navigation/Menu.popover.mjs +154 -168
- package/dist/components/navigation/Menu.popover.mjs.map +1 -1
- package/dist/components/navigation/Nav.cjs +1 -1
- package/dist/components/navigation/Nav.cjs.map +1 -1
- package/dist/components/navigation/Nav.mjs +156 -136
- package/dist/components/navigation/Nav.mjs.map +1 -1
- package/dist/components/navigation/NavDrawer.cjs +1 -1
- package/dist/components/navigation/NavDrawer.cjs.map +1 -1
- package/dist/components/navigation/NavDrawer.mjs +48 -45
- package/dist/components/navigation/NavDrawer.mjs.map +1 -1
- package/dist/components/overlays/Dialog.cjs +1 -1
- package/dist/components/overlays/Dialog.cjs.map +1 -1
- package/dist/components/overlays/Dialog.mjs +128 -122
- package/dist/components/overlays/Dialog.mjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.cjs +1 -1
- package/dist/components/overlays/Dialog.slots.cjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.mjs +12 -12
- package/dist/components/overlays/Dialog.slots.mjs.map +1 -1
- package/dist/components/overlays/Drawer.cjs.map +1 -1
- package/dist/components/overlays/Drawer.mjs.map +1 -1
- package/dist/components/overlays/Drawer.panel.cjs +1 -1
- package/dist/components/overlays/Drawer.panel.cjs.map +1 -1
- package/dist/components/overlays/Drawer.panel.mjs +97 -81
- package/dist/components/overlays/Drawer.panel.mjs.map +1 -1
- package/dist/components/overlays/Drawer.root.cjs +1 -1
- package/dist/components/overlays/Drawer.root.cjs.map +1 -1
- package/dist/components/overlays/Drawer.root.mjs +34 -31
- package/dist/components/overlays/Drawer.root.mjs.map +1 -1
- package/dist/components/overlays/Popover.cjs +1 -1
- package/dist/components/overlays/Popover.cjs.map +1 -1
- package/dist/components/overlays/Popover.mjs +231 -216
- package/dist/components/overlays/Popover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.parts.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.parts.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.parts.mjs +202 -173
- package/dist/components/overlays/TeachingPopover.parts.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.root.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.root.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.root.mjs +108 -99
- package/dist/components/overlays/TeachingPopover.root.mjs.map +1 -1
- package/dist/components/overlays/Tooltip.cjs +1 -1
- package/dist/components/overlays/Tooltip.cjs.map +1 -1
- package/dist/components/overlays/Tooltip.mjs +66 -61
- package/dist/components/overlays/Tooltip.mjs.map +1 -1
- package/dist/components/provider/WaveProvider.cjs +1 -1
- package/dist/components/provider/WaveProvider.cjs.map +1 -1
- package/dist/components/provider/WaveProvider.mjs +26 -23
- package/dist/components/provider/WaveProvider.mjs.map +1 -1
- package/dist/hooks/useCollapsePresence.cjs +2 -0
- package/dist/hooks/useCollapsePresence.cjs.map +1 -0
- package/dist/hooks/useCollapsePresence.mjs +21 -0
- package/dist/hooks/useCollapsePresence.mjs.map +1 -0
- package/dist/hooks/useFocusBeforeClose.cjs +2 -0
- package/dist/hooks/useFocusBeforeClose.cjs.map +1 -0
- package/dist/hooks/useFocusBeforeClose.mjs +33 -0
- package/dist/hooks/useFocusBeforeClose.mjs.map +1 -0
- package/dist/hooks/useMotion.cjs +2 -0
- package/dist/hooks/useMotion.cjs.map +1 -0
- package/dist/hooks/useMotion.mjs +14 -0
- package/dist/hooks/useMotion.mjs.map +1 -0
- package/dist/hooks/usePresenceGroup.cjs +2 -0
- package/dist/hooks/usePresenceGroup.cjs.map +1 -0
- package/dist/hooks/usePresenceGroup.mjs +68 -0
- package/dist/hooks/usePresenceGroup.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +721 -131
- package/dist/index.d.ts +721 -131
- package/dist/index.mjs +136 -135
- package/dist/lib/classNames.cjs +1 -1
- package/dist/lib/classNames.cjs.map +1 -1
- package/dist/lib/classNames.mjs +101 -90
- package/dist/lib/classNames.mjs.map +1 -1
- package/dist/lib/motion.cjs +2 -0
- package/dist/lib/motion.cjs.map +1 -0
- package/dist/lib/motion.mjs +43 -0
- package/dist/lib/motion.mjs.map +1 -0
- package/dist/styles.css +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tree.core.mjs","names":["useId","useId$1","React","EMPTY","ITEM_IN_LABEL_MESSAGE","warnDuplicateValue","value","SELECTED_WITH_MULTIPLE_MESSAGE","CHECKED_WITHOUT_MULTIPLE_MESSAGE","SINGLE_WITHOUT_SELECTED_MESSAGE","forestInTreeOrder","entries","entry","a","b","TREE_ITEM_SELECTOR","ACTION_ITEM_SELECTOR","ACTIONS_ON_ITEM_FOCUS","ASIDE_OFF_ON_ITEM_FOCUS","ACTIONS_VISIBILITY","ASIDE_OFF_WITH_ACTIONS","END_CELL_SHARED","focusFirstAction","toolbar","item","cssHidden","el","isHiddenInput","concealed","marker","TreeRoot","rest","initialExpanded","defaultExpandedItems","expandedList","setExpandedList","useControllable","expandedItems","onExpandedItemsChange","next","expanded","toggle","prev","v","expand","added","values","activate","useEventCallback","initialChecked","defaultCheckedItems","pendingDetails","checkedList","setCheckedList","checkedItems","onCheckedItemsChange","checked","topLevel","registerTopLevel","toggleChecked","forest","toggleCheck","previous","effectiveSelected","selectionMode","selected","warnOnce","hasCheckedProps","focusedItem","setFocusedItem","valueCounts","registerValue","isDev","counts","count","remaining","useRovingTabIndex","context","current","getTabIndex","focusValue","navigationMode","mergedRef","useMergedRefs","ref","containerProps","handleKeyDown","event","syncTypeaheadText","handleKeyDownCapture","handleBlur","TreeContext","TreeParentContext","TreeCheckForcedContext","cn","treeClassNames","className","composeEventHandlers","onKeyDown","onKeyDownCapture","onFocus","onBlur","TreeLabelContext","label","treeitem","personaName","text","isOwnKeyEvent","target","isOwnClick","TreeItemActions","treegrid","rovingRef","rovingKeyDown","rovingFocus","popupFocus","setPopupFocus","frame","handleToolbarFocus","handleToolbarBlur","isOwnEvent","popup","isEditableTarget","getArrowIntent","getDirection","labelledBy","isPrev","onReturn","treeItemClassNames","TreeItem","props","typeaheadText","ctx","useTreeContext","parent","insideLabel","isExpanded","labelId","asideId","ancestorListed","itemRef","layoutIds","setLayoutIds","registerLayout","ids","itemContext","nameId","nestedItems","labelContent","firstChildValue","children","child","keyed","key","isElementOfType","iconNode","icon","slotRendersContent","renderSlot","iconAfterNode","iconAfter","hasAside","aside","hasActions","actions","hasChildren","leaf","chevron","expandIcon","ChevronRightIcon","multiple","ownNode","collectItems","checkState","computeCheckStates","selectionEntry","isTopLevel","isSelected","isCurrent","handleClick","onClick","siblings","intent","focusedAction","inOwnActions","handleFocus","handleActionsBlur","action","active","checkbox","forcedColors","SubtractIcon","CheckIcon","radio","indicator","groupListed","joinIds","TreeItemContext","materialiseSlotContent"],"sources":["../../../src/components/layout/Tree.core.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { flattenChildren, isElementOfType } from '../../lib/children';\nimport { treeClassNames, treeItemClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { isDev, warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isEditableTarget, isOwnEvent } from '../../lib/events';\nimport { isHiddenInput } from '../../lib/focus';\nimport { CheckIcon, ChevronRightIcon, SubtractIcon } from '../../lib/icons';\nimport type { SelectionMode } from '../../lib/types';\nimport { materialiseSlotContent, renderSlot, slotRendersContent, type Slot } from '../../lib/slot';\nimport { forcedColors } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { isHiddenByCss, useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport {\n TreeCheckForcedContext,\n TreeContext,\n TreeItemContext,\n TreeLabelContext,\n TreeParentContext,\n useTreeContext,\n type PersonaLayoutIds,\n type TreeContextValue,\n type TreeItemContextValue,\n type TreeSelectionEntry,\n} from './Tree.context';\nimport {\n collectItems,\n computeCheckStates,\n toggleCheck,\n type CheckState,\n type TreeNode,\n} from './Tree.selection';\n\nconst EMPTY: readonly string[] = [];\n\nconst ITEM_IN_LABEL_MESSAGE =\n 'Tree.Item was rendered inside the label of another Tree.Item, so it is not part of that ' +\n \"item's child group: the parent cannot expand, its name includes the nested text, and a \" +\n 'treeitem sits inside a label (axe aria-required-parent). A Tree.Item finds its nested items ' +\n 'among its own children (written directly, in Fragments, or returned by a render function such ' +\n 'as `children.map(renderNode)`), but not inside a component that renders Tree.Item itself. ' +\n 'Build a data-driven tree with a render function instead of a recursive component.';\n\nfunction warnDuplicateValue(value: string): void {\n warnOnce(\n `Tree:duplicate:${value}`,\n `Tree: several items share the value \"${value}\". Item values must be unique within a Tree; ` +\n 'items with the same value share their expanded, selected and focus state.',\n );\n}\n\nconst SELECTED_WITH_MULTIPLE_MESSAGE =\n 'Tree: `selected` has no effect with selectionMode=\"multiple\"; use `checkedItems`, and ' +\n '`current` for the item the user is on.';\n\nconst CHECKED_WITHOUT_MULTIPLE_MESSAGE =\n 'Tree: `checkedItems` and `defaultCheckedItems` need selectionMode=\"multiple\"; without it the ' +\n 'tree draws no checkboxes and ignores them.';\n\nconst SINGLE_WITHOUT_SELECTED_MESSAGE =\n 'Tree: selectionMode=\"single\" draws a radio on every item for `selected`; pass `selected` ' +\n '(null while nothing is selected) and update it from `onItemSelect`.';\n\n/** The registered top-level subtrees in document order, which is the tree order of their items. */\nfunction forestInTreeOrder(\n entries: ReadonlySet<React.RefObject<TreeSelectionEntry | null>> | null,\n): TreeNode[] {\n if (!entries) return [];\n return Array.from(entries, (entry) => entry.current)\n .filter((entry): entry is TreeSelectionEntry => entry !== null)\n .sort((a, b) => {\n if (!a.element || !b.element || a.element === b.element) return 0;\n return a.element.compareDocumentPosition(b.element) & Node.DOCUMENT_POSITION_FOLLOWING\n ? -1\n : 1;\n })\n .map((entry) => entry.node);\n}\n\n/**\n * The tree's own items for the tab stop and the arrow keys: the treeitems. A row's actions are a\n * roving container of their own, which the default selector would count as one more item.\n */\nconst TREE_ITEM_SELECTOR = '[role=\"treeitem\"]';\n\n/** Every focusable control a row's actions can hold (Toolbar's rule). */\nconst ACTION_ITEM_SELECTOR = 'button, [href], input, select, textarea, [role=\"button\"], [tabindex]';\n\n/**\n * Shows a row's actions while focus is on its item (also after a click) or inside the item's own\n * row, never in its child group, so Tab and the treegrid arrows reach them. The item's\n * `:focus-within`, not its `:focus`: while focus moves from the item into an action, Chromium has\n * already ended the item's `:focus` (but keeps `:focus-within` on it, the common ancestor) when it\n * checks that the action can take focus, and a hidden action refuses it.\n */\nconst ACTIONS_ON_ITEM_FOCUS =\n '[&:focus-within:not(:has(>[role=group]_:focus))>[data-tree-row]_[data-tree-actions]]:visible';\n\n/** Makes the aside invisible while its actions show for focus, where they take its place. */\nconst ASIDE_OFF_ON_ITEM_FOCUS =\n '[@media(hover:hover)]:not-forced-colors:[&:focus-within:not(:has(>[role=group]_:focus))>[data-tree-row]_[data-tree-aside]]:invisible';\n\n/**\n * The actions stay invisible until the row is hovered or the item or an action has focus, and\n * always show in forced colors and without hover (touch). An invisible action takes no focus.\n * They also show while a surface opened from an action is open (its trigger is expanded) and\n * while focus is in such a surface (`data-focus-in-popup`), so the surface's focus return, which\n * runs after its trigger already reports it closed, reaches the action.\n */\nconst ACTIONS_VISIBILITY =\n 'invisible group-hover/row:visible focus-within:visible forced-colors:visible [@media(hover:none)]:visible has-[[aria-expanded=true]]:visible data-[focus-in-popup]:visible';\n\n/** The aside gives way to the actions where the two share one place. */\nconst ASIDE_OFF_WITH_ACTIONS =\n 'not-forced-colors:group-hover/row:invisible [@media(hover:hover)]:not-forced-colors:group-focus-within/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[aria-expanded=true]]/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[data-focus-in-popup]]/end:invisible';\n\n/** Aside and actions share one cell, and sit side by side where the actions always show. */\nconst END_CELL_SHARED = '[&>*]:[grid-area:1/1] forced-colors:flex [@media(hover:none)]:flex';\n\n/**\n * Focuses the first action of an item's own row that takes focus, trying them in order and\n * skipping what the roving hook skips: natively disabled, marked `data-roving-disabled`,\n * `aria-disabled` unless focusable-disabled, hidden form inputs, anything inside a `hidden` or\n * `inert` element of the toolbar, and what CSS hides (the hook's own `isHiddenByCss`). `false` when\n * focus did not move into the row's actions.\n */\nfunction focusFirstAction(item: HTMLElement): boolean {\n const toolbar = item.querySelector<HTMLElement>(':scope > [data-tree-row] [data-tree-actions]');\n if (!toolbar) return false;\n const cssHidden = new Map<Element, boolean>();\n for (const el of Array.from(toolbar.querySelectorAll<HTMLElement>(ACTION_ITEM_SELECTOR))) {\n if (isHiddenInput(el) || el.matches(':disabled')) continue;\n const concealed = el.closest('[hidden], [inert]');\n if (concealed && toolbar.contains(concealed)) continue;\n const marker = el.getAttribute('data-roving-disabled');\n if (marker !== null && marker !== 'false') continue;\n if (\n el.getAttribute('aria-disabled') === 'true' &&\n !el.hasAttribute('data-disabled-focusable')\n ) {\n continue;\n }\n if (isHiddenByCss(el, toolbar, cssHidden)) continue;\n el.focus();\n if (el.ownerDocument.activeElement === el) return true;\n }\n return false;\n}\n\n/* ------------------------------------------------------------------ */\n/* Tree */\n/* ------------------------------------------------------------------ */\n\n/** The second argument of `onCheckedItemsChange`. */\nexport interface TreeCheckedItemsChangeDetails {\n /** The item that was toggled. */\n value: string;\n /** Its new state (a toggle never leaves it mixed). */\n checked: boolean;\n /** The DOM event of the toggle: a keyboard event for Space, a mouse event for a click. */\n event: Event;\n}\n\n/** Properties for the Tree component. */\nexport interface TreeProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Controlled list of expanded item values. */\n expandedItems?: readonly string[];\n /**\n * Item values that are expanded initially (uncontrolled).\n * @default []\n */\n defaultExpandedItems?: readonly string[];\n /** Called with the new list of expanded item values when an item expands or collapses. */\n onExpandedItemsChange?: (expandedItems: string[]) => void;\n /**\n * Called with an item's value every time it is activated (a click on its row, Enter, or Space\n * unless the tree has checkboxes), also when the same item is activated again.\n */\n onItemSelect?: (value: string) => void;\n /**\n * Value of the selected item. When set (also to `null`), every item carries `aria-selected`, and\n * the selected item is where keyboard focus enters the tree. It has no effect with\n * `selectionMode=\"multiple\"` (a development warning): items carry `aria-checked` instead. With\n * `selectionMode=\"single\"` every item carries `aria-selected` even while it is not set (a\n * development warning: the radios need it).\n */\n selected?: string | null;\n /** Value of the current item (for example the open page): it gets `aria-current=\"true\"`. */\n current?: string | null;\n /**\n * How items are selected. `'none'`: activation only (0.7; `selected` highlights one item).\n * `'single'`: a radio indicator on every item for `selected`/`onItemSelect`. `'multiple'`: a\n * checkbox on every item, bound to `checkedItems`; checking an item checks its descendants, and a\n * parent shows checked, mixed or unchecked from them. Fluent's `'multiselect'` is `'multiple'`.\n * @default 'none'\n */\n selectionMode?: 'none' | SelectionMode;\n /** Controlled checked items (`selectionMode=\"multiple\"`); see the cascade rule in the component docs. */\n checkedItems?: readonly string[];\n /**\n * Initially checked items (uncontrolled).\n * @default []\n */\n defaultCheckedItems?: readonly string[];\n /**\n * Called with every checked item (in tree order) when a check changes (Fluent's `onCheckedChange`).\n * WaveUI always passes `details`; it is typed optional until 1.0.\n */\n onCheckedItemsChange?: (checkedItems: string[], details?: TreeCheckedItemsChangeDetails) => void;\n /**\n * `'tree'`: Tab from a focused item enters its actions. `'treegrid'`: the \"next\" arrow\n * (ArrowRight, ArrowLeft in RTL) moves into an item's actions and \"previous\" returns; on an\n * expanded parent \"next\" no longer moves to the first child (ArrowDown does). The roles stay\n * `tree` and `treeitem` (Fluent's `navigationMode`).\n * @default 'tree'\n */\n navigationMode?: 'tree' | 'treegrid';\n /** Ref to the `role=\"tree\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nexport const TreeRoot = ({\n expandedItems,\n defaultExpandedItems,\n onExpandedItemsChange,\n onItemSelect,\n selected,\n current,\n selectionMode = 'none',\n navigationMode = 'tree',\n checkedItems,\n defaultCheckedItems,\n onCheckedItemsChange,\n className,\n children,\n onKeyDown,\n onKeyDownCapture,\n onFocus,\n onBlur,\n ref,\n ...rest\n}: TreeProps) => {\n const [initialExpanded] = React.useState<readonly string[]>(() => defaultExpandedItems ?? EMPTY);\n const [expandedList, setExpandedList] = useControllable<readonly string[]>(\n expandedItems,\n initialExpanded,\n (next) => onExpandedItemsChange?.([...next]),\n );\n const expanded = React.useMemo(() => new Set(expandedList), [expandedList]);\n\n const toggle = React.useCallback(\n (value: string) => {\n setExpandedList((prev) =>\n prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value],\n );\n },\n [setExpandedList],\n );\n\n const expand = React.useCallback(\n (values: readonly string[]) => {\n setExpandedList((prev) => {\n const added = values.filter((v) => !prev.includes(v));\n return added.length > 0 ? [...prev, ...added] : prev;\n });\n },\n [setExpandedList],\n );\n\n const activate = useEventCallback((value: string) => {\n onItemSelect?.(value);\n });\n\n // Checked items (`selectionMode=\"multiple\"`). useControllable passes the value only, so a toggle\n // hands `details` to the change callback through a ref it writes and clears in the same event.\n const [initialChecked] = React.useState<readonly string[]>(() => defaultCheckedItems ?? EMPTY);\n const pendingDetails = React.useRef<TreeCheckedItemsChangeDetails | undefined>(undefined);\n const [checkedList, setCheckedList] = useControllable<readonly string[]>(\n checkedItems,\n initialChecked,\n (next) => onCheckedItemsChange?.([...next], pendingDetails.current),\n );\n const checked = React.useMemo(() => new Set(checkedList), [checkedList]);\n\n // The top-level items' subtrees (each item scans its own children), read when a check toggles:\n // they give the emitted list its tree order.\n const topLevel = React.useRef<Set<React.RefObject<TreeSelectionEntry | null>> | null>(null);\n const registerTopLevel = React.useCallback(\n (entry: React.RefObject<TreeSelectionEntry | null>) => {\n topLevel.current ??= new Set();\n const entries = topLevel.current;\n entries.add(entry);\n return () => {\n entries.delete(entry);\n };\n },\n [],\n );\n const toggleChecked = useEventCallback((value: string, event: Event) => {\n const forest = forestInTreeOrder(topLevel.current);\n setCheckedList((previous) => {\n const next = toggleCheck(forest, previous, value);\n pendingDetails.current = { value, checked: next.includes(value), event };\n return next;\n });\n pendingDetails.current = undefined;\n });\n\n // An item carries aria-checked or aria-selected, never both (APG); in single mode every item\n // carries aria-selected from the first render, so the radios and the state agree.\n const effectiveSelected =\n selectionMode === 'multiple'\n ? undefined\n : selectionMode === 'single'\n ? (selected ?? null)\n : selected;\n\n React.useEffect(() => {\n if (selectionMode === 'multiple' && selected !== undefined) {\n warnOnce('Tree:selected-with-multiple', SELECTED_WITH_MULTIPLE_MESSAGE);\n }\n }, [selectionMode, selected]);\n React.useEffect(() => {\n if (selectionMode === 'single' && selected === undefined) {\n warnOnce('Tree:single-without-selected', SINGLE_WITHOUT_SELECTED_MESSAGE);\n }\n }, [selectionMode, selected]);\n const hasCheckedProps = checkedItems !== undefined || defaultCheckedItems !== undefined;\n React.useEffect(() => {\n if (selectionMode !== 'multiple' && hasCheckedProps) {\n warnOnce('Tree:checked-without-multiple', CHECKED_WITHOUT_MULTIPLE_MESSAGE);\n }\n }, [selectionMode, hasCheckedProps]);\n\n // The item that has focus while focus is inside the tree: it holds the tab stop, so Shift+Tab\n // leaves the tree. Cleared when focus leaves; the next entry goes to `selected`, else the first.\n const [focusedItem, setFocusedItem] = React.useState<string | null>(null);\n\n // How many mounted items carry each value (written from the items' effects only).\n const valueCounts = React.useRef<Map<string, number> | null>(null);\n const registerValue = React.useCallback((value: string) => {\n if (!isDev) return () => {};\n valueCounts.current ??= new Map();\n const counts = valueCounts.current;\n const count = (counts.get(value) ?? 0) + 1;\n counts.set(value, count);\n if (count > 1) warnDuplicateValue(value);\n return () => {\n const remaining = (counts.get(value) ?? 1) - 1;\n if (remaining > 0) counts.set(value, remaining);\n else counts.delete(value);\n };\n }, []);\n\n const { containerProps, getTabIndex, focusValue } = useRovingTabIndex({\n activeValue: focusedItem ?? effectiveSelected ?? null,\n itemSelector: TREE_ITEM_SELECTOR,\n orientation: 'vertical',\n loop: false,\n typeahead: true,\n });\n\n const context = React.useMemo<TreeContextValue>(\n () => ({\n expanded,\n toggle,\n expand,\n activate,\n selected: effectiveSelected,\n current,\n getTabIndex,\n focusValue,\n onItemFocus: setFocusedItem,\n focusedItem,\n navigationMode,\n registerValue,\n selectionMode,\n checked,\n toggleChecked,\n registerTopLevel,\n }),\n [\n expanded,\n toggle,\n expand,\n activate,\n effectiveSelected,\n current,\n getTabIndex,\n focusValue,\n focusedItem,\n navigationMode,\n registerValue,\n selectionMode,\n checked,\n toggleChecked,\n registerTopLevel,\n ],\n );\n\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, containerProps.ref);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n // Typeahead reads `data-roving-text` at key time: fill it from each item's label first.\n if (event.key.length === 1) syncTypeaheadText(event.currentTarget);\n containerProps.onKeyDown(event);\n };\n\n // A Space that continues a search is typeahead too, taken before the item would activate on it.\n const handleKeyDownCapture = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === ' ') syncTypeaheadText(event.currentTarget);\n containerProps.onKeyDownCapture(event);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n const next = event.relatedTarget as Node | null;\n if (!next || !event.currentTarget.contains(next)) setFocusedItem(null);\n };\n\n return (\n <TreeContext.Provider value={context}>\n <TreeParentContext.Provider value={null}>\n <TreeCheckForcedContext.Provider value={false}>\n <div\n role=\"tree\"\n data-selection-mode={selectionMode}\n aria-multiselectable={selectionMode === 'multiple' ? true : undefined}\n className={cn(treeClassNames.root, 'text-body-1', className)}\n {...rest}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyDownCapture={composeEventHandlers(onKeyDownCapture, handleKeyDownCapture)}\n onFocus={composeEventHandlers(onFocus, containerProps.onFocus, {\n checkDefaultPrevented: false,\n })}\n onBlur={composeEventHandlers(onBlur, handleBlur, { checkDefaultPrevented: false })}\n ref={mergedRef}\n >\n {/* A Tree has its own items, also when it renders inside a label (a portaled popup). */}\n <TreeLabelContext.Provider value={false}>{children}</TreeLabelContext.Provider>\n </div>\n </TreeCheckForcedContext.Provider>\n </TreeParentContext.Provider>\n </TreeContext.Provider>\n );\n};\nTreeRoot.displayName = 'Tree';\n\n/* ------------------------------------------------------------------ */\n/* Tree.Item */\n/* ------------------------------------------------------------------ */\n\n/** Properties for the TreeItem sub-component. */\nexport interface TreeItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Unique value identifying this tree item. */\n value: string;\n /**\n * Icon displayed before the label. Rendered in a `<span>` hidden from assistive technology\n * (`aria-hidden`); pass a slot object (`{ className, children, … }`) to customise it. A falsy\n * icon (`''`, `0`) or a list of nothing renders no span.\n */\n icon?: Slot<'span'>;\n /** Icon after the label (decorative, `aria-hidden`; a falsy value renders nothing, as `icon`). */\n iconAfter?: Slot<'span'>;\n /**\n * Replaces the expand chevron (decorative). `null`/`undefined` keep the chevron; `false`, or\n * anything that renders nothing, hides it (`aria-expanded` still reports the state). Not rotated.\n */\n expandIcon?: Slot<'span'>;\n /**\n * Non-interactive content at the end of the row, such as a count or a badge. It describes the item\n * (`aria-describedby`); it hides while the actions show on hover or focus.\n */\n aside?: React.ReactNode;\n /**\n * Buttons at the end of the row (a toolbar named by the item's label). Shown while the row is\n * hovered or the item or its actions have focus, and always in forced colors and without hover\n * (touch). Tab reaches them from the focused item (`navigationMode=\"tree\"`), or the arrow keys do\n * (`\"treegrid\"`). Keys and clicks on them never activate or check the item.\n *\n * They also stay shown while a Menu, Popover or Dialog rendered inside them holds focus or its\n * trigger among them is expanded, so its focus return reaches the action. A dialog your app\n * renders elsewhere and opens from an action through state (a \"Delete…\" menu item that opens a\n * confirm Dialog) closes after the actions have hidden again (on devices with hover, outside\n * forced colors): a hidden action cannot take focus, so focus returns to the nearest element\n * that can, normally the item. Render such a Dialog inside `actions` (its `Dialog.Trigger`\n * there, or the controlled Dialog next to the Menu that opens it) to return focus to the action;\n * `finalFocusRef` cannot name it, since it is still hidden when the dialog closes.\n */\n actions?: React.ReactNode;\n /**\n * Renders the item as a leaf even when it has nested `Tree.Item`s: they are not rendered, and\n * the item has no `aria-expanded` and does not expand. An item is expandable only while it has\n * nested items, so `leaf={false}` does not make an item without them expandable. To load the\n * children on first expansion, give the item a placeholder child (a \"Loading…\" `Tree.Item`)\n * until they arrive.\n * @default false\n */\n leaf?: boolean;\n /** Ref to the `role=\"treeitem\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * Sets the typeahead text (`data-roving-text`, read by the roving hook) of every rendered\n * treeitem to the text of its label (a persona layout's name when the label holds one), so neither\n * the icon nor the nested items take part. A consumer `data-roving-text` on a Tree.Item is kept on\n * its label and wins.\n */\nfunction syncTypeaheadText(tree: HTMLElement): void {\n tree.querySelectorAll<HTMLElement>('[role=\"treeitem\"]').forEach((treeitem) => {\n const label = treeitem.querySelector<HTMLElement>(\n ':scope > [data-tree-row] > [data-tree-label]',\n );\n if (!label) return;\n // A persona layout's name is the item's name, so it is its typeahead text too (not the media,\n // such as an avatar's initials, or the description).\n const personaName = label.querySelector<HTMLElement>('[data-tree-persona-name]');\n const text =\n label.getAttribute('data-roving-text') ?? personaName?.textContent ?? label.textContent ?? '';\n if (treeitem.getAttribute('data-roving-text') !== text) {\n treeitem.setAttribute('data-roving-text', text);\n }\n });\n}\n\n/**\n * Whether a keyboard event belongs to this treeitem: its target (the focused element) is this\n * treeitem or inside its row, not a nested item and not the row's actions (their keys are theirs).\n */\nfunction isOwnKeyEvent(event: React.KeyboardEvent<HTMLElement>): boolean {\n const target = event.target as Element | null;\n if (target?.closest?.('[data-tree-actions]')) return false;\n return target?.closest?.('[role=\"treeitem\"]') === event.currentTarget;\n}\n\n/**\n * Whether a click landed on this treeitem's own row (or on the treeitem element itself). Clicks\n * in its child group, including the indentation gutter beside the nested rows, clicks on nested\n * items, on its checkbox and on its actions are not its own.\n */\nfunction isOwnClick(event: React.MouseEvent<HTMLElement>): boolean {\n const target = event.target as Element | null;\n if (target === event.currentTarget) return true;\n if (target?.closest?.('[data-tree-checkbox], [data-tree-actions]')) return false;\n return target?.closest?.('[data-tree-row]')?.parentElement === event.currentTarget;\n}\n\ninterface TreeItemActionsProps {\n /** Id of the element that names the item. */\n labelledBy: string;\n /**\n * `'last-focused'` while the actions hold a Tab stop (their item has focus, tree mode), else\n * `'none'`.\n */\n tabStop: 'last-focused' | 'none';\n /** `'treegrid'`: the arrows do not wrap, and \"previous\" on the first action returns to the item. */\n navigationMode: 'tree' | 'treegrid';\n /** Moves focus back to the item. */\n onReturn: () => void;\n children: React.ReactNode;\n}\n\n/**\n * A row's actions: the consumer's controls rove with the arrow keys and hold at most one Tab\n * stop. A key pressed on an action is the action's: ArrowDown and ArrowUp on an action that opens\n * a popup (`aria-haspopup`) never move focus to another item. In treegrid navigation, \"previous\"\n * on the first action returns to the item.\n */\nconst TreeItemActions = ({\n labelledBy,\n tabStop,\n navigationMode,\n onReturn,\n children,\n}: TreeItemActionsProps) => {\n const treegrid = navigationMode === 'treegrid';\n const {\n containerProps: { ref: rovingRef },\n handleKeyDown: rovingKeyDown,\n handleFocus: rovingFocus,\n } = useRovingTabIndex({\n itemSelector: ACTION_ITEM_SELECTOR,\n manageTabIndex: true,\n orientation: 'horizontal',\n loop: !treegrid,\n tabStop,\n });\n\n // Focus in a surface opened from an action (a Menu, Popover or Dialog rendered in a portal, whose\n // focus events reach the toolbar through the React tree): `'inside'`. Once focus leaves such a\n // surface for anywhere but the toolbar, `'leaving'` until the next frame, because the surface's\n // focus return comes later in that close (its layout phase, or a microtask).\n const [popupFocus, setPopupFocus] = React.useState<'inside' | 'leaving' | null>(null);\n React.useEffect(() => {\n if (popupFocus !== 'leaving') return;\n const frame = requestAnimationFrame(() => setPopupFocus(null));\n return () => cancelAnimationFrame(frame);\n }, [popupFocus]);\n\n const handleToolbarFocus = (event: React.FocusEvent<HTMLSpanElement>) => {\n rovingFocus(event);\n setPopupFocus(event.currentTarget.contains(event.target) ? null : 'inside');\n };\n\n const handleToolbarBlur = (event: React.FocusEvent<HTMLSpanElement>) => {\n // An action's own blur: its focus-within reveal decides.\n if (event.currentTarget.contains(event.target)) return;\n const next = event.relatedTarget;\n // Back to an action: its focus clears the hold.\n if (next instanceof Node && event.currentTarget.contains(next)) return;\n setPopupFocus('leaving');\n };\n\n /** Whether the key is treegrid's \"previous\" for an action (the roving order settles it). */\n const handleKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>): boolean => {\n // A key from a popup an action opened reaches here through the React tree: not ours.\n if (event.defaultPrevented || !isOwnEvent(event)) return false;\n const target = event.target as HTMLElement;\n const popup = target.getAttribute('aria-haspopup');\n if (\n (event.key === 'ArrowDown' || event.key === 'ArrowUp') &&\n popup !== null &&\n popup !== 'false'\n ) {\n event.preventDefault();\n return false;\n }\n if (!treegrid || event.altKey || event.ctrlKey || event.metaKey || isEditableTarget(target)) {\n return false;\n }\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n return intent === 'prev';\n };\n\n const handleToolbarKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {\n const isPrev = handleKeyDown(event);\n if (event.defaultPrevented) return;\n rovingKeyDown(event);\n // \"Previous\" that the roving order did not take (the first action it reaches) returns.\n if (isPrev && event.target === document.activeElement) {\n event.preventDefault();\n onReturn();\n }\n };\n\n return (\n <span\n role=\"toolbar\"\n aria-labelledby={labelledBy}\n aria-orientation=\"horizontal\"\n data-tree-actions=\"\"\n data-roving-container=\"\"\n ref={rovingRef}\n data-focus-in-popup={popupFocus === null ? undefined : ''}\n onKeyDown={handleToolbarKeyDown}\n onFocus={handleToolbarFocus}\n onBlur={handleToolbarBlur}\n className={cn(\n treeItemClassNames.actions,\n 'inline-flex items-center gap-1',\n ACTIONS_VISIBILITY,\n )}\n >\n {children}\n </span>\n );\n};\nTreeItemActions.displayName = 'TreeItemActions';\n\n/**\n * One node of a Tree. Text and other content are the label; nested `Tree.Item` children form its\n * child group, which is shown while the item is expanded.\n *\n * Nested items must be `Tree.Item` elements among the item's own children: written directly, in\n * Fragments, or returned by a render function (`{node.children.map(renderNode)}`). A component\n * that renders `Tree.Item` itself (a recursive `<NodeView node={child} />`) is not recognised:\n * its output becomes part of the label, so the parent cannot expand (a development warning names\n * this). Render data-driven trees with a render function instead. The checks of a\n * `selectionMode=\"multiple\"` tree cascade by the same rule, so an item that such a component\n * renders is not checked with its parent.\n *\n * `ref` and every other prop land on the `role=\"treeitem\"` element, which contains the label row\n * and the child group. Its `onClick` receives only clicks on its own row (not on its child group\n * or nested items) and its `onKeyDown` only keys pressed while focus is on it or in its row; both\n * run before the built-in behaviour (call `event.preventDefault()` to skip it). In a checkbox\n * tree, a click on the item's checkbox toggles its check and is not passed to `onClick`, and\n * neither is a click on its actions; `onKeyDown` receives no keys pressed in the actions. Its\n * other event handlers (`onFocus`, `onDoubleClick`, `onContextMenu` and the rest) are not\n * filtered: as DOM events bubble, they also receive events from its child group and nested items\n * (compare `event.target` with `event.currentTarget` to tell them apart).\n *\n * `actions` render in a toolbar at the end of the row, named by the item; keys and clicks on them\n * belong to them and never activate or check the item. `aside` sits before them and describes the\n * item.\n *\n * The item is named by its label (`aria-labelledby`), not by its icon or nested items; an\n * `aria-label` or `aria-labelledby` prop replaces that name. Typeahead matches the label text too\n * (a `data-roving-text` prop replaces it).\n */\nexport const TreeItem = ({\n value,\n icon,\n iconAfter,\n expandIcon,\n aside,\n actions,\n leaf = false,\n className,\n children,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ref,\n ...props\n}: TreeItemProps) => {\n const { 'data-roving-text': typeaheadText, ...rest } = props as typeof props & {\n 'data-roving-text'?: string;\n };\n const ctx = useTreeContext('Tree.Item');\n const parent = React.useContext(TreeParentContext);\n const insideLabel = React.useContext(TreeLabelContext);\n const isExpanded = ctx.expanded.has(value);\n const labelId = useId('tree-item-label');\n const asideId = useId('tree-item-aside');\n const ancestorListed = React.useContext(TreeCheckForcedContext);\n const itemRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, itemRef);\n // A Tree.ItemPersonaLayout in the label registers its name and description: the item is named\n // by the name only and described by the description.\n const [layoutIds, setLayoutIds] = React.useState<PersonaLayoutIds | null>(null);\n const registerLayout = React.useCallback((ids: PersonaLayoutIds) => {\n setLayoutIds(ids);\n return () => setLayoutIds((current) => (current === ids ? null : current));\n }, []);\n const itemContext = React.useMemo<TreeItemContextValue>(\n () => ({ registerLayout }),\n [registerLayout],\n );\n const nameId = layoutIds?.nameId ?? labelId;\n\n const { registerValue, registerTopLevel } = ctx;\n React.useEffect(() => registerValue(value), [registerValue, value]);\n React.useEffect(() => {\n if (insideLabel) warnOnce('Tree.Item:inside-label', ITEM_IN_LABEL_MESSAGE);\n }, [insideLabel]);\n\n // Nested Tree.Items (and, as in 0.4, nested Trees) form the child group; the rest is the label.\n // Parts are identified through their element type, so parts written in a Server Component\n // (lazy references) count too.\n const nestedItems: React.ReactNode[] = [];\n const labelContent: React.ReactNode[] = [];\n let firstChildValue: string | undefined;\n flattenChildren(children).forEach(({ key, node: child }) => {\n const keyed = <React.Fragment key={key}>{child}</React.Fragment>;\n if (isElementOfType<TreeItemProps>(child, TreeItem)) {\n firstChildValue ??= child.props.value;\n nestedItems.push(keyed);\n } else if (isElementOfType(child, TreeRoot)) {\n nestedItems.push(keyed);\n } else {\n labelContent.push(keyed);\n }\n });\n\n // A falsy icon (`icon={name && <Icon />}` with `name` '' or a count of 0) is no icon, as in 0.4\n // and as in Avatar, and so is a collection whose items render nothing: no empty span adds a gap\n // to the row. The check does not consume a generator: renderSlot still renders its items.\n const iconNode =\n icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(treeItemClassNames.icon, 'inline-flex shrink-0'), {\n 'aria-hidden': true,\n })\n : null;\n const iconAfterNode =\n iconAfter && slotRendersContent(iconAfter)\n ? renderSlot(iconAfter, 'span', cn(treeItemClassNames.iconAfter, 'inline-flex shrink-0'), {\n 'aria-hidden': true,\n })\n : null;\n // No empty aside and no empty toolbar (`actions={cond && <Button />}` with `cond` false).\n const hasAside = slotRendersContent(aside);\n const hasActions = slotRendersContent(actions);\n const hasChildren = nestedItems.length > 0 && !leaf;\n\n // The optional-indicator slot rule (C-SLOTS): `null`/`undefined` keep the chevron, `false` or\n // content that renders nothing hides it (the spacer keeps the column), and a custom glyph is\n // rendered as given, not rotated.\n let chevron: React.ReactNode = <span className=\"w-3 shrink-0\" aria-hidden=\"true\" />;\n if (hasChildren && (expandIcon === undefined || expandIcon === null)) {\n chevron = (\n <ChevronRightIcon\n className={cn(\n treeItemClassNames.expandIcon,\n 'shrink-0 transition-transform motion-reduce:transition-none',\n isExpanded ? 'rotate-90' : 'wave-rtl:-scale-x-100',\n )}\n />\n );\n } else if (hasChildren && slotRendersContent(expandIcon)) {\n chevron = renderSlot(\n expandIcon,\n 'span',\n cn(treeItemClassNames.expandIcon, 'inline-flex shrink-0'),\n { 'aria-hidden': true },\n );\n }\n\n // Checkbox tree: the item computes its state from its own subtree (the child-group rule) and\n // the checked list, so every state renders on the server and needs no other item. A top-level\n // item also hands its subtree to the root, which orders a toggle's list by it.\n const multiple = ctx.selectionMode === 'multiple';\n const ownNode = React.useMemo<TreeNode | null>(\n () =>\n multiple\n ? {\n value,\n children: leaf ? [] : collectItems(children, { item: TreeItem, tree: TreeRoot }),\n }\n : null,\n [multiple, value, leaf, children],\n );\n const checkState: CheckState | undefined = ownNode\n ? computeCheckStates([ownNode], ctx.checked, ancestorListed).get(value)\n : undefined;\n const selectionEntry = React.useRef<TreeSelectionEntry | null>(null);\n React.useLayoutEffect(() => {\n selectionEntry.current = ownNode ? { node: ownNode, element: itemRef.current } : null;\n });\n const isTopLevel = parent === null && !insideLabel;\n React.useLayoutEffect(\n () => (multiple && isTopLevel ? registerTopLevel(selectionEntry) : undefined),\n [multiple, isTopLevel, registerTopLevel],\n );\n const isSelected = ctx.selected !== undefined ? ctx.selected === value : undefined;\n const isCurrent = ctx.current !== undefined && ctx.current !== null && ctx.current === value;\n\n const activate = () => {\n if (hasChildren) ctx.toggle(value);\n ctx.activate(value);\n };\n\n const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!isOwnClick(event)) return;\n onClick?.(event);\n if (!event.defaultPrevented) activate();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!isOwnKeyEvent(event)) return;\n onKeyDown?.(event);\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) return;\n\n switch (event.key) {\n case 'Enter':\n event.preventDefault();\n activate();\n return;\n case ' ':\n event.preventDefault();\n // A checkbox tree toggles the focused item's check (APG); the other modes activate.\n if (checkState !== undefined) ctx.toggleChecked(value, event.nativeEvent);\n else activate();\n return;\n case '*': {\n event.preventDefault();\n const siblings = event.currentTarget.parentElement?.querySelectorAll<HTMLElement>(\n ':scope > [role=\"treeitem\"][aria-expanded=\"false\"][data-roving-value]',\n );\n ctx.expand(\n Array.from(siblings ?? [], (el) => el.getAttribute('data-roving-value') ?? '').filter(\n Boolean,\n ),\n );\n return;\n }\n default:\n }\n\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n if (intent === 'next') {\n event.preventDefault();\n if (hasChildren && !isExpanded) {\n ctx.toggle(value);\n return;\n }\n // Treegrid navigation moves into the row's actions, also from an open parent (Down reaches\n // its first child), where APG's tree moves to the first child.\n if (ctx.navigationMode === 'treegrid' && focusFirstAction(event.currentTarget)) return;\n if (hasChildren && firstChildValue !== undefined) ctx.focusValue(firstChildValue);\n } else if (intent === 'prev') {\n event.preventDefault();\n if (hasChildren && isExpanded) ctx.toggle(value);\n else if (parent !== null) ctx.focusValue(parent);\n }\n };\n\n // Focus in the actions: tracked from the events, because a removed element fires no reliable\n // blur. A blur that leaves for another element, or from an element still in the document, ends it.\n const focusedAction = React.useRef<Element | null>(null);\n const inOwnActions = (event: React.FocusEvent<HTMLElement>) =>\n (event.target as Element).closest('[data-tree-actions]')?.closest('[role=\"treeitem\"]') ===\n event.currentTarget;\n // Focus on the item, or on one of its own actions (a click), makes it the active item.\n const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget || inOwnActions(event)) ctx.onItemFocus(value);\n if (inOwnActions(event)) focusedAction.current = event.target as Element;\n };\n\n const handleActionsBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n if (inOwnActions(event) && (event.relatedTarget !== null || event.target.isConnected)) {\n focusedAction.current = null;\n }\n };\n // An action that had focus is gone (no longer in the document) and focus fell to the page: it\n // goes to the item instead. Focus anywhere else ends the record at the next render.\n React.useLayoutEffect(() => {\n const action = focusedAction.current;\n if (!action) return;\n const item = itemRef.current;\n const active = item?.ownerDocument.activeElement;\n if (active && active !== item.ownerDocument.body) {\n focusedAction.current = null;\n } else if (item && !action.isConnected) {\n focusedAction.current = null;\n item.focus({ preventScroll: true });\n }\n });\n\n // The checkbox never takes focus (APG: focus stays on tree items): a press on it focuses its\n // item instead, and its click toggles the check without activating the item.\n const keepFocusOnItem = (event: React.MouseEvent<HTMLSpanElement>) => {\n event.preventDefault();\n itemRef.current?.focus({ preventScroll: true });\n };\n const handleCheckboxClick = (event: React.MouseEvent<HTMLSpanElement>) => {\n ctx.toggleChecked(value, event.nativeEvent);\n };\n\n const checkbox =\n checkState === undefined ? null : (\n <span\n role=\"checkbox\"\n aria-checked={checkState === 'mixed' ? 'mixed' : checkState === 'checked'}\n aria-labelledby={nameId}\n tabIndex={-1}\n data-tree-checkbox=\"\"\n onMouseDown={keepFocusOnItem}\n onClick={handleCheckboxClick}\n className={cn(\n treeItemClassNames.indicator,\n // Checkbox's box: 16px inside a 24px target (the pseudo-element), WCAG 2.5.8.\n 'relative inline-flex size-4 shrink-0 items-center justify-center rounded-xs border transition-colors motion-reduce:transition-none',\n 'before:absolute before:-inset-1',\n checkState === 'unchecked'\n ? cn('border-stroke-accessible bg-transparent', forcedColors.control)\n : 'border-primary bg-primary text-primary-foreground forced-colors:border-[Highlight] forced-colors:bg-[Highlight]',\n )}\n >\n {checkState === 'mixed' ? (\n <SubtractIcon size={12} className={forcedColors.selectedLeaf} />\n ) : checkState === 'checked' ? (\n <CheckIcon size={12} className={forcedColors.selectedLeaf} />\n ) : null}\n </span>\n );\n\n // Single mode: a decorative radio (the treeitem's aria-selected carries the state). A click on\n // it is a click on the row, so it activates the item.\n const radio =\n ctx.selectionMode === 'single' ? (\n <span\n aria-hidden=\"true\"\n className={cn(\n treeItemClassNames.indicator,\n 'inline-flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors motion-reduce:transition-none',\n isSelected\n ? 'border-2 border-primary forced-colors:border-[Highlight]'\n : cn('border-stroke-accessible', forcedColors.control),\n )}\n >\n {isSelected && (\n <span className={cn('block size-2 rounded-full bg-primary', forcedColors.selectedLeaf)} />\n )}\n </span>\n ) : null;\n // A tree item shows its checkbox in multiple mode, its radio in single mode, and nothing else.\n const indicator = checkbox ?? radio;\n\n // Items in this item's group are checked when the list checks this item or an ancestor.\n const groupListed = ancestorListed || (multiple && ctx.checked.has(value));\n\n return (\n <div\n role=\"treeitem\"\n aria-selected={isSelected}\n aria-current={isCurrent ? true : undefined}\n data-checked={checkState === 'checked' ? '' : undefined}\n data-mixed={checkState === 'mixed' ? '' : undefined}\n className={cn(\n treeItemClassNames.root,\n // The focus ring is drawn on the row: an outline on the treeitem would surround its\n // whole subtree.\n 'block outline-none',\n '[&:focus-visible>[data-tree-row]]:outline-2 [&:focus-visible>[data-tree-row]]:-outline-offset-2 [&:focus-visible>[data-tree-row]]:outline-ring',\n hasActions && ACTIONS_ON_ITEM_FOCUS,\n hasActions && hasAside && ASIDE_OFF_ON_ITEM_FOCUS,\n className,\n )}\n {...rest}\n // Named by its label only: the treeitem also contains its icon and its child group. A\n // consumer aria-labelledby or aria-label replaces it.\n aria-labelledby={\n rest['aria-labelledby'] ?? (rest['aria-label'] === undefined ? nameId : undefined)\n }\n // The aside describes the item, after a consumer description.\n aria-describedby={joinIds(\n rest['aria-describedby'],\n hasAside ? asideId : undefined,\n layoutIds?.descriptionId,\n )}\n aria-expanded={hasChildren ? isExpanded : undefined}\n // From the checked list, after the rest props, so a consumer cannot contradict it.\n aria-checked={\n checkState === undefined\n ? undefined\n : checkState === 'mixed'\n ? 'mixed'\n : checkState === 'checked'\n }\n tabIndex={ctx.getTabIndex(value)}\n data-roving-value={value}\n data-selected={isSelected ? '' : undefined}\n data-current={isCurrent ? '' : undefined}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onFocus={(event) =>\n composeEventHandlers(onFocus, handleFocus, { checkDefaultPrevented: false })(event)\n }\n onBlur={(event) =>\n composeEventHandlers(onBlur, handleActionsBlur, { checkDefaultPrevented: false })(event)\n }\n ref={mergedRef}\n >\n <div\n data-tree-row=\"\"\n className={cn(\n treeItemClassNames.row,\n 'flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 hover:bg-subtle-hover',\n hasActions && 'group/row',\n isSelected && cn('bg-subtle-selected font-semibold', forcedColors.selectedContainer),\n )}\n >\n {chevron}\n {indicator}\n {iconNode}\n <span\n id={labelId}\n data-tree-label=\"\"\n data-roving-text={typeaheadText}\n // The label shrinks (and truncates) when the row has content after it.\n className={cn(\n treeItemClassNames.label,\n 'truncate',\n (iconAfterNode || hasAside || hasActions) && 'min-w-0',\n )}\n >\n <TreeCheckForcedContext.Provider value={false}>\n <TreeLabelContext.Provider value>\n <TreeItemContext.Provider value={itemContext}>\n {labelContent}\n </TreeItemContext.Provider>\n </TreeLabelContext.Provider>\n </TreeCheckForcedContext.Provider>\n </span>\n {iconAfterNode}\n {(hasAside || hasActions) && (\n <span\n data-tree-end=\"\"\n className={cn(\n 'group/end ms-auto inline-grid shrink-0 items-center gap-1',\n hasAside && hasActions && END_CELL_SHARED,\n )}\n >\n {hasAside && (\n <span\n id={asideId}\n data-tree-aside=\"\"\n className={cn(\n treeItemClassNames.aside,\n 'inline-flex items-center text-caption-1 text-muted-foreground',\n hasActions && ASIDE_OFF_WITH_ACTIONS,\n )}\n >\n {materialiseSlotContent(aside)}\n </span>\n )}\n {hasActions && (\n <TreeItemActions\n labelledBy={nameId}\n tabStop={\n ctx.navigationMode === 'tree' && ctx.focusedItem === value\n ? 'last-focused'\n : 'none'\n }\n navigationMode={ctx.navigationMode}\n onReturn={() => ctx.focusValue(value)}\n >\n {materialiseSlotContent(actions)}\n </TreeItemActions>\n )}\n </span>\n )}\n </div>\n {hasChildren && isExpanded && (\n <TreeParentContext.Provider value={value}>\n <TreeCheckForcedContext.Provider value={groupListed}>\n <TreeLabelContext.Provider value={false}>\n <div role=\"group\" className={cn(treeItemClassNames.group, 'ps-4')}>\n {nestedItems}\n </div>\n </TreeLabelContext.Provider>\n </TreeCheckForcedContext.Provider>\n </TreeParentContext.Provider>\n )}\n </div>\n );\n};\nTreeItem.displayName = 'TreeItem';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tree.core.mjs","names":["useId","useId$1","React","EMPTY","ITEM_IN_LABEL_MESSAGE","warnDuplicateValue","value","SELECTED_WITH_MULTIPLE_MESSAGE","CHECKED_WITHOUT_MULTIPLE_MESSAGE","SINGLE_WITHOUT_SELECTED_MESSAGE","forestInTreeOrder","entries","entry","a","b","TREE_ITEM_SELECTOR","ACTION_ITEM_SELECTOR","ACTIONS_ON_ITEM_FOCUS","ASIDE_OFF_ON_ITEM_FOCUS","ACTIONS_VISIBILITY","ASIDE_OFF_WITH_ACTIONS","END_CELL_SHARED","focusFirstAction","toolbar","item","cssHidden","el","isHiddenInput","concealed","marker","TreeRoot","rest","initialExpanded","defaultExpandedItems","expandedList","setExpandedList","useControllable","expandedItems","onExpandedItemsChange","next","expanded","toggle","prev","v","expand","added","values","activate","useEventCallback","initialChecked","defaultCheckedItems","pendingDetails","checkedList","setCheckedList","checkedItems","onCheckedItemsChange","checked","topLevel","registerTopLevel","toggleChecked","forest","toggleCheck","previous","effectiveSelected","selectionMode","selected","warnOnce","hasCheckedProps","focusedItem","setFocusedItem","valueCounts","registerValue","isDev","counts","count","remaining","useRovingTabIndex","context","current","getTabIndex","focusValue","navigationMode","motion","mergedRef","useMergedRefs","ref","containerProps","handleKeyDown","event","syncTypeaheadText","handleKeyDownCapture","handleBlur","TreeContext","TreeParentContext","TreeCheckForcedContext","cn","treeClassNames","className","composeEventHandlers","onKeyDown","onKeyDownCapture","onFocus","onBlur","TreeLabelContext","label","treeitem","personaName","text","isOwnKeyEvent","target","isOwnClick","TreeItemActions","treegrid","rovingRef","rovingKeyDown","rovingFocus","popupFocus","setPopupFocus","frame","handleToolbarFocus","handleToolbarBlur","isOwnEvent","popup","isEditableTarget","getArrowIntent","getDirection","labelledBy","isPrev","onReturn","treeItemClassNames","TreeItem","props","typeaheadText","ctx","useTreeContext","parent","insideLabel","isExpanded","labelId","asideId","ancestorListed","itemRef","layoutIds","setLayoutIds","registerLayout","ids","itemContext","nameId","nestedItems","labelContent","firstChildValue","children","child","keyed","key","isElementOfType","iconNode","icon","slotRendersContent","renderSlot","iconAfterNode","iconAfter","hasAside","aside","hasActions","actions","hasChildren","leaf","groupRef","isGroupMounted","collapseRef","collapsePresenceProps","collapseClassName","useCollapsePresence","chevron","expandIcon","ChevronRightIcon","multiple","ownNode","collectItems","checkState","computeCheckStates","selectionEntry","isTopLevel","isSelected","isCurrent","handleClick","onClick","siblings","intent","focusedAction","inOwnActions","handleFocus","handleActionsBlur","action","active","checkbox","forcedColors","SubtractIcon","CheckIcon","radio","indicator","groupListed","joinIds","TreeItemContext","materialiseSlotContent"],"sources":["../../../src/components/layout/Tree.core.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { flattenChildren, isElementOfType } from '../../lib/children';\nimport { treeClassNames, treeItemClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { isDev, warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isEditableTarget, isOwnEvent } from '../../lib/events';\nimport { isHiddenInput } from '../../lib/focus';\nimport { CheckIcon, ChevronRightIcon, SubtractIcon } from '../../lib/icons';\nimport type { MotionSlot, SelectionMode } from '../../lib/types';\nimport { materialiseSlotContent, renderSlot, slotRendersContent, type Slot } from '../../lib/slot';\nimport { forcedColors } from '../../lib/styles';\nimport { useCollapsePresence } from '../../hooks/useCollapsePresence';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { isHiddenByCss, useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport {\n TreeCheckForcedContext,\n TreeContext,\n TreeItemContext,\n TreeLabelContext,\n TreeParentContext,\n useTreeContext,\n type PersonaLayoutIds,\n type TreeContextValue,\n type TreeItemContextValue,\n type TreeSelectionEntry,\n} from './Tree.context';\nimport {\n collectItems,\n computeCheckStates,\n toggleCheck,\n type CheckState,\n type TreeNode,\n} from './Tree.selection';\n\nconst EMPTY: readonly string[] = [];\n\nconst ITEM_IN_LABEL_MESSAGE =\n 'Tree.Item was rendered inside the label of another Tree.Item, so it is not part of that ' +\n \"item's child group: the parent cannot expand, its name includes the nested text, and a \" +\n 'treeitem sits inside a label (axe aria-required-parent). A Tree.Item finds its nested items ' +\n 'among its own children (written directly, in Fragments, or returned by a render function such ' +\n 'as `children.map(renderNode)`), but not inside a component that renders Tree.Item itself. ' +\n 'Build a data-driven tree with a render function instead of a recursive component.';\n\nfunction warnDuplicateValue(value: string): void {\n warnOnce(\n `Tree:duplicate:${value}`,\n `Tree: several items share the value \"${value}\". Item values must be unique within a Tree; ` +\n 'items with the same value share their expanded, selected and focus state.',\n );\n}\n\nconst SELECTED_WITH_MULTIPLE_MESSAGE =\n 'Tree: `selected` has no effect with selectionMode=\"multiple\"; use `checkedItems`, and ' +\n '`current` for the item the user is on.';\n\nconst CHECKED_WITHOUT_MULTIPLE_MESSAGE =\n 'Tree: `checkedItems` and `defaultCheckedItems` need selectionMode=\"multiple\"; without it the ' +\n 'tree draws no checkboxes and ignores them.';\n\nconst SINGLE_WITHOUT_SELECTED_MESSAGE =\n 'Tree: selectionMode=\"single\" draws a radio on every item for `selected`; pass `selected` ' +\n '(null while nothing is selected) and update it from `onItemSelect`.';\n\n/** The registered top-level subtrees in document order, which is the tree order of their items. */\nfunction forestInTreeOrder(\n entries: ReadonlySet<React.RefObject<TreeSelectionEntry | null>> | null,\n): TreeNode[] {\n if (!entries) return [];\n return Array.from(entries, (entry) => entry.current)\n .filter((entry): entry is TreeSelectionEntry => entry !== null)\n .sort((a, b) => {\n if (!a.element || !b.element || a.element === b.element) return 0;\n return a.element.compareDocumentPosition(b.element) & Node.DOCUMENT_POSITION_FOLLOWING\n ? -1\n : 1;\n })\n .map((entry) => entry.node);\n}\n\n/**\n * The tree's own items for the tab stop and the arrow keys: the treeitems. A row's actions are a\n * roving container of their own, which the default selector would count as one more item.\n */\nconst TREE_ITEM_SELECTOR = '[role=\"treeitem\"]';\n\n/** Every focusable control a row's actions can hold (Toolbar's rule). */\nconst ACTION_ITEM_SELECTOR = 'button, [href], input, select, textarea, [role=\"button\"], [tabindex]';\n\n/**\n * Shows a row's actions while focus is on its item (also after a click) or inside the item's own\n * row, never in its child group (a grandchild of the item: the group sits in its collapse\n * element), so Tab and the treegrid arrows reach them. The item's `:focus-within`, not its\n * `:focus`: while focus moves from the item into an action, Chromium has already ended the item's\n * `:focus` (but keeps `:focus-within` on it, the common ancestor) when it checks that the action\n * can take focus, and a hidden action refuses it.\n */\nconst ACTIONS_ON_ITEM_FOCUS =\n '[&:focus-within:not(:has(>*>[role=group]_:focus))>[data-tree-row]_[data-tree-actions]]:visible';\n\n/** Makes the aside invisible while its actions show for focus, where they take its place. */\nconst ASIDE_OFF_ON_ITEM_FOCUS =\n '[@media(hover:hover)]:not-forced-colors:[&:focus-within:not(:has(>*>[role=group]_:focus))>[data-tree-row]_[data-tree-aside]]:invisible';\n\n/**\n * The actions stay invisible until the row is hovered or the item or an action has focus, and\n * always show in forced colors and without hover (touch). An invisible action takes no focus.\n * They also show while a surface opened from an action is open (its trigger is expanded) and\n * while focus is in such a surface (`data-focus-in-popup`), so the surface's focus return, which\n * runs after its trigger already reports it closed, reaches the action.\n */\nconst ACTIONS_VISIBILITY =\n 'invisible group-hover/row:visible focus-within:visible forced-colors:visible [@media(hover:none)]:visible has-[[aria-expanded=true]]:visible data-[focus-in-popup]:visible';\n\n/** The aside gives way to the actions where the two share one place. */\nconst ASIDE_OFF_WITH_ACTIONS =\n 'not-forced-colors:group-hover/row:invisible [@media(hover:hover)]:not-forced-colors:group-focus-within/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[aria-expanded=true]]/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[data-focus-in-popup]]/end:invisible';\n\n/** Aside and actions share one cell, and sit side by side where the actions always show. */\nconst END_CELL_SHARED = '[&>*]:[grid-area:1/1] forced-colors:flex [@media(hover:none)]:flex';\n\n/**\n * Focuses the first action of an item's own row that takes focus, trying them in order and\n * skipping what the roving hook skips: natively disabled, marked `data-roving-disabled`,\n * `aria-disabled` unless focusable-disabled, hidden form inputs, anything inside a `hidden` or\n * `inert` element of the toolbar, and what CSS hides (the hook's own `isHiddenByCss`). `false` when\n * focus did not move into the row's actions.\n */\nfunction focusFirstAction(item: HTMLElement): boolean {\n const toolbar = item.querySelector<HTMLElement>(':scope > [data-tree-row] [data-tree-actions]');\n if (!toolbar) return false;\n const cssHidden = new Map<Element, boolean>();\n for (const el of Array.from(toolbar.querySelectorAll<HTMLElement>(ACTION_ITEM_SELECTOR))) {\n if (isHiddenInput(el) || el.matches(':disabled')) continue;\n const concealed = el.closest('[hidden], [inert]');\n if (concealed && toolbar.contains(concealed)) continue;\n const marker = el.getAttribute('data-roving-disabled');\n if (marker !== null && marker !== 'false') continue;\n if (\n el.getAttribute('aria-disabled') === 'true' &&\n !el.hasAttribute('data-disabled-focusable')\n ) {\n continue;\n }\n if (isHiddenByCss(el, toolbar, cssHidden)) continue;\n el.focus();\n if (el.ownerDocument.activeElement === el) return true;\n }\n return false;\n}\n\n/* ------------------------------------------------------------------ */\n/* Tree */\n/* ------------------------------------------------------------------ */\n\n/** The second argument of `onCheckedItemsChange`. */\nexport interface TreeCheckedItemsChangeDetails {\n /** The item that was toggled. */\n value: string;\n /** Its new state (a toggle never leaves it mixed). */\n checked: boolean;\n /** The DOM event of the toggle: a keyboard event for Space, a mouse event for a click. */\n event: Event;\n}\n\n/** Properties for the Tree component. */\nexport interface TreeProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Controlled list of expanded item values. */\n expandedItems?: readonly string[];\n /**\n * Item values that are expanded initially (uncontrolled).\n * @default []\n */\n defaultExpandedItems?: readonly string[];\n /** Called with the new list of expanded item values when an item expands or collapses. */\n onExpandedItemsChange?: (expandedItems: string[]) => void;\n /**\n * Called with an item's value every time it is activated (a click on its row, Enter, or Space\n * unless the tree has checkboxes), also when the same item is activated again.\n */\n onItemSelect?: (value: string) => void;\n /**\n * Value of the selected item. When set (also to `null`), every item carries `aria-selected`, and\n * the selected item is where keyboard focus enters the tree. It has no effect with\n * `selectionMode=\"multiple\"` (a development warning): items carry `aria-checked` instead. With\n * `selectionMode=\"single\"` every item carries `aria-selected` even while it is not set (a\n * development warning: the radios need it).\n */\n selected?: string | null;\n /** Value of the current item (for example the open page): it gets `aria-current=\"true\"`. */\n current?: string | null;\n /**\n * How items are selected. `'none'`: activation only (0.7; `selected` highlights one item).\n * `'single'`: a radio indicator on every item for `selected`/`onItemSelect`. `'multiple'`: a\n * checkbox on every item, bound to `checkedItems`; checking an item checks its descendants, and a\n * parent shows checked, mixed or unchecked from them. Fluent's `'multiselect'` is `'multiple'`.\n * @default 'none'\n */\n selectionMode?: 'none' | SelectionMode;\n /** Controlled checked items (`selectionMode=\"multiple\"`); see the cascade rule in the component docs. */\n checkedItems?: readonly string[];\n /**\n * Initially checked items (uncontrolled).\n * @default []\n */\n defaultCheckedItems?: readonly string[];\n /**\n * Called with every checked item (in tree order) when a check changes (Fluent's `onCheckedChange`).\n * WaveUI always passes `details`; it is typed optional until 1.0.\n */\n onCheckedItemsChange?: (checkedItems: string[], details?: TreeCheckedItemsChangeDetails) => void;\n /**\n * `'tree'`: Tab from a focused item enters its actions. `'treegrid'`: the \"next\" arrow\n * (ArrowRight, ArrowLeft in RTL) moves into an item's actions and \"previous\" returns; on an\n * expanded parent \"next\" no longer moves to the first child (ArrowDown does). The roles stay\n * `tree` and `treeitem` (Fluent's `navigationMode`).\n * @default 'tree'\n */\n navigationMode?: 'tree' | 'treegrid';\n /**\n * Replaces the collapse of every child group in the tree (Fluent's `Tree collapseMotion`), on\n * the element around each `role=\"group\"` element: by default the space a group takes opens\n * from nothing and closes back to it, with a fade, over the normal duration (200 ms) with the\n * max easy-ease curve, both ways. `null` turns it off (a group appears and disappears at once);\n * a class string or `{ className }` replaces it, written as `MotionSlot` describes. A\n * `WaveProvider` with `motion=\"none\"` turns the default off, and a value here still applies\n * under it. The expand chevron's turn is not part of it, and a nested `Tree` takes its own.\n * @default the collapse described above\n */\n motion?: MotionSlot | null;\n /** Ref to the `role=\"tree\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nexport const TreeRoot = ({\n expandedItems,\n defaultExpandedItems,\n onExpandedItemsChange,\n onItemSelect,\n selected,\n current,\n selectionMode = 'none',\n navigationMode = 'tree',\n checkedItems,\n defaultCheckedItems,\n onCheckedItemsChange,\n motion,\n className,\n children,\n onKeyDown,\n onKeyDownCapture,\n onFocus,\n onBlur,\n ref,\n ...rest\n}: TreeProps) => {\n const [initialExpanded] = React.useState<readonly string[]>(() => defaultExpandedItems ?? EMPTY);\n const [expandedList, setExpandedList] = useControllable<readonly string[]>(\n expandedItems,\n initialExpanded,\n (next) => onExpandedItemsChange?.([...next]),\n );\n const expanded = React.useMemo(() => new Set(expandedList), [expandedList]);\n\n const toggle = React.useCallback(\n (value: string) => {\n setExpandedList((prev) =>\n prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value],\n );\n },\n [setExpandedList],\n );\n\n const expand = React.useCallback(\n (values: readonly string[]) => {\n setExpandedList((prev) => {\n const added = values.filter((v) => !prev.includes(v));\n return added.length > 0 ? [...prev, ...added] : prev;\n });\n },\n [setExpandedList],\n );\n\n const activate = useEventCallback((value: string) => {\n onItemSelect?.(value);\n });\n\n // Checked items (`selectionMode=\"multiple\"`). useControllable passes the value only, so a toggle\n // hands `details` to the change callback through a ref it writes and clears in the same event.\n const [initialChecked] = React.useState<readonly string[]>(() => defaultCheckedItems ?? EMPTY);\n const pendingDetails = React.useRef<TreeCheckedItemsChangeDetails | undefined>(undefined);\n const [checkedList, setCheckedList] = useControllable<readonly string[]>(\n checkedItems,\n initialChecked,\n (next) => onCheckedItemsChange?.([...next], pendingDetails.current),\n );\n const checked = React.useMemo(() => new Set(checkedList), [checkedList]);\n\n // The top-level items' subtrees (each item scans its own children), read when a check toggles:\n // they give the emitted list its tree order.\n const topLevel = React.useRef<Set<React.RefObject<TreeSelectionEntry | null>> | null>(null);\n const registerTopLevel = React.useCallback(\n (entry: React.RefObject<TreeSelectionEntry | null>) => {\n topLevel.current ??= new Set();\n const entries = topLevel.current;\n entries.add(entry);\n return () => {\n entries.delete(entry);\n };\n },\n [],\n );\n const toggleChecked = useEventCallback((value: string, event: Event) => {\n const forest = forestInTreeOrder(topLevel.current);\n setCheckedList((previous) => {\n const next = toggleCheck(forest, previous, value);\n pendingDetails.current = { value, checked: next.includes(value), event };\n return next;\n });\n pendingDetails.current = undefined;\n });\n\n // An item carries aria-checked or aria-selected, never both (APG); in single mode every item\n // carries aria-selected from the first render, so the radios and the state agree.\n const effectiveSelected =\n selectionMode === 'multiple'\n ? undefined\n : selectionMode === 'single'\n ? (selected ?? null)\n : selected;\n\n React.useEffect(() => {\n if (selectionMode === 'multiple' && selected !== undefined) {\n warnOnce('Tree:selected-with-multiple', SELECTED_WITH_MULTIPLE_MESSAGE);\n }\n }, [selectionMode, selected]);\n React.useEffect(() => {\n if (selectionMode === 'single' && selected === undefined) {\n warnOnce('Tree:single-without-selected', SINGLE_WITHOUT_SELECTED_MESSAGE);\n }\n }, [selectionMode, selected]);\n const hasCheckedProps = checkedItems !== undefined || defaultCheckedItems !== undefined;\n React.useEffect(() => {\n if (selectionMode !== 'multiple' && hasCheckedProps) {\n warnOnce('Tree:checked-without-multiple', CHECKED_WITHOUT_MULTIPLE_MESSAGE);\n }\n }, [selectionMode, hasCheckedProps]);\n\n // The item that has focus while focus is inside the tree: it holds the tab stop, so Shift+Tab\n // leaves the tree. Cleared when focus leaves; the next entry goes to `selected`, else the first.\n const [focusedItem, setFocusedItem] = React.useState<string | null>(null);\n\n // How many mounted items carry each value (written from the items' effects only).\n const valueCounts = React.useRef<Map<string, number> | null>(null);\n const registerValue = React.useCallback((value: string) => {\n if (!isDev) return () => {};\n valueCounts.current ??= new Map();\n const counts = valueCounts.current;\n const count = (counts.get(value) ?? 0) + 1;\n counts.set(value, count);\n if (count > 1) warnDuplicateValue(value);\n return () => {\n const remaining = (counts.get(value) ?? 1) - 1;\n if (remaining > 0) counts.set(value, remaining);\n else counts.delete(value);\n };\n }, []);\n\n const { containerProps, getTabIndex, focusValue } = useRovingTabIndex({\n activeValue: focusedItem ?? effectiveSelected ?? null,\n itemSelector: TREE_ITEM_SELECTOR,\n orientation: 'vertical',\n loop: false,\n typeahead: true,\n });\n\n const context = React.useMemo<TreeContextValue>(\n () => ({\n expanded,\n toggle,\n expand,\n activate,\n selected: effectiveSelected,\n current,\n getTabIndex,\n focusValue,\n onItemFocus: setFocusedItem,\n focusedItem,\n navigationMode,\n registerValue,\n selectionMode,\n checked,\n toggleChecked,\n registerTopLevel,\n motion,\n }),\n [\n expanded,\n toggle,\n expand,\n activate,\n effectiveSelected,\n current,\n getTabIndex,\n focusValue,\n focusedItem,\n navigationMode,\n registerValue,\n selectionMode,\n checked,\n toggleChecked,\n registerTopLevel,\n motion,\n ],\n );\n\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, containerProps.ref);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n // Typeahead reads `data-roving-text` at key time: fill it from each item's label first.\n if (event.key.length === 1) syncTypeaheadText(event.currentTarget);\n containerProps.onKeyDown(event);\n };\n\n // A Space that continues a search is typeahead too, taken before the item would activate on it.\n const handleKeyDownCapture = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === ' ') syncTypeaheadText(event.currentTarget);\n containerProps.onKeyDownCapture(event);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n const next = event.relatedTarget as Node | null;\n if (!next || !event.currentTarget.contains(next)) setFocusedItem(null);\n };\n\n return (\n <TreeContext.Provider value={context}>\n <TreeParentContext.Provider value={null}>\n <TreeCheckForcedContext.Provider value={false}>\n <div\n role=\"tree\"\n data-selection-mode={selectionMode}\n aria-multiselectable={selectionMode === 'multiple' ? true : undefined}\n className={cn(treeClassNames.root, 'text-body-1', className)}\n {...rest}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyDownCapture={composeEventHandlers(onKeyDownCapture, handleKeyDownCapture)}\n onFocus={composeEventHandlers(onFocus, containerProps.onFocus, {\n checkDefaultPrevented: false,\n })}\n onBlur={composeEventHandlers(onBlur, handleBlur, { checkDefaultPrevented: false })}\n ref={mergedRef}\n >\n {/* A Tree has its own items, also when it renders inside a label (a portaled popup). */}\n <TreeLabelContext.Provider value={false}>{children}</TreeLabelContext.Provider>\n </div>\n </TreeCheckForcedContext.Provider>\n </TreeParentContext.Provider>\n </TreeContext.Provider>\n );\n};\nTreeRoot.displayName = 'Tree';\n\n/* ------------------------------------------------------------------ */\n/* Tree.Item */\n/* ------------------------------------------------------------------ */\n\n/** Properties for the TreeItem sub-component. */\nexport interface TreeItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Unique value identifying this tree item. */\n value: string;\n /**\n * Icon displayed before the label. Rendered in a `<span>` hidden from assistive technology\n * (`aria-hidden`); pass a slot object (`{ className, children, … }`) to customise it. A falsy\n * icon (`''`, `0`) or a list of nothing renders no span.\n */\n icon?: Slot<'span'>;\n /** Icon after the label (decorative, `aria-hidden`; a falsy value renders nothing, as `icon`). */\n iconAfter?: Slot<'span'>;\n /**\n * Replaces the expand chevron (decorative). `null`/`undefined` keep the chevron; `false`, or\n * anything that renders nothing, hides it (`aria-expanded` still reports the state). Not rotated.\n */\n expandIcon?: Slot<'span'>;\n /**\n * Non-interactive content at the end of the row, such as a count or a badge. It describes the item\n * (`aria-describedby`); it hides while the actions show on hover or focus.\n */\n aside?: React.ReactNode;\n /**\n * Buttons at the end of the row (a toolbar named by the item's label). Shown while the row is\n * hovered or the item or its actions have focus, and always in forced colors and without hover\n * (touch). Tab reaches them from the focused item (`navigationMode=\"tree\"`), or the arrow keys do\n * (`\"treegrid\"`). Keys and clicks on them never activate or check the item.\n *\n * They also stay shown while a Menu, Popover or Dialog rendered inside them holds focus or its\n * trigger among them is expanded, so its focus return reaches the action. A dialog your app\n * renders elsewhere and opens from an action through state (a \"Delete…\" menu item that opens a\n * confirm Dialog) closes after the actions have hidden again (on devices with hover, outside\n * forced colors): a hidden action cannot take focus, so focus returns to the nearest element\n * that can, normally the item. Render such a Dialog inside `actions` (its `Dialog.Trigger`\n * there, or the controlled Dialog next to the Menu that opens it) to return focus to the action;\n * `finalFocusRef` cannot name it, since it is still hidden when the dialog closes.\n */\n actions?: React.ReactNode;\n /**\n * Renders the item as a leaf even when it has nested `Tree.Item`s: they are not rendered, and\n * the item has no `aria-expanded` and does not expand. An item is expandable only while it has\n * nested items, so `leaf={false}` does not make an item without them expandable. To load the\n * children on first expansion, give the item a placeholder child (a \"Loading…\" `Tree.Item`)\n * until they arrive.\n * @default false\n */\n leaf?: boolean;\n /** Ref to the `role=\"treeitem\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * Sets the typeahead text (`data-roving-text`, read by the roving hook) of every rendered\n * treeitem to the text of its label (a persona layout's name when the label holds one), so neither\n * the icon nor the nested items take part. A consumer `data-roving-text` on a Tree.Item is kept on\n * its label and wins.\n */\nfunction syncTypeaheadText(tree: HTMLElement): void {\n tree.querySelectorAll<HTMLElement>('[role=\"treeitem\"]').forEach((treeitem) => {\n const label = treeitem.querySelector<HTMLElement>(\n ':scope > [data-tree-row] > [data-tree-label]',\n );\n if (!label) return;\n // A persona layout's name is the item's name, so it is its typeahead text too (not the media,\n // such as an avatar's initials, or the description).\n const personaName = label.querySelector<HTMLElement>('[data-tree-persona-name]');\n const text =\n label.getAttribute('data-roving-text') ?? personaName?.textContent ?? label.textContent ?? '';\n if (treeitem.getAttribute('data-roving-text') !== text) {\n treeitem.setAttribute('data-roving-text', text);\n }\n });\n}\n\n/**\n * Whether a keyboard event belongs to this treeitem: its target (the focused element) is this\n * treeitem or inside its row, not a nested item and not the row's actions (their keys are theirs).\n */\nfunction isOwnKeyEvent(event: React.KeyboardEvent<HTMLElement>): boolean {\n const target = event.target as Element | null;\n if (target?.closest?.('[data-tree-actions]')) return false;\n return target?.closest?.('[role=\"treeitem\"]') === event.currentTarget;\n}\n\n/**\n * Whether a click landed on this treeitem's own row (or on the treeitem element itself). Clicks\n * in its child group, including the indentation gutter beside the nested rows, clicks on nested\n * items, on its checkbox and on its actions are not its own.\n *\n * While the child group exits, its collapse element is `inert`, which hit-tests like an element\n * the pointer passes through: a pointer click in the group's box lands on the treeitem element\n * itself, and is not its own either (it would expand the item again and activate it). A click\n * without a pointer (`detail` 0: Enter on a focused item, a screen reader's click) still is.\n */\nfunction isOwnClick(event: React.MouseEvent<HTMLElement>): boolean {\n const target = event.target as Element | null;\n if (target === event.currentTarget) {\n return event.detail === 0 || !event.currentTarget.querySelector(':scope > [inert]');\n }\n if (target?.closest?.('[data-tree-checkbox], [data-tree-actions]')) return false;\n return target?.closest?.('[data-tree-row]')?.parentElement === event.currentTarget;\n}\n\ninterface TreeItemActionsProps {\n /** Id of the element that names the item. */\n labelledBy: string;\n /**\n * `'last-focused'` while the actions hold a Tab stop (their item has focus, tree mode), else\n * `'none'`.\n */\n tabStop: 'last-focused' | 'none';\n /** `'treegrid'`: the arrows do not wrap, and \"previous\" on the first action returns to the item. */\n navigationMode: 'tree' | 'treegrid';\n /** Moves focus back to the item. */\n onReturn: () => void;\n children: React.ReactNode;\n}\n\n/**\n * A row's actions: the consumer's controls rove with the arrow keys and hold at most one Tab\n * stop. A key pressed on an action is the action's: ArrowDown and ArrowUp on an action that opens\n * a popup (`aria-haspopup`) never move focus to another item. In treegrid navigation, \"previous\"\n * on the first action returns to the item.\n */\nconst TreeItemActions = ({\n labelledBy,\n tabStop,\n navigationMode,\n onReturn,\n children,\n}: TreeItemActionsProps) => {\n const treegrid = navigationMode === 'treegrid';\n const {\n containerProps: { ref: rovingRef },\n handleKeyDown: rovingKeyDown,\n handleFocus: rovingFocus,\n } = useRovingTabIndex({\n itemSelector: ACTION_ITEM_SELECTOR,\n manageTabIndex: true,\n orientation: 'horizontal',\n loop: !treegrid,\n tabStop,\n });\n\n // Focus in a surface opened from an action (a Menu, Popover or Dialog rendered in a portal, whose\n // focus events reach the toolbar through the React tree): `'inside'`. Once focus leaves such a\n // surface for anywhere but the toolbar, `'leaving'` until the next frame, because the surface's\n // focus return comes later in that close (its layout phase, or a microtask).\n const [popupFocus, setPopupFocus] = React.useState<'inside' | 'leaving' | null>(null);\n React.useEffect(() => {\n if (popupFocus !== 'leaving') return;\n const frame = requestAnimationFrame(() => setPopupFocus(null));\n return () => cancelAnimationFrame(frame);\n }, [popupFocus]);\n\n const handleToolbarFocus = (event: React.FocusEvent<HTMLSpanElement>) => {\n rovingFocus(event);\n setPopupFocus(event.currentTarget.contains(event.target) ? null : 'inside');\n };\n\n const handleToolbarBlur = (event: React.FocusEvent<HTMLSpanElement>) => {\n // An action's own blur: its focus-within reveal decides.\n if (event.currentTarget.contains(event.target)) return;\n const next = event.relatedTarget;\n // Back to an action: its focus clears the hold.\n if (next instanceof Node && event.currentTarget.contains(next)) return;\n setPopupFocus('leaving');\n };\n\n /** Whether the key is treegrid's \"previous\" for an action (the roving order settles it). */\n const handleKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>): boolean => {\n // A key from a popup an action opened reaches here through the React tree: not ours.\n if (event.defaultPrevented || !isOwnEvent(event)) return false;\n const target = event.target as HTMLElement;\n const popup = target.getAttribute('aria-haspopup');\n if (\n (event.key === 'ArrowDown' || event.key === 'ArrowUp') &&\n popup !== null &&\n popup !== 'false'\n ) {\n event.preventDefault();\n return false;\n }\n if (!treegrid || event.altKey || event.ctrlKey || event.metaKey || isEditableTarget(target)) {\n return false;\n }\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n return intent === 'prev';\n };\n\n const handleToolbarKeyDown = (event: React.KeyboardEvent<HTMLSpanElement>) => {\n const isPrev = handleKeyDown(event);\n if (event.defaultPrevented) return;\n rovingKeyDown(event);\n // \"Previous\" that the roving order did not take (the first action it reaches) returns.\n if (isPrev && event.target === document.activeElement) {\n event.preventDefault();\n onReturn();\n }\n };\n\n return (\n <span\n role=\"toolbar\"\n aria-labelledby={labelledBy}\n aria-orientation=\"horizontal\"\n data-tree-actions=\"\"\n data-roving-container=\"\"\n ref={rovingRef}\n data-focus-in-popup={popupFocus === null ? undefined : ''}\n onKeyDown={handleToolbarKeyDown}\n onFocus={handleToolbarFocus}\n onBlur={handleToolbarBlur}\n className={cn(\n treeItemClassNames.actions,\n 'inline-flex items-center gap-1',\n ACTIONS_VISIBILITY,\n )}\n >\n {children}\n </span>\n );\n};\nTreeItemActions.displayName = 'TreeItemActions';\n\n/**\n * One node of a Tree. Text and other content are the label; nested `Tree.Item` children form its\n * child group, which is shown while the item is expanded.\n *\n * The child group renders as the only child of a collapse element (its stable class\n * `wave-tree-item__collapse`), which opens and closes the group's space (the Tree's `motion`) and\n * has no box of its own while the item is expanded, so the group lays out in the item as before.\n * An item expanded by default appears without motion. After a collapse the group stays in the\n * document until the collapse ends, `inert` (its items leave the arrow keys and typeahead at once)\n * while the item already reports itself collapsed; expanding the item again during the collapse\n * keeps the same group. Focus inside the group when the item collapses moves to the item. A\n * pointer click that falls through the exiting group onto the item (an `inert` element lets the\n * pointer through) is not the item's: it neither expands nor activates it.\n *\n * Nested items must be `Tree.Item` elements among the item's own children: written directly, in\n * Fragments, or returned by a render function (`{node.children.map(renderNode)}`). A component\n * that renders `Tree.Item` itself (a recursive `<NodeView node={child} />`) is not recognised:\n * its output becomes part of the label, so the parent cannot expand (a development warning names\n * this). Render data-driven trees with a render function instead. The checks of a\n * `selectionMode=\"multiple\"` tree cascade by the same rule, so an item that such a component\n * renders is not checked with its parent.\n *\n * `ref` and every other prop land on the `role=\"treeitem\"` element, which contains the label row\n * and the child group (in its collapse element). Its `onClick` receives only clicks on its own\n * row (not on its child group or nested items) and its `onKeyDown` only keys pressed while focus\n * is on it or in its row; both run before the built-in behaviour (call `event.preventDefault()`\n * to skip it). In a checkbox tree, a click on the item's checkbox toggles its check and is not\n * passed to `onClick`, and neither is a click on its actions; `onKeyDown` receives no keys pressed\n * in the actions. Its other event handlers (`onFocus`, `onDoubleClick`, `onContextMenu` and the\n * rest) are not filtered: as DOM events bubble, they also receive events from its child group and\n * nested items (compare `event.target` with `event.currentTarget` to tell them apart).\n *\n * `actions` render in a toolbar at the end of the row, named by the item; keys and clicks on them\n * belong to them and never activate or check the item. `aside` sits before them and describes the\n * item.\n *\n * The item is named by its label (`aria-labelledby`), not by its icon or nested items; an\n * `aria-label` or `aria-labelledby` prop replaces that name. Typeahead matches the label text too\n * (a `data-roving-text` prop replaces it).\n */\nexport const TreeItem = ({\n value,\n icon,\n iconAfter,\n expandIcon,\n aside,\n actions,\n leaf = false,\n className,\n children,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ref,\n ...props\n}: TreeItemProps) => {\n const { 'data-roving-text': typeaheadText, ...rest } = props as typeof props & {\n 'data-roving-text'?: string;\n };\n const ctx = useTreeContext('Tree.Item');\n const parent = React.useContext(TreeParentContext);\n const insideLabel = React.useContext(TreeLabelContext);\n const isExpanded = ctx.expanded.has(value);\n const labelId = useId('tree-item-label');\n const asideId = useId('tree-item-aside');\n const ancestorListed = React.useContext(TreeCheckForcedContext);\n const itemRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, itemRef);\n // A Tree.ItemPersonaLayout in the label registers its name and description: the item is named\n // by the name only and described by the description.\n const [layoutIds, setLayoutIds] = React.useState<PersonaLayoutIds | null>(null);\n const registerLayout = React.useCallback((ids: PersonaLayoutIds) => {\n setLayoutIds(ids);\n return () => setLayoutIds((current) => (current === ids ? null : current));\n }, []);\n const itemContext = React.useMemo<TreeItemContextValue>(\n () => ({ registerLayout }),\n [registerLayout],\n );\n const nameId = layoutIds?.nameId ?? labelId;\n\n const { registerValue, registerTopLevel } = ctx;\n React.useEffect(() => registerValue(value), [registerValue, value]);\n React.useEffect(() => {\n if (insideLabel) warnOnce('Tree.Item:inside-label', ITEM_IN_LABEL_MESSAGE);\n }, [insideLabel]);\n\n // Nested Tree.Items (and, as in 0.4, nested Trees) form the child group; the rest is the label.\n // Parts are identified through their element type, so parts written in a Server Component\n // (lazy references) count too.\n const nestedItems: React.ReactNode[] = [];\n const labelContent: React.ReactNode[] = [];\n let firstChildValue: string | undefined;\n flattenChildren(children).forEach(({ key, node: child }) => {\n const keyed = <React.Fragment key={key}>{child}</React.Fragment>;\n if (isElementOfType<TreeItemProps>(child, TreeItem)) {\n firstChildValue ??= child.props.value;\n nestedItems.push(keyed);\n } else if (isElementOfType(child, TreeRoot)) {\n nestedItems.push(keyed);\n } else {\n labelContent.push(keyed);\n }\n });\n\n // A falsy icon (`icon={name && <Icon />}` with `name` '' or a count of 0) is no icon, as in 0.4\n // and as in Avatar, and so is a collection whose items render nothing: no empty span adds a gap\n // to the row. The check does not consume a generator: renderSlot still renders its items.\n const iconNode =\n icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(treeItemClassNames.icon, 'inline-flex shrink-0'), {\n 'aria-hidden': true,\n })\n : null;\n const iconAfterNode =\n iconAfter && slotRendersContent(iconAfter)\n ? renderSlot(iconAfter, 'span', cn(treeItemClassNames.iconAfter, 'inline-flex shrink-0'), {\n 'aria-hidden': true,\n })\n : null;\n // No empty aside and no empty toolbar (`actions={cond && <Button />}` with `cond` false).\n const hasAside = slotRendersContent(aside);\n const hasActions = slotRendersContent(actions);\n const hasChildren = nestedItems.length > 0 && !leaf;\n\n // The child group renders in a collapse element (the presence element) while the item is\n // expanded and, after a collapse, until that element's motion ends; focus inside the group when\n // the item collapses moves to this item, which the roving hook then treats as the focused item.\n const groupRef = React.useRef<HTMLDivElement | null>(null);\n const {\n isMounted: isGroupMounted,\n wrapperRef: collapseRef,\n presenceProps: collapsePresenceProps,\n className: collapseClassName,\n } = useCollapsePresence(hasChildren && isExpanded, {\n motion: ctx.motion,\n partRef: groupRef,\n getTrigger: () => itemRef.current,\n });\n\n // The optional-indicator slot rule (C-SLOTS): `null`/`undefined` keep the chevron, `false` or\n // content that renders nothing hides it (the spacer keeps the column), and a custom glyph is\n // rendered as given, not rotated.\n let chevron: React.ReactNode = <span className=\"w-3 shrink-0\" aria-hidden=\"true\" />;\n if (hasChildren && (expandIcon === undefined || expandIcon === null)) {\n chevron = (\n <ChevronRightIcon\n className={cn(\n treeItemClassNames.expandIcon,\n 'shrink-0 transition-transform motion-reduce:transition-none',\n isExpanded ? 'rotate-90' : 'wave-rtl:-scale-x-100',\n )}\n />\n );\n } else if (hasChildren && slotRendersContent(expandIcon)) {\n chevron = renderSlot(\n expandIcon,\n 'span',\n cn(treeItemClassNames.expandIcon, 'inline-flex shrink-0'),\n { 'aria-hidden': true },\n );\n }\n\n // Checkbox tree: the item computes its state from its own subtree (the child-group rule) and\n // the checked list, so every state renders on the server and needs no other item. A top-level\n // item also hands its subtree to the root, which orders a toggle's list by it.\n const multiple = ctx.selectionMode === 'multiple';\n const ownNode = React.useMemo<TreeNode | null>(\n () =>\n multiple\n ? {\n value,\n children: leaf ? [] : collectItems(children, { item: TreeItem, tree: TreeRoot }),\n }\n : null,\n [multiple, value, leaf, children],\n );\n const checkState: CheckState | undefined = ownNode\n ? computeCheckStates([ownNode], ctx.checked, ancestorListed).get(value)\n : undefined;\n const selectionEntry = React.useRef<TreeSelectionEntry | null>(null);\n React.useLayoutEffect(() => {\n selectionEntry.current = ownNode ? { node: ownNode, element: itemRef.current } : null;\n });\n const isTopLevel = parent === null && !insideLabel;\n React.useLayoutEffect(\n () => (multiple && isTopLevel ? registerTopLevel(selectionEntry) : undefined),\n [multiple, isTopLevel, registerTopLevel],\n );\n const isSelected = ctx.selected !== undefined ? ctx.selected === value : undefined;\n const isCurrent = ctx.current !== undefined && ctx.current !== null && ctx.current === value;\n\n const activate = () => {\n if (hasChildren) ctx.toggle(value);\n ctx.activate(value);\n };\n\n const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!isOwnClick(event)) return;\n onClick?.(event);\n if (!event.defaultPrevented) activate();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!isOwnKeyEvent(event)) return;\n onKeyDown?.(event);\n if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) return;\n\n switch (event.key) {\n case 'Enter':\n event.preventDefault();\n activate();\n return;\n case ' ':\n event.preventDefault();\n // A checkbox tree toggles the focused item's check (APG); the other modes activate.\n if (checkState !== undefined) ctx.toggleChecked(value, event.nativeEvent);\n else activate();\n return;\n case '*': {\n event.preventDefault();\n const siblings = event.currentTarget.parentElement?.querySelectorAll<HTMLElement>(\n ':scope > [role=\"treeitem\"][aria-expanded=\"false\"][data-roving-value]',\n );\n ctx.expand(\n Array.from(siblings ?? [], (el) => el.getAttribute('data-roving-value') ?? '').filter(\n Boolean,\n ),\n );\n return;\n }\n default:\n }\n\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n if (intent === 'next') {\n event.preventDefault();\n if (hasChildren && !isExpanded) {\n ctx.toggle(value);\n return;\n }\n // Treegrid navigation moves into the row's actions, also from an open parent (Down reaches\n // its first child), where APG's tree moves to the first child.\n if (ctx.navigationMode === 'treegrid' && focusFirstAction(event.currentTarget)) return;\n if (hasChildren && firstChildValue !== undefined) ctx.focusValue(firstChildValue);\n } else if (intent === 'prev') {\n event.preventDefault();\n if (hasChildren && isExpanded) ctx.toggle(value);\n else if (parent !== null) ctx.focusValue(parent);\n }\n };\n\n // Focus in the actions: tracked from the events, because a removed element fires no reliable\n // blur. A blur that leaves for another element, or from an element still in the document, ends it.\n const focusedAction = React.useRef<Element | null>(null);\n const inOwnActions = (event: React.FocusEvent<HTMLElement>) =>\n (event.target as Element).closest('[data-tree-actions]')?.closest('[role=\"treeitem\"]') ===\n event.currentTarget;\n // Focus on the item, or on one of its own actions (a click), makes it the active item.\n const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget || inOwnActions(event)) ctx.onItemFocus(value);\n if (inOwnActions(event)) focusedAction.current = event.target as Element;\n };\n\n const handleActionsBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n if (inOwnActions(event) && (event.relatedTarget !== null || event.target.isConnected)) {\n focusedAction.current = null;\n }\n };\n // An action that had focus is gone (no longer in the document) and focus fell to the page: it\n // goes to the item instead. Focus anywhere else ends the record at the next render.\n React.useLayoutEffect(() => {\n const action = focusedAction.current;\n if (!action) return;\n const item = itemRef.current;\n const active = item?.ownerDocument.activeElement;\n if (active && active !== item.ownerDocument.body) {\n focusedAction.current = null;\n } else if (item && !action.isConnected) {\n focusedAction.current = null;\n item.focus({ preventScroll: true });\n }\n });\n\n // The checkbox never takes focus (APG: focus stays on tree items): a press on it focuses its\n // item instead, and its click toggles the check without activating the item.\n const keepFocusOnItem = (event: React.MouseEvent<HTMLSpanElement>) => {\n event.preventDefault();\n itemRef.current?.focus({ preventScroll: true });\n };\n const handleCheckboxClick = (event: React.MouseEvent<HTMLSpanElement>) => {\n ctx.toggleChecked(value, event.nativeEvent);\n };\n\n const checkbox =\n checkState === undefined ? null : (\n <span\n role=\"checkbox\"\n aria-checked={checkState === 'mixed' ? 'mixed' : checkState === 'checked'}\n aria-labelledby={nameId}\n tabIndex={-1}\n data-tree-checkbox=\"\"\n onMouseDown={keepFocusOnItem}\n onClick={handleCheckboxClick}\n className={cn(\n treeItemClassNames.indicator,\n // Checkbox's box: 16px inside a 24px target (the pseudo-element), WCAG 2.5.8.\n 'relative inline-flex size-4 shrink-0 items-center justify-center rounded-xs border transition-colors motion-reduce:transition-none',\n 'before:absolute before:-inset-1',\n checkState === 'unchecked'\n ? cn('border-stroke-accessible bg-transparent', forcedColors.control)\n : 'border-primary bg-primary text-primary-foreground forced-colors:border-[Highlight] forced-colors:bg-[Highlight]',\n )}\n >\n {checkState === 'mixed' ? (\n <SubtractIcon size={12} className={forcedColors.selectedLeaf} />\n ) : checkState === 'checked' ? (\n <CheckIcon size={12} className={forcedColors.selectedLeaf} />\n ) : null}\n </span>\n );\n\n // Single mode: a decorative radio (the treeitem's aria-selected carries the state). A click on\n // it is a click on the row, so it activates the item.\n const radio =\n ctx.selectionMode === 'single' ? (\n <span\n aria-hidden=\"true\"\n className={cn(\n treeItemClassNames.indicator,\n 'inline-flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors motion-reduce:transition-none',\n isSelected\n ? 'border-2 border-primary forced-colors:border-[Highlight]'\n : cn('border-stroke-accessible', forcedColors.control),\n )}\n >\n {isSelected && (\n <span className={cn('block size-2 rounded-full bg-primary', forcedColors.selectedLeaf)} />\n )}\n </span>\n ) : null;\n // A tree item shows its checkbox in multiple mode, its radio in single mode, and nothing else.\n const indicator = checkbox ?? radio;\n\n // Items in this item's group are checked when the list checks this item or an ancestor.\n const groupListed = ancestorListed || (multiple && ctx.checked.has(value));\n\n return (\n <div\n role=\"treeitem\"\n aria-selected={isSelected}\n aria-current={isCurrent ? true : undefined}\n data-checked={checkState === 'checked' ? '' : undefined}\n data-mixed={checkState === 'mixed' ? '' : undefined}\n className={cn(\n treeItemClassNames.root,\n // The focus ring is drawn on the row: an outline on the treeitem would surround its\n // whole subtree.\n 'block outline-none',\n '[&:focus-visible>[data-tree-row]]:outline-2 [&:focus-visible>[data-tree-row]]:-outline-offset-2 [&:focus-visible>[data-tree-row]]:outline-ring',\n hasActions && ACTIONS_ON_ITEM_FOCUS,\n hasActions && hasAside && ASIDE_OFF_ON_ITEM_FOCUS,\n className,\n )}\n {...rest}\n // Named by its label only: the treeitem also contains its icon and its child group. A\n // consumer aria-labelledby or aria-label replaces it.\n aria-labelledby={\n rest['aria-labelledby'] ?? (rest['aria-label'] === undefined ? nameId : undefined)\n }\n // The aside describes the item, after a consumer description.\n aria-describedby={joinIds(\n rest['aria-describedby'],\n hasAside ? asideId : undefined,\n layoutIds?.descriptionId,\n )}\n aria-expanded={hasChildren ? isExpanded : undefined}\n // From the checked list, after the rest props, so a consumer cannot contradict it.\n aria-checked={\n checkState === undefined\n ? undefined\n : checkState === 'mixed'\n ? 'mixed'\n : checkState === 'checked'\n }\n tabIndex={ctx.getTabIndex(value)}\n data-roving-value={value}\n data-selected={isSelected ? '' : undefined}\n data-current={isCurrent ? '' : undefined}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onFocus={(event) =>\n composeEventHandlers(onFocus, handleFocus, { checkDefaultPrevented: false })(event)\n }\n onBlur={(event) =>\n composeEventHandlers(onBlur, handleActionsBlur, { checkDefaultPrevented: false })(event)\n }\n ref={mergedRef}\n >\n <div\n data-tree-row=\"\"\n className={cn(\n treeItemClassNames.row,\n 'flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 hover:bg-subtle-hover',\n hasActions && 'group/row',\n isSelected && cn('bg-subtle-selected font-semibold', forcedColors.selectedContainer),\n )}\n >\n {chevron}\n {indicator}\n {iconNode}\n <span\n id={labelId}\n data-tree-label=\"\"\n data-roving-text={typeaheadText}\n // The label shrinks (and truncates) when the row has content after it.\n className={cn(\n treeItemClassNames.label,\n 'truncate',\n (iconAfterNode || hasAside || hasActions) && 'min-w-0',\n )}\n >\n <TreeCheckForcedContext.Provider value={false}>\n <TreeLabelContext.Provider value>\n <TreeItemContext.Provider value={itemContext}>\n {labelContent}\n </TreeItemContext.Provider>\n </TreeLabelContext.Provider>\n </TreeCheckForcedContext.Provider>\n </span>\n {iconAfterNode}\n {(hasAside || hasActions) && (\n <span\n data-tree-end=\"\"\n className={cn(\n 'group/end ms-auto inline-grid shrink-0 items-center gap-1',\n hasAside && hasActions && END_CELL_SHARED,\n )}\n >\n {hasAside && (\n <span\n id={asideId}\n data-tree-aside=\"\"\n className={cn(\n treeItemClassNames.aside,\n 'inline-flex items-center text-caption-1 text-muted-foreground',\n hasActions && ASIDE_OFF_WITH_ACTIONS,\n )}\n >\n {materialiseSlotContent(aside)}\n </span>\n )}\n {hasActions && (\n <TreeItemActions\n labelledBy={nameId}\n tabStop={\n ctx.navigationMode === 'tree' && ctx.focusedItem === value\n ? 'last-focused'\n : 'none'\n }\n navigationMode={ctx.navigationMode}\n onReturn={() => ctx.focusValue(value)}\n >\n {materialiseSlotContent(actions)}\n </TreeItemActions>\n )}\n </span>\n )}\n </div>\n {isGroupMounted && (\n <TreeParentContext.Provider value={value}>\n <TreeCheckForcedContext.Provider value={groupListed}>\n <TreeLabelContext.Provider value={false}>\n <div\n ref={collapseRef}\n {...collapsePresenceProps}\n className={cn(treeItemClassNames.collapse, collapseClassName)}\n >\n <div ref={groupRef} role=\"group\" className={cn(treeItemClassNames.group, 'ps-4')}>\n {nestedItems}\n </div>\n </div>\n </TreeLabelContext.Provider>\n </TreeCheckForcedContext.Provider>\n </TreeParentContext.Provider>\n )}\n </div>\n );\n};\nTreeItem.displayName = 'TreeItem';\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tree.mjs","names":["Tree","TreeRoot","TreeItem","TreeItemPersonaLayout"],"sources":["../../../src/components/layout/Tree.tsx"],"sourcesContent":["import { TreeItem, TreeRoot } from './Tree.core';\nimport { TreeItemPersonaLayout } from './Tree.itemPersonaLayout';\n\nexport type { TreeCheckedItemsChangeDetails, TreeItemProps, TreeProps } from './Tree.core';\nexport type { TreeItemPersonaLayoutProps } from './Tree.itemPersonaLayout';\n\n/**\n * A hierarchical list (WAI-ARIA Tree View pattern) with a single tab stop: Up/Down move between\n * visible items, Home/End to the first/last, Right expands or moves to the first child (or into\n * the row's actions, see below), Left collapses or moves to the parent (both mirrored in RTL),\n * Enter activates (and toggles a parent), and so does Space unless the tree has checkboxes, `*`\n * expands the siblings, and typing jumps to an item by its text.\n *\n * Keyboard focus enters at the `selected` item, else the first item; while focus is inside, the\n * tab stop follows it, so Shift+Tab leaves the tree.\n *\n * `selectionMode=\"multiple\"` draws a checkbox on every item, bound to `checkedItems`: Space\n * toggles the focused item's check, a click on the checkbox toggles it, and a click elsewhere on\n * the row activates the item (as Enter does). Checks cascade: checking an item checks every item\n * nested in it, and an item shows checked when all of its nested items are checked, mixed when\n * some are. `onCheckedItemsChange` receives every checked item in tree order (fully checked parents\n * included), followed by listed values that match no item, and `details` (`value`, `checked`,\n * `event`).\n *\n * Row content: `actions` (buttons at the end of the row, in a toolbar named by the item, shown on\n * hover and focus, and always where there is no hover or colors are forced), `aside` (a count or a\n * badge that describes the item), `iconAfter` and `expandIcon`. Tab from the focused item enters\n * its actions and Shift+Tab returns. Keys and clicks on the actions never activate or check the\n * item. With `navigationMode=\"treegrid\"`, Right (Left in right-to-left layouts) moves from an\n * item into its actions and Left returns, the actions take no Tab stop, and on an open parent Right\n * moves into its actions rather than to its first child (Down does); the roles stay `tree` and\n * `treeitem`.\n *\n * Items are `Tree.Item` elements; nested items are written in their parent's children (directly,\n * in Fragments, or returned by a render function), not rendered by a component of their own.\n * Every item needs a `value` that is unique within the Tree. `Tree.ItemPersonaLayout` lays out a\n * person (media, name and description) as an item's label.\n *\n * `Tree.Item` and `Tree.ItemPersonaLayout` are also exported as `TreeItem` and\n * `TreeItemPersonaLayout` for React Server Components, which cannot use the dotted form.\n */\nexport const Tree = /* @__PURE__ */ Object.assign(TreeRoot, {\n Item: TreeItem,\n ItemPersonaLayout: TreeItemPersonaLayout,\n});\n\nexport { TreeItem, TreeItemPersonaLayout };\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"Tree.mjs","names":["Tree","TreeRoot","TreeItem","TreeItemPersonaLayout"],"sources":["../../../src/components/layout/Tree.tsx"],"sourcesContent":["import { TreeItem, TreeRoot } from './Tree.core';\nimport { TreeItemPersonaLayout } from './Tree.itemPersonaLayout';\n\nexport type { TreeCheckedItemsChangeDetails, TreeItemProps, TreeProps } from './Tree.core';\nexport type { TreeItemPersonaLayoutProps } from './Tree.itemPersonaLayout';\n\n/**\n * A hierarchical list (WAI-ARIA Tree View pattern) with a single tab stop: Up/Down move between\n * visible items, Home/End to the first/last, Right expands or moves to the first child (or into\n * the row's actions, see below), Left collapses or moves to the parent (both mirrored in RTL),\n * Enter activates (and toggles a parent), and so does Space unless the tree has checkboxes, `*`\n * expands the siblings, and typing jumps to an item by its text.\n *\n * Keyboard focus enters at the `selected` item, else the first item; while focus is inside, the\n * tab stop follows it, so Shift+Tab leaves the tree.\n *\n * A child group opens and closes its space with a short collapse and fade (the Tree's `motion`;\n * none under reduced motion or a `WaveProvider` with `motion=\"none\"`), and focus inside a group\n * that collapses moves to its item.\n *\n * `selectionMode=\"multiple\"` draws a checkbox on every item, bound to `checkedItems`: Space\n * toggles the focused item's check, a click on the checkbox toggles it, and a click elsewhere on\n * the row activates the item (as Enter does). Checks cascade: checking an item checks every item\n * nested in it, and an item shows checked when all of its nested items are checked, mixed when\n * some are. `onCheckedItemsChange` receives every checked item in tree order (fully checked parents\n * included), followed by listed values that match no item, and `details` (`value`, `checked`,\n * `event`).\n *\n * Row content: `actions` (buttons at the end of the row, in a toolbar named by the item, shown on\n * hover and focus, and always where there is no hover or colors are forced), `aside` (a count or a\n * badge that describes the item), `iconAfter` and `expandIcon`. Tab from the focused item enters\n * its actions and Shift+Tab returns. Keys and clicks on the actions never activate or check the\n * item. With `navigationMode=\"treegrid\"`, Right (Left in right-to-left layouts) moves from an\n * item into its actions and Left returns, the actions take no Tab stop, and on an open parent Right\n * moves into its actions rather than to its first child (Down does); the roles stay `tree` and\n * `treeitem`.\n *\n * Items are `Tree.Item` elements; nested items are written in their parent's children (directly,\n * in Fragments, or returned by a render function), not rendered by a component of their own.\n * Every item needs a `value` that is unique within the Tree. `Tree.ItemPersonaLayout` lays out a\n * person (media, name and description) as an item's label.\n *\n * `Tree.Item` and `Tree.ItemPersonaLayout` are also exported as `TreeItem` and\n * `TreeItemPersonaLayout` for React Server Components, which cannot use the dotted form.\n */\nexport const Tree = /* @__PURE__ */ Object.assign(TreeRoot, {\n Item: TreeItem,\n ItemPersonaLayout: TreeItemPersonaLayout,\n});\n\nexport { TreeItem, TreeItemPersonaLayout };\n"],"mappings":";;;;AA6CA,IAAaA,IAAuB,uBAAO,OAAOC,GAAU;CAC1D,MAAMC;CACN,mBAAmBC;AACrB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useEventCallback.cjs"),o=require("../../lib/direction.cjs"),s=require("../../lib/focus.cjs"),ee=require("../../hooks/useRovingTabIndex.cjs"),te=require("../../hooks/useMergedRefs.cjs"),ne=require("../../hooks/usePresence.cjs"),c=require("../../hooks/usePopupPosition.cjs"),re=require("../../hooks/useDismiss.cjs"),ie=require("../../hooks/useRestoreFocus.cjs"),l=require("../portal/Portal.cjs"),u=require("../../lib/events.cjs"),d=require("../../hooks/useHoverIntent.cjs"),f=require("../../hooks/useTriggerElement.cjs"),p=require("./Menu.context.cjs"),m=require("./Menu.shared.cjs"),
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useEventCallback.cjs"),o=require("../../lib/direction.cjs"),s=require("../../lib/focus.cjs"),ee=require("../../hooks/useRovingTabIndex.cjs"),te=require("../../hooks/useMergedRefs.cjs"),ne=require("../../hooks/usePresence.cjs"),c=require("../../hooks/usePopupPosition.cjs"),re=require("../../hooks/useDismiss.cjs"),ie=require("../../hooks/useRestoreFocus.cjs"),l=require("../portal/Portal.cjs"),u=require("../../lib/events.cjs"),ae=require("../../lib/motion.cjs"),oe=require("../../hooks/useFocusBeforeClose.cjs"),d=require("../../hooks/useHoverIntent.cjs"),se=require("../../hooks/useMotion.cjs"),f=require("../../hooks/useTriggerElement.cjs"),p=require("./Menu.context.cjs"),m=require("./Menu.shared.cjs"),ce=require("../../hooks/useResolvedTarget.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime");var le={padding:8,crossAxis:!0};function ue(e){return!!e&&e.nodeType===1}function _(e){let[t]=h.useState(d.createHoverIntentGroup),n=h.useRef(!1);return{hoverGroup:t,isHoverFocusing:h.useCallback(()=>n.current,[]),onPointerMove:a.useEventCallback(r=>{if(r.pointerType===`touch`||r.pointerType===`pen`||!u.isOwnEvent(r))return;let i=r.target.closest(m.MENU_ITEM_SELECTOR);if(!i||!r.currentTarget.contains(i)||i.getAttribute(`aria-disabled`)===`true`||i.ownerDocument.activeElement===i)return;let a=e;for(;a.parent;)a=a.parent;a.listContainsFocus()&&!t.isHeld(r.clientX,r.clientY)&&(n.current=!0,i.focus({preventScroll:!0}),queueMicrotask(()=>{n.current=!1}))})}}var v=({side:e,align:d=`start`,offset:v,target:de,positioning:y,motion:fe,children:pe,className:b,style:me,onKeyDown:he,onKeyDownCapture:ge,onFocus:_e,onPointerEnter:ve,onPointerLeave:ye,onPointerMove:be,onContextMenu:xe,ref:Se,...x})=>{let S=p.useMenuContext(`Menu.Popover`),{popup:Ce,open:C,takeInitialFocus:w,registerSurface:T,menuId:we,labelledBy:Te,triggerRef:E,triggerElement:D,isSubmenu:O,requestClose:Ee,closeChain:k,dismiss:De,hoverSurfaceHandlers:A,isHoverClose:Oe,openOnContext:j,contextSurfaceHandlers:ke,contextAnchor:M,fromContext:N,contextOpener:P}=S;m.useStaticMenuPartWarning(`Menu.Popover`,Ce);let{target:F,pending:Ae}=ce.usePopupTarget(`Menu.Popover`,de,y),I=ue(F)?F:null,[L,je]=h.useState(null),R=h.useRef(null),Me=h.useCallback(e=>{R.current=e,je(e)},[]),{isMounted:z,ref:Ne,presenceProps:Pe}=ne.usePresence(C,{appear:!0}),Fe=se.useMotionClasses(fe,ae.popupMotion,b),{setReference:B,setFloating:Ie,floatingProps:V,isPositioned:H}=c.usePopupPosition({open:C,side:e??(O?`end`:`bottom`),align:d,shift:O?le:void 0,...c.resolvePositioning(y,{offset:O?0:4,fitViewport:!0}),...v!==void 0&&{offset:v}}),U=Ae?{...V,style:{...V.style,visibility:`hidden`}}:V,{maxHeight:Le,maxWidth:Re,...ze}=U.style;h.useLayoutEffect(()=>{B(N?M??f.getTriggerFocusTarget(D)??D:F??D)},[B,M,N,F,D]);let W=a.useEventCallback(()=>{let e=j?P.current:null;return e&&s.isConnectedAndFocusable(e)?e:f.getTriggerFocusTarget(E.current)||(I&&s.isConnectedAndFocusable(I)?I:null)}),Be=h.useMemo(()=>({get current(){return W()??E.current}}),[W,E]),G={current:I},{layerId:K}=re.useDismiss({open:C,onDismiss:De,refs:j?[R,G]:[R,E,G],anchorRef:Be,kind:`menu`,focusOutside:!0,outsidePress:j?e=>!(e.ctrlKey&&e.target instanceof Node&&E.current?.contains(e.target)):!0}),q=f.useTriggerFocusRef(E);ie.useRestoreFocus({enabled:C,container:L,triggerRef:j?void 0:q,finalFocusRef:j?P:void 0,fallback:W,onlyIfFocusInside:!0,isHoverClose:Oe});let J=z&&(j||F!=null&&!D)&&x[`aria-label`]===void 0&&x[`aria-labelledby`]===void 0;h.useEffect(()=>{J&&n.warnOnce(`Menu.Popover:name`,"Menu.Popover: this menu has no trigger to name it (a context menu, or a menu placed at a `target` without Menu.Trigger): give Menu.Popover an aria-label or aria-labelledby.")},[J]);let{containerProps:{ref:Ve},handleKeyDown:He,handleKeyDownCapture:Ue,handleFocus:We,focusFirst:Y,focusLast:X}=ee.useRovingTabIndex({orientation:`vertical`,loop:!0,typeahead:!0,manageTabIndex:!0,itemSelector:m.MENU_ITEM_SELECTOR}),Ge=te.useMergedRefs(Se,Me,Ve,Ie,Ne);h.useLayoutEffect(()=>{if(L&&C)return T({focusFirst:Y,focusLast:X,surface:L,layerId:K,getReturnFocus:W}),()=>T(null)},[L,C,T,Y,X,K,W]),oe.useFocusBeforeClose({open:C,surfaceRef:R,captureOpener:()=>j?null:q.current,candidates:e=>[j?P.current:null,e,W()]}),h.useLayoutEffect(()=>{if(!C||!L||L.contains(L.ownerDocument.activeElement))return;let e=w();e===`last`?X():e===`first`&&Y()},[C,L,w,Y,X]),h.useLayoutEffect(()=>{if(!H||!L)return;let e=L.ownerDocument.activeElement;e&&e!==L&&L.contains(e)&&e.scrollIntoView?.({block:`nearest`})},[H,L]);let Z=h.useContext(l.PortalDepthContext)+1,Q=p.useCheckableRegistry(),{hoverGroup:Ke,isHoverFocusing:$,onPointerMove:qe}=_(S),Je=h.useMemo(()=>({menu:S,isStatic:!1,portalDepth:Z,closeFromItem:k,registerCheckable:Q,hoverGroup:Ke,isHoverFocusing:$}),[S,Z,k,Q,Ke,$]),Ye=e=>{if(he?.(e),!e.defaultPrevented&&u.isOwnEvent(e)){if(e.key===`Tab`){k();return}if(O&&!e.altKey&&!e.ctrlKey&&!e.metaKey&&!u.isEditableTarget(e.target)&&o.getArrowIntent(e.key,{orientation:`horizontal`,dir:o.getDirection(e.currentTarget)})===`prev`){e.preventDefault(),W()?.focus({preventScroll:!0}),Ee();return}He(e)}};return z?(0,g.jsx)(l.Portal,{layerId:K,children:(0,g.jsx)(p.MenuListContext.Provider,{value:Je,children:(0,g.jsx)(`div`,{role:`menu`,...x,"aria-labelledby":x[`aria-labelledby`]===void 0?D&&!j&&x[`aria-label`]===void 0?Te:void 0:x[`aria-labelledby`],...Pe,ref:Ge,id:we,"data-state":C?`open`:`closed`,"data-side":U[`data-side`],"data-align":U[`data-align`],"data-roving-container":``,style:{...ze,...me},onKeyDown:Ye,onKeyDownCapture:m.withTypeaheadText(r.composeEventHandlers(ge,Ue)),onFocus:r.composeEventHandlers(_e,We,{checkDefaultPrevented:!1}),onPointerEnter:r.composeEventHandlers(ve,A.onPointerEnter),onPointerLeave:r.composeEventHandlers(ye,A.onPointerLeave),onPointerMove:r.composeEventHandlers(be,qe),onContextMenu:r.composeEventHandlers(xe,ke.onContextMenu),className:t.cn(i.menuPopoverClassNames.root,m.menuPopoverClasses,Fe,b),children:pe})})}):null};v.displayName=`MenuPopover`,exports.MenuPopover=v,exports.useMenuListPointer=_;
|
|
2
2
|
//# sourceMappingURL=Menu.popover.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.popover.cjs","names":["React","createHoverIntentGroup","useEventCallback","isOwnEvent","MENU_ITEM_SELECTOR","useMenuContext","usePopupTarget","usePresence","usePopupPosition","resolvePositioning","getTriggerFocusTarget","isConnectedAndFocusable","useDismiss","useTriggerFocusRef","useRovingTabIndex","useMergedRefs","PortalDepthContext","useCheckableRegistry","isEditableTarget","getArrowIntent","getDirection","Portal","MenuListContext","withTypeaheadText","composeEventHandlers","cn","menuPopoverClassNames","menuPopoverClasses","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useEventCallback","require_direction","require_focus","require_useRovingTabIndex","require_useMergedRefs","require_usePresence","require_usePopupPosition","require_useDismiss","require_useRestoreFocus","require_Portal","require_events","require_useHoverIntent","require_useTriggerElement","require_Menu_context","require_Menu_shared","require_useResolvedTarget","react","react_jsx_runtime","SUBMENU_SHIFT","isElementTarget","target","useMenuListPointer","hoverGroup","hoverFocusingRef","event","item","root","menu","MenuPopover","targetProp","rest","popup","targetPending","positioning","targetElement","surface","setSurface","surfaceRef","setSurfaceElement","element","presenceRef","open","positionedProps","side","isSubmenu","offset","floatingProps","_maxHeight","_maxWidth","positionStyle","setReference","fromContext","contextAnchor","triggerElement","getReturnFocus","opener","openOnContext","contextOpener","triggerRef","returnFocusRef","targetRef","dismiss","triggerFocusRef","openerRef","wasOpenRef","captureOpener","container","doc","isCandidate","el","trigger","active","wasOpen","getCloseFocus","unnamed","isMounted","rovingRef","rovingKeyDown","rovingKeyDownCapture","rovingFocus","mergedRef","ref","setFloating","registerSurface","focusFirst","focusLast","layerId","unmountingRef","focusReturnTargetOnClose","surfaceElement","takeInitialFocus","isPositioned","portalDepth","registerCheckable","listPointerMove","listContext","closeChain","isHoverFocusing","handleKeyDown","onKeyDown","requestClose","labelledBy","presenceProps","menuId","style","onKeyDownCapture","onFocus","onPointerEnter","hoverSurfaceHandlers","onPointerLeave","onPointerMove","onContextMenu","contextSurfaceHandlers","className"],"sources":["../../../src/components/navigation/Menu.popover.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { menuPopoverClassNames } from '../../lib/classNames';\nimport type {\n PopupAlign,\n PopupPositioning,\n PopupSide,\n PopupTarget,\n PopupTargetInput,\n} from '../../lib/types';\nimport { usePopupTarget } from '../../hooks/useResolvedTarget';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isEditableTarget, isOwnEvent } from '../../lib/events';\nimport { isConnectedAndFocusable } from '../../lib/focus';\nimport { useDismiss } from '../../hooks/useDismiss';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { createHoverIntentGroup, type HoverIntentGroup } from '../../hooks/useHoverIntent';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { resolvePositioning, usePopupPosition } from '../../hooks/usePopupPosition';\nimport { usePresence } from '../../hooks/usePresence';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { getTriggerFocusTarget, useTriggerFocusRef } from '../../hooks/useTriggerElement';\nimport { Portal, PortalDepthContext } from '../portal/Portal';\nimport { MenuListContext, useCheckableRegistry, useMenuContext } from './Menu.context';\nimport type { MenuContextValue, MenuListContextValue } from './Menu.context';\nimport {\n MENU_ITEM_SELECTOR,\n menuPopoverClasses,\n useStaticMenuPartWarning,\n withTypeaheadText,\n} from './Menu.shared';\n\n/** Properties for the MenuPopover sub-component. */\nexport interface MenuPopoverProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'id'> {\n /**\n * Side of the trigger the menu opens on (`start`/`end` follow the writing direction).\n * @default 'bottom' ('end' in a submenu)\n */\n side?: PopupSide;\n /** Alignment along that side. @default 'start' */\n align?: PopupAlign;\n /** Distance from the trigger in px. @default 4 (0 in a submenu) */\n offset?: number;\n /**\n * Where to place the menu instead of next to `Menu.Trigger`: an element or a `VirtualElement`\n * (a rectangle, such as a point; an inline object is fine). With a controlled `open`, a menu\n * with a `target` needs no trigger; name it with `aria-label`, and give a toggle button you use\n * as the target `aria-haspopup=\"menu\"` and `aria-expanded` yourself (the menu's `id` is\n * generated, so the toggle cannot point `aria-controls` at it). A press on a target element\n * does not close the menu. Hold the element in state, or pass a ref object (read after\n * each render of the menu). A menu opened by `openOnContext` is placed at\n * the gesture instead.\n */\n target?: PopupTargetInput;\n /**\n * Advanced positioning (Fluent's `positioning`): `offset`, `fitViewport`, `matchReferenceWidth`,\n * `fallbackPlacements` and `target` (used when the `target` prop is not set). `side` and `align`\n * stay separate props, and the `offset` prop wins over `positioning.offset`.\n * @default `{ fitViewport: true }`\n */\n positioning?: PopupPositioning;\n /** Menu items and dividers. */\n children: React.ReactNode;\n /**\n * Ref to the portaled `role=\"menu\"` surface. Its `id` is generated (the trigger's\n * `aria-controls` points to it), and it is labelled by the trigger unless `aria-label` or\n * `aria-labelledby` is given (one that holds `undefined` counts as not given).\n */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * A submenu with room on neither side of its trigger item is shifted across that side, over its\n * parent menu, to stay inside the viewport (as native and Fluent menus do).\n */\nconst SUBMENU_SHIFT = { padding: 8, crossAxis: true } as const;\n\n/** Whether a `target` is an element (duck typed, so an element of another realm counts). */\nfunction isElementTarget(target: PopupTarget | undefined): target is HTMLElement {\n return !!target && (target as Partial<Node>).nodeType === 1;\n}\n\n/**\n * Internal: the mouse behaviour of a menu list (the static root and every `Menu.Popover`\n * surface). While focus is inside a list of the menu tree (the chain's root list or any of its\n * submenus), a mouse `pointermove` over an enabled item of this list focuses it (`preventScroll`),\n * unless it already has focus or a submenu's safe zone of this list holds the point. Hover moves\n * no focus while focus is elsewhere, so a hover-opened menu or a static menu the user is not in\n * never takes focus from the page, and a Popover, Dialog or other portal opened from an item\n * keeps it. Also returns the list's hover group (the safe zones of its submenu trigger items) and\n * the flag the submenus of the list read while such a focus change runs.\n */\nexport function useMenuListPointer(menu: MenuContextValue): {\n hoverGroup: HoverIntentGroup;\n isHoverFocusing: () => boolean;\n onPointerMove: React.PointerEventHandler<HTMLElement>;\n} {\n const [hoverGroup] = React.useState(createHoverIntentGroup);\n const hoverFocusingRef = React.useRef(false);\n const isHoverFocusing = React.useCallback(() => hoverFocusingRef.current, []);\n const onPointerMove = useEventCallback((event: React.PointerEvent<HTMLElement>) => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen' || !isOwnEvent(event)) return;\n const target = event.target as Element;\n const item = target.closest<HTMLElement>(MENU_ITEM_SELECTOR);\n if (!item || !event.currentTarget.contains(item)) return;\n if (item.getAttribute('aria-disabled') === 'true') return;\n if (item.ownerDocument.activeElement === item) return;\n let root = menu;\n while (root.parent) root = root.parent;\n if (!root.listContainsFocus() || hoverGroup.isHeld(event.clientX, event.clientY)) return;\n hoverFocusingRef.current = true;\n item.focus({ preventScroll: true });\n // A submenu that just lost focus is dismissed (focus outside) in a microtask the focus change\n // queued; the flag is cleared after it.\n queueMicrotask(() => {\n hoverFocusingRef.current = false;\n });\n });\n return { hoverGroup, isHoverFocusing, onPointerMove };\n}\n\n/**\n * The portaled `role=\"menu\"` surface of a popup menu, positioned next to `Menu.Trigger`. A menu\n * taller than the space available scrolls inside the viewport: the surface is limited to the space\n * next to the trigger (`max-height`/`max-width` classes, which a `max-h-*`/`max-w-*` class in\n * `className` or a `style` replaces) and scrolls, and an item that receives focus is scrolled into\n * view. Focus moves to the first (ArrowUp: last) enabled item when it opens; arrows, Home/End and\n * typeahead move between enabled items. Escape closes it and returns focus to the trigger. An\n * outside press closes it and leaves focus where the press put it (on the trigger only when focus\n * was still in the menu or lost to the page). Tab closes it and moves focus to the trigger without\n * preventing the default, so tabbing continues from the trigger (inside a Dialog, the focus trap\n * moves on from there). The trigger here is the element that takes its focus: for a wrapper span,\n * the element inside it that carries the state ARIA (the span itself when you made it the trigger\n * with a `role` such as `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n * Keys from a portal opened inside the menu (a Popover of an item) are left to that portal: Tab\n * there moves on inside it and keeps the menu open.\n *\n * In a submenu it opens at the end side of its trigger item (`side=\"end\"`, `offset={0}`) and\n * flips to fit the viewport; with room on neither side, it overlaps its parent menu inside the\n * viewport. ArrowLeft (ArrowRight in RTL) and Escape close only the submenu and return focus to\n * its trigger item; item activation and Tab close every menu of the chain and put focus on the\n * root trigger.\n *\n * While focus is inside the menu (or one of its submenus), the item under the mouse pointer takes\n * focus, so Enter activates the item you point at. Focus in a Popover, Dialog or other portal\n * opened from an item stays there.\n *\n * A context menu (`openOnContext`) opens at the pointer or at the focused row and returns focus to\n * the element focused at the gesture; it is not labelled by its region, so give it `aria-label`\n * (development warning otherwise), as for a menu placed at a `target` without `Menu.Trigger`.\n *\n * The surface mounts through the presence core (`usePresence`): it carries\n * `data-presence=\"entering\" | \"entered\" | \"exiting\"` and, while it closes, `data-state=\"closed\"`\n * and `inert`, so exit motion classes on `data-presence` keep it on screen until they end. Focus,\n * the dismiss layer and positioning follow the open state, not the exit. Without motion it unmounts\n * as soon as it closes.\n *\n * Also exported as `MenuPopover` (import the flat name from React Server Components).\n */\nexport const MenuPopover = ({\n side,\n align = 'start',\n offset,\n target: targetProp,\n positioning,\n children,\n className,\n style,\n onKeyDown,\n onKeyDownCapture,\n onFocus,\n onPointerEnter,\n onPointerLeave,\n onPointerMove,\n onContextMenu,\n ref,\n ...rest\n}: MenuPopoverProps) => {\n const menu = useMenuContext('Menu.Popover');\n const {\n popup,\n open,\n takeInitialFocus,\n registerSurface,\n menuId,\n labelledBy,\n triggerRef,\n triggerElement,\n isSubmenu,\n requestClose,\n closeChain,\n dismiss,\n hoverSurfaceHandlers,\n isHoverClose,\n openOnContext,\n contextSurfaceHandlers,\n contextAnchor,\n fromContext,\n contextOpener,\n } = menu;\n useStaticMenuPartWarning('Menu.Popover', popup);\n const { target, pending: targetPending } = usePopupTarget(\n 'Menu.Popover',\n targetProp,\n positioning,\n );\n const targetElement = isElementTarget(target) ? target : null;\n\n const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n const surfaceRef = React.useRef<HTMLDivElement | null>(null);\n const setSurfaceElement = React.useCallback((element: HTMLDivElement | null) => {\n surfaceRef.current = element;\n setSurface(element);\n }, []);\n\n // The surface mounts and unmounts through the presence core; everything else below keys on\n // `open`, so focus returns and the layer goes on close, not after an exit motion.\n const { isMounted, ref: presenceRef, presenceProps } = usePresence(open);\n\n const {\n setReference,\n setFloating,\n floatingProps: positionedProps,\n isPositioned,\n } = usePopupPosition({\n open,\n side: side ?? (isSubmenu ? 'end' : 'bottom'),\n align,\n shift: isSubmenu ? SUBMENU_SHIFT : undefined,\n ...resolvePositioning(positioning, { offset: isSubmenu ? 0 : 4, fitViewport: true }),\n ...(offset !== undefined && { offset }),\n });\n // A ref target that holds no element yet keeps the popup hidden (as TeachingPopover's is).\n const floatingProps = targetPending\n ? { ...positionedProps, style: { ...positionedProps.style, visibility: 'hidden' as const } }\n : positionedProps;\n // The size limits come from menuPopoverClasses, which a consumer class can replace; an inline\n // max-height/max-width would beat every class.\n const { maxHeight: _maxHeight, maxWidth: _maxWidth, ...positionStyle } = floatingProps.style;\n // The positioning reference: the anchor of a context gesture (the point, else the focused row,\n // else the trigger's focus target), else `target`, else the trigger. Kept while the surface\n // exits, so it does not jump; a new inline VirtualElement only recomputes the position.\n React.useLayoutEffect(() => {\n setReference(\n fromContext\n ? (contextAnchor ?? getTriggerFocusTarget(triggerElement) ?? triggerElement)\n : (target ?? triggerElement),\n );\n }, [setReference, contextAnchor, fromContext, target, triggerElement]);\n\n // Where focus returns when the menu closes (item activation, Tab, Escape): in a context menu,\n // the element focused at the gesture when it can take focus; else the element that takes focus\n // for the trigger (for a wrapper span, the element inside it that carries the state ARIA; for a\n // submenu, its trigger item); else a focusable `target` element.\n const getReturnFocus = useEventCallback((): HTMLElement | null => {\n const opener = openOnContext ? contextOpener.current : null;\n if (opener && isConnectedAndFocusable(opener)) return opener;\n const triggerTarget = getTriggerFocusTarget(triggerRef.current);\n if (triggerTarget) return triggerTarget;\n return targetElement && isConnectedAndFocusable(targetElement) ? targetElement : null;\n });\n\n // The layer's anchor (where a surface opened from an item that is gone by then restores focus):\n // the return target, else the trigger itself.\n const returnFocusRef = React.useMemo<React.RefObject<HTMLElement | null>>(\n () => ({\n get current() {\n return getReturnFocus() ?? triggerRef.current;\n },\n }),\n [getReturnFocus, triggerRef],\n );\n // A context region is not part of the layer (a press on another row closes the menu), and a\n // Ctrl+press there is a macOS context click, which moves the menu instead; a target element is.\n const targetRef = { current: targetElement };\n const { layerId } = useDismiss({\n open,\n onDismiss: dismiss,\n refs: openOnContext ? [surfaceRef, targetRef] : [surfaceRef, triggerRef, targetRef],\n anchorRef: returnFocusRef,\n kind: 'menu',\n focusOutside: true,\n outsidePress: openOnContext\n ? (event) =>\n !(\n event.ctrlKey &&\n event.target instanceof Node &&\n triggerRef.current?.contains(event.target)\n )\n : true,\n });\n\n const triggerFocusRef = useTriggerFocusRef(triggerRef);\n\n // The element focused when the menu opened, captured as useRestoreFocus captures its opener: in\n // the commit that opens the menu, before the initial focus moves into it; the trigger's focus\n // target first (not in a context menu, whose region is no opener), else the focused element.\n const openerRef = React.useRef<HTMLElement | null>(null);\n const wasOpenRef = React.useRef(false);\n const captureOpener = useEventCallback(() => {\n const container = surfaceRef.current;\n const doc = (triggerRef.current ?? container)?.ownerDocument ?? document;\n const isCandidate = (el: Element | null | undefined): el is HTMLElement =>\n !!el && el !== doc.body && el !== doc.documentElement && !container?.contains(el);\n const trigger = openOnContext ? null : triggerFocusRef.current;\n const active = doc.activeElement;\n openerRef.current = isCandidate(trigger) ? trigger : isCandidate(active) ? active : null;\n });\n React.useInsertionEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (open && !wasOpen) captureOpener();\n });\n // Where focus goes when the menu closes with focus inside it (Escape, a close by the app): where\n // useRestoreFocus would put it, in its order: the context opener, the element focused when the\n // menu opened, then the return target (a menu with a `target` and no trigger returns focus to\n // its opener, not to a focusable target element).\n const getCloseFocus = useEventCallback((): HTMLElement | null => {\n const container = surfaceRef.current;\n const candidates = [\n openOnContext ? contextOpener.current : null,\n openerRef.current,\n getReturnFocus(),\n ];\n return (\n candidates.find(\n (el): el is HTMLElement => !!el && isConnectedAndFocusable(el) && !container?.contains(el),\n ) ?? null\n );\n });\n\n useRestoreFocus({\n enabled: open,\n container: surface,\n // A context menu returns focus to the opener (the focused row), not to the region.\n triggerRef: openOnContext ? undefined : triggerFocusRef,\n finalFocusRef: openOnContext ? contextOpener : undefined,\n fallback: getReturnFocus,\n onlyIfFocusInside: true,\n // A hover close moves no focus (a submenu closing with it is taken along by the hook).\n isHoverClose,\n });\n\n // C-DEV: a surface that no trigger labels needs its own name.\n const unnamed =\n isMounted &&\n (openOnContext || (target != null && !triggerElement)) &&\n rest['aria-label'] === undefined &&\n rest['aria-labelledby'] === undefined;\n React.useEffect(() => {\n if (!unnamed) return;\n warnOnce(\n 'Menu.Popover:name',\n 'Menu.Popover: this menu has no trigger to name it (a context menu, or a menu placed at a `target` without Menu.Trigger): give Menu.Popover an aria-label or aria-labelledby.',\n );\n }, [unnamed]);\n\n const {\n containerProps: { ref: rovingRef },\n handleKeyDown: rovingKeyDown,\n handleKeyDownCapture: rovingKeyDownCapture,\n handleFocus: rovingFocus,\n focusFirst,\n focusLast,\n } = useRovingTabIndex({\n orientation: 'vertical',\n loop: true,\n typeahead: true,\n manageTabIndex: true,\n itemSelector: MENU_ITEM_SELECTOR,\n });\n\n const mergedRef = useMergedRefs<HTMLDivElement>(\n ref,\n setSurfaceElement,\n rovingRef,\n setFloating,\n presenceRef,\n );\n\n // Lets the trigger move focus into an already open menu (ArrowDown/ArrowUp on the trigger) and\n // the root reach the surface. Only an open surface registers, and it unregisters in the commit\n // that closes the menu: a surface that stays mounted while it exits would otherwise make the next\n // opening focus its (inert) items instead of opening the menu.\n React.useLayoutEffect(() => {\n if (!surface || !open) return;\n registerSurface({ focusFirst, focusLast, surface, layerId, getReturnFocus });\n return () => registerSurface(null);\n }, [surface, open, registerSurface, focusFirst, focusLast, layerId, getReturnFocus]);\n\n // Focus before close, on every close: when the menu closes with focus inside it, focus moves to\n // where the restore would put it (`getCloseFocus`) in the closing commit's mutation phase (a\n // layout effect cleanup), before a surface opened in the same update (a Dialog rendered after\n // the menu, opened by the item that closed it) records the focused element as its opener. The\n // closing surface is still in the document then (it unmounts once its exit phase ends), so that\n // opener would be its item, gone by the time the Dialog closes. The surface is inert from this\n // commit on, so in a browser React cannot put focus back on the item after the commit, and\n // useRestoreFocus, which then finds focus outside, leaves it there: the two must agree on the\n // target. Unmounting is left to useRestoreFocus.\n const unmountingRef = React.useRef(false);\n React.useLayoutEffect(() => {\n unmountingRef.current = false;\n return () => {\n unmountingRef.current = true;\n };\n }, []);\n const focusReturnTargetOnClose = useEventCallback(() => {\n const surfaceElement = surfaceRef.current;\n const active = surfaceElement?.ownerDocument.activeElement;\n if (unmountingRef.current || !surfaceElement || !active || !surfaceElement.contains(active)) {\n return;\n }\n getCloseFocus()?.focus({ preventScroll: true });\n });\n React.useLayoutEffect(() => {\n if (!open) return undefined;\n return focusReturnTargetOnClose;\n }, [open, focusReturnTargetOnClose]);\n\n // Initial focus: the first (or last) enabled item, unless focus is already inside. A hover\n // opening moves no focus.\n React.useLayoutEffect(() => {\n if (!open || !surface) return;\n if (surface.contains(surface.ownerDocument.activeElement)) return;\n const target = takeInitialFocus();\n if (target === 'last') focusLast();\n else if (target === 'first') focusFirst();\n }, [open, surface, takeInitialFocus, focusFirst, focusLast]);\n\n // The initial focus lands before the surface is limited to the available height (floating-ui\n // measures after mount), so it scrolls nothing: once positioned, the focused item (the last one\n // after ArrowUp) is scrolled into view. Later focus moves scroll through the native focus().\n React.useLayoutEffect(() => {\n if (!isPositioned || !surface) return;\n const active = surface.ownerDocument.activeElement as HTMLElement | null;\n if (active && active !== surface && surface.contains(active)) {\n active.scrollIntoView?.({ block: 'nearest' });\n }\n }, [isPositioned, surface]);\n\n // The list the items render in. Its children sit inside the Portal, one portal level deeper.\n // Item activation closes the whole chain; the item under the mouse takes focus while focus is\n // inside the menu tree.\n const portalDepth = React.useContext(PortalDepthContext) + 1;\n const registerCheckable = useCheckableRegistry();\n const { hoverGroup, isHoverFocusing, onPointerMove: listPointerMove } = useMenuListPointer(menu);\n const listContext = React.useMemo<MenuListContextValue>(\n () => ({\n menu,\n isStatic: false,\n portalDepth,\n closeFromItem: closeChain,\n registerCheckable,\n hoverGroup,\n isHoverFocusing,\n }),\n [menu, portalDepth, closeChain, registerCheckable, hoverGroup, isHoverFocusing],\n );\n\n // C-COMPOSE: the consumer's onKeyDown runs first; preventDefault() skips the built-in keys. A key\n // from a portal opened inside the menu (a Popover of an item, a submenu) is that portal's: Tab\n // moves on inside it and never closes the menu.\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || !isOwnEvent(event)) return;\n if (event.key === 'Tab') {\n // Close every menu of the chain and put focus on the root trigger; the default Tab action\n // then continues from there.\n closeChain();\n return;\n }\n // \"Previous\" (ArrowLeft, ArrowRight in RTL) closes a submenu and returns to its trigger item.\n if (\n isSubmenu &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !isEditableTarget(event.target) &&\n getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n }) === 'prev'\n ) {\n event.preventDefault();\n getReturnFocus()?.focus({ preventScroll: true });\n requestClose();\n return;\n }\n rovingKeyDown(event);\n };\n\n if (!isMounted) return null;\n\n return (\n <Portal layerId={layerId}>\n <MenuListContext.Provider value={listContext}>\n <div\n role=\"menu\"\n {...rest}\n // After the spread: a consumer name wins when it is defined, and a forwarded key that\n // holds `undefined` does not remove the trigger's. A context region's whole text is no\n // name: a context menu is named by aria-label.\n aria-labelledby={\n rest['aria-labelledby'] !== undefined\n ? rest['aria-labelledby']\n : triggerElement && !openOnContext && rest['aria-label'] === undefined\n ? labelledBy\n : undefined\n }\n {...presenceProps}\n ref={mergedRef}\n id={menuId}\n data-state={open ? 'open' : 'closed'}\n data-side={floatingProps['data-side']}\n data-align={floatingProps['data-align']}\n data-roving-container=\"\"\n style={{ ...positionStyle, ...style }}\n onKeyDown={handleKeyDown}\n onKeyDownCapture={withTypeaheadText(\n composeEventHandlers(onKeyDownCapture, rovingKeyDownCapture),\n )}\n onFocus={composeEventHandlers(onFocus, rovingFocus, { checkDefaultPrevented: false })}\n onPointerEnter={composeEventHandlers(onPointerEnter, hoverSurfaceHandlers.onPointerEnter)}\n onPointerLeave={composeEventHandlers(onPointerLeave, hoverSurfaceHandlers.onPointerLeave)}\n onPointerMove={composeEventHandlers(onPointerMove, listPointerMove)}\n onContextMenu={composeEventHandlers(onContextMenu, contextSurfaceHandlers.onContextMenu)}\n className={cn(menuPopoverClassNames.root, menuPopoverClasses, className)}\n >\n {children}\n </div>\n </MenuListContext.Provider>\n </Portal>\n );\n};\nMenuPopover.displayName = 'MenuPopover';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Menu.popover.cjs","names":["React","createHoverIntentGroup","useEventCallback","isOwnEvent","MENU_ITEM_SELECTOR","useMenuContext","usePopupTarget","usePresence","useMotionClasses","popupMotion","usePopupPosition","resolvePositioning","getTriggerFocusTarget","isConnectedAndFocusable","useDismiss","useTriggerFocusRef","useRovingTabIndex","useMergedRefs","PortalDepthContext","useCheckableRegistry","isEditableTarget","getArrowIntent","getDirection","Portal","MenuListContext","withTypeaheadText","composeEventHandlers","cn","menuPopoverClassNames","menuPopoverClasses","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useEventCallback","require_direction","require_focus","require_useRovingTabIndex","require_useMergedRefs","require_usePresence","require_usePopupPosition","require_useDismiss","require_useRestoreFocus","require_Portal","require_events","require_motion","require_useFocusBeforeClose","require_useHoverIntent","require_useMotion","require_useTriggerElement","require_Menu_context","require_Menu_shared","require_useResolvedTarget","react","react_jsx_runtime","SUBMENU_SHIFT","isElementTarget","target","useMenuListPointer","hoverGroup","hoverFocusingRef","event","item","root","menu","MenuPopover","targetProp","rest","popup","targetPending","positioning","targetElement","surface","setSurface","surfaceRef","setSurfaceElement","element","presenceRef","open","motionClassName","motion","className","positionedProps","side","isSubmenu","offset","floatingProps","_maxHeight","_maxWidth","positionStyle","setReference","fromContext","contextAnchor","triggerElement","getReturnFocus","opener","openOnContext","contextOpener","triggerRef","returnFocusRef","targetRef","dismiss","triggerFocusRef","unnamed","isMounted","rovingRef","rovingKeyDown","rovingKeyDownCapture","rovingFocus","mergedRef","ref","setFloating","registerSurface","focusFirst","focusLast","layerId","takeInitialFocus","isPositioned","active","portalDepth","registerCheckable","listPointerMove","listContext","closeChain","isHoverFocusing","handleKeyDown","onKeyDown","requestClose","labelledBy","presenceProps","menuId","style","onKeyDownCapture","onFocus","onPointerEnter","hoverSurfaceHandlers","onPointerLeave","onPointerMove","onContextMenu","contextSurfaceHandlers"],"sources":["../../../src/components/navigation/Menu.popover.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { menuPopoverClassNames } from '../../lib/classNames';\nimport { popupMotion } from '../../lib/motion';\nimport type {\n MotionSlot,\n PopupAlign,\n PopupPositioning,\n PopupSide,\n PopupTarget,\n PopupTargetInput,\n} from '../../lib/types';\nimport { usePopupTarget } from '../../hooks/useResolvedTarget';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isEditableTarget, isOwnEvent } from '../../lib/events';\nimport { isConnectedAndFocusable } from '../../lib/focus';\nimport { useDismiss } from '../../hooks/useDismiss';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useFocusBeforeClose } from '../../hooks/useFocusBeforeClose';\nimport { createHoverIntentGroup, type HoverIntentGroup } from '../../hooks/useHoverIntent';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useMotionClasses } from '../../hooks/useMotion';\nimport { resolvePositioning, usePopupPosition } from '../../hooks/usePopupPosition';\nimport { usePresence } from '../../hooks/usePresence';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { getTriggerFocusTarget, useTriggerFocusRef } from '../../hooks/useTriggerElement';\nimport { Portal, PortalDepthContext } from '../portal/Portal';\nimport { MenuListContext, useCheckableRegistry, useMenuContext } from './Menu.context';\nimport type { MenuContextValue, MenuListContextValue } from './Menu.context';\nimport {\n MENU_ITEM_SELECTOR,\n menuPopoverClasses,\n useStaticMenuPartWarning,\n withTypeaheadText,\n} from './Menu.shared';\n\n/** Properties for the MenuPopover sub-component. */\nexport interface MenuPopoverProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'id'> {\n /**\n * Side of the trigger the menu opens on (`start`/`end` follow the writing direction).\n * @default 'bottom' ('end' in a submenu)\n */\n side?: PopupSide;\n /** Alignment along that side. @default 'start' */\n align?: PopupAlign;\n /** Distance from the trigger in px. @default 4 (0 in a submenu) */\n offset?: number;\n /**\n * Where to place the menu instead of next to `Menu.Trigger`: an element or a `VirtualElement`\n * (a rectangle, such as a point; an inline object is fine). With a controlled `open`, a menu\n * with a `target` needs no trigger; name it with `aria-label`, and give a toggle button you use\n * as the target `aria-haspopup=\"menu\"` and `aria-expanded` yourself (the menu's `id` is\n * generated, so the toggle cannot point `aria-controls` at it). A press on a target element\n * does not close the menu. Hold the element in state, or pass a ref object (read after\n * each render of the menu). A menu opened by `openOnContext` is placed at\n * the gesture instead.\n */\n target?: PopupTargetInput;\n /**\n * Advanced positioning (Fluent's `positioning`): `offset`, `fitViewport`, `matchReferenceWidth`,\n * `fallbackPlacements` and `target` (used when the `target` prop is not set). `side` and `align`\n * stay separate props, and the `offset` prop wins over `positioning.offset`.\n * @default `{ fitViewport: true }`\n */\n positioning?: PopupPositioning;\n /**\n * The menu's motion. By default it fades in and slides 4px away from its trigger, on the side\n * it opened on (a submenu away from its parent menu), over 200 ms with a decelerating curve, and\n * fades out and slides back over 100 ms with an accelerating curve; under reduced motion it\n * appears and disappears at once. `null` turns the motion off (the surface still renders its\n * `data-presence` phases, which then end at once); a class string or `{ className }` replaces\n * the default classes with yours (see `MotionSlot`), also under a `WaveProvider` with\n * `motion=\"none\"`, which otherwise turns the default off. A `className` that holds\n * `data-[presence=…]` classes while `motion` is unset keeps 0.14's behaviour: no default motion,\n * your classes animate the surface. Fluent's `Menu` `surfaceMotion`.\n * @default the fade and slide above\n */\n motion?: MotionSlot | null;\n /** Menu items and dividers. */\n children: React.ReactNode;\n /**\n * Ref to the portaled `role=\"menu\"` surface. Its `id` is generated (the trigger's\n * `aria-controls` points to it), and it is labelled by the trigger unless `aria-label` or\n * `aria-labelledby` is given (one that holds `undefined` counts as not given).\n */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * A submenu with room on neither side of its trigger item is shifted across that side, over its\n * parent menu, to stay inside the viewport (as native and Fluent menus do).\n */\nconst SUBMENU_SHIFT = { padding: 8, crossAxis: true } as const;\n\n/** Whether a `target` is an element (duck typed, so an element of another realm counts). */\nfunction isElementTarget(target: PopupTarget | undefined): target is HTMLElement {\n return !!target && (target as Partial<Node>).nodeType === 1;\n}\n\n/**\n * Internal: the mouse behaviour of a menu list (the static root and every `Menu.Popover`\n * surface). While focus is inside a list of the menu tree (the chain's root list or any of its\n * submenus), a mouse `pointermove` over an enabled item of this list focuses it (`preventScroll`),\n * unless it already has focus or a submenu's safe zone of this list holds the point. Hover moves\n * no focus while focus is elsewhere, so a hover-opened menu or a static menu the user is not in\n * never takes focus from the page, and a Popover, Dialog or other portal opened from an item\n * keeps it. Also returns the list's hover group (the safe zones of its submenu trigger items) and\n * the flag the submenus of the list read while such a focus change runs.\n */\nexport function useMenuListPointer(menu: MenuContextValue): {\n hoverGroup: HoverIntentGroup;\n isHoverFocusing: () => boolean;\n onPointerMove: React.PointerEventHandler<HTMLElement>;\n} {\n const [hoverGroup] = React.useState(createHoverIntentGroup);\n const hoverFocusingRef = React.useRef(false);\n const isHoverFocusing = React.useCallback(() => hoverFocusingRef.current, []);\n const onPointerMove = useEventCallback((event: React.PointerEvent<HTMLElement>) => {\n if (event.pointerType === 'touch' || event.pointerType === 'pen' || !isOwnEvent(event)) return;\n const target = event.target as Element;\n const item = target.closest<HTMLElement>(MENU_ITEM_SELECTOR);\n if (!item || !event.currentTarget.contains(item)) return;\n if (item.getAttribute('aria-disabled') === 'true') return;\n if (item.ownerDocument.activeElement === item) return;\n let root = menu;\n while (root.parent) root = root.parent;\n if (!root.listContainsFocus() || hoverGroup.isHeld(event.clientX, event.clientY)) return;\n hoverFocusingRef.current = true;\n item.focus({ preventScroll: true });\n // A submenu that just lost focus is dismissed (focus outside) in a microtask the focus change\n // queued; the flag is cleared after it.\n queueMicrotask(() => {\n hoverFocusingRef.current = false;\n });\n });\n return { hoverGroup, isHoverFocusing, onPointerMove };\n}\n\n/**\n * The portaled `role=\"menu\"` surface of a popup menu, positioned next to `Menu.Trigger`. A menu\n * taller than the space available scrolls inside the viewport: the surface is limited to the space\n * next to the trigger (`max-height`/`max-width` classes, which a `max-h-*`/`max-w-*` class in\n * `className` or a `style` replaces) and scrolls, and an item that receives focus is scrolled into\n * view. Focus moves to the first (ArrowUp: last) enabled item when it opens; arrows, Home/End and\n * typeahead move between enabled items. Escape closes it and returns focus to the trigger. An\n * outside press closes it and leaves focus where the press put it (on the trigger only when focus\n * was still in the menu or lost to the page). Tab closes it and moves focus to the trigger without\n * preventing the default, so tabbing continues from the trigger (inside a Dialog, the focus trap\n * moves on from there). The trigger here is the element that takes its focus: for a wrapper span,\n * the element inside it that carries the state ARIA (the span itself when you made it the trigger\n * with a `role` such as `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n * Keys from a portal opened inside the menu (a Popover of an item) are left to that portal: Tab\n * there moves on inside it and keeps the menu open.\n *\n * In a submenu it opens at the end side of its trigger item (`side=\"end\"`, `offset={0}`) and\n * flips to fit the viewport; with room on neither side, it overlaps its parent menu inside the\n * viewport. ArrowLeft (ArrowRight in RTL) and Escape close only the submenu and return focus to\n * its trigger item; item activation and Tab close every menu of the chain and put focus on the\n * root trigger.\n *\n * While focus is inside the menu (or one of its submenus), the item under the mouse pointer takes\n * focus, so Enter activates the item you point at. Focus in a Popover, Dialog or other portal\n * opened from an item stays there.\n *\n * A context menu (`openOnContext`) opens at the pointer or at the focused row and returns focus to\n * the element focused at the gesture; it is not labelled by its region, so give it `aria-label`\n * (development warning otherwise), as for a menu placed at a `target` without `Menu.Trigger`.\n *\n * It moves in and out: the surface fades in and slides 4px away from its trigger over 200 ms, and\n * fades out and slides back over 100 ms, on the side it opened on (`data-side`), so a submenu\n * slides out of its parent menu; a menu open by default animates in when it mounts in the\n * browser. Under reduced motion it appears and disappears at once. `motion` turns the motion off\n * (`null`) or replaces its classes, and a `WaveProvider` with `motion=\"none\"` turns the default\n * off; a `className` with `data-[presence=…]` classes and no `motion` keeps 0.14's behaviour (your\n * classes, no default motion). The surface mounts through the presence core (`usePresence`): it\n * carries `data-presence=\"entering\" | \"entered\" | \"exiting\"` and, while it closes,\n * `data-state=\"closed\"` and `inert`, so it stays on screen, where it was, until its exit motion\n * ends. Focus, the dismiss layer and positioning follow the open state, not the exit: focus\n * inside a closing menu leaves it in the commit that closes it. Without motion it unmounts as\n * soon as it closes.\n *\n * Also exported as `MenuPopover` (import the flat name from React Server Components).\n */\nexport const MenuPopover = ({\n side,\n align = 'start',\n offset,\n target: targetProp,\n positioning,\n motion,\n children,\n className,\n style,\n onKeyDown,\n onKeyDownCapture,\n onFocus,\n onPointerEnter,\n onPointerLeave,\n onPointerMove,\n onContextMenu,\n ref,\n ...rest\n}: MenuPopoverProps) => {\n const menu = useMenuContext('Menu.Popover');\n const {\n popup,\n open,\n takeInitialFocus,\n registerSurface,\n menuId,\n labelledBy,\n triggerRef,\n triggerElement,\n isSubmenu,\n requestClose,\n closeChain,\n dismiss,\n hoverSurfaceHandlers,\n isHoverClose,\n openOnContext,\n contextSurfaceHandlers,\n contextAnchor,\n fromContext,\n contextOpener,\n } = menu;\n useStaticMenuPartWarning('Menu.Popover', popup);\n const { target, pending: targetPending } = usePopupTarget(\n 'Menu.Popover',\n targetProp,\n positioning,\n );\n const targetElement = isElementTarget(target) ? target : null;\n\n const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n const surfaceRef = React.useRef<HTMLDivElement | null>(null);\n const setSurfaceElement = React.useCallback((element: HTMLDivElement | null) => {\n surfaceRef.current = element;\n setSurface(element);\n }, []);\n\n // The surface mounts and unmounts through the presence core, and enters also when it mounts open\n // (D9: a menu open by default animates in on a client render as after hydration); everything\n // else below keys on `open`, so focus returns and the layer goes on close, not after the exit.\n const { isMounted, ref: presenceRef, presenceProps } = usePresence(open, { appear: true });\n // The motion classes (a `className` with presence variants keeps 0.14's own motion, D19).\n const motionClassName = useMotionClasses(motion, popupMotion, className);\n\n const {\n setReference,\n setFloating,\n floatingProps: positionedProps,\n isPositioned,\n } = usePopupPosition({\n open,\n side: side ?? (isSubmenu ? 'end' : 'bottom'),\n align,\n shift: isSubmenu ? SUBMENU_SHIFT : undefined,\n ...resolvePositioning(positioning, { offset: isSubmenu ? 0 : 4, fitViewport: true }),\n ...(offset !== undefined && { offset }),\n });\n // A ref target that holds no element yet keeps the popup hidden (as TeachingPopover's is).\n const floatingProps = targetPending\n ? { ...positionedProps, style: { ...positionedProps.style, visibility: 'hidden' as const } }\n : positionedProps;\n // The size limits come from menuPopoverClasses, which a consumer class can replace; an inline\n // max-height/max-width would beat every class.\n const { maxHeight: _maxHeight, maxWidth: _maxWidth, ...positionStyle } = floatingProps.style;\n // The positioning reference: the anchor of a context gesture (the point, else the focused row,\n // else the trigger's focus target), else `target`, else the trigger. Kept while the surface\n // exits, so it does not jump; a new inline VirtualElement only recomputes the position.\n React.useLayoutEffect(() => {\n setReference(\n fromContext\n ? (contextAnchor ?? getTriggerFocusTarget(triggerElement) ?? triggerElement)\n : (target ?? triggerElement),\n );\n }, [setReference, contextAnchor, fromContext, target, triggerElement]);\n\n // Where focus returns when the menu closes (item activation, Tab, Escape): in a context menu,\n // the element focused at the gesture when it can take focus; else the element that takes focus\n // for the trigger (for a wrapper span, the element inside it that carries the state ARIA; for a\n // submenu, its trigger item); else a focusable `target` element.\n const getReturnFocus = useEventCallback((): HTMLElement | null => {\n const opener = openOnContext ? contextOpener.current : null;\n if (opener && isConnectedAndFocusable(opener)) return opener;\n const triggerTarget = getTriggerFocusTarget(triggerRef.current);\n if (triggerTarget) return triggerTarget;\n return targetElement && isConnectedAndFocusable(targetElement) ? targetElement : null;\n });\n\n // The layer's anchor (where a surface opened from an item that is gone by then restores focus):\n // the return target, else the trigger itself.\n const returnFocusRef = React.useMemo<React.RefObject<HTMLElement | null>>(\n () => ({\n get current() {\n return getReturnFocus() ?? triggerRef.current;\n },\n }),\n [getReturnFocus, triggerRef],\n );\n // A context region is not part of the layer (a press on another row closes the menu), and a\n // Ctrl+press there is a macOS context click, which moves the menu instead; a target element is.\n const targetRef = { current: targetElement };\n const { layerId } = useDismiss({\n open,\n onDismiss: dismiss,\n refs: openOnContext ? [surfaceRef, targetRef] : [surfaceRef, triggerRef, targetRef],\n anchorRef: returnFocusRef,\n kind: 'menu',\n focusOutside: true,\n outsidePress: openOnContext\n ? (event) =>\n !(\n event.ctrlKey &&\n event.target instanceof Node &&\n triggerRef.current?.contains(event.target)\n )\n : true,\n });\n\n const triggerFocusRef = useTriggerFocusRef(triggerRef);\n\n useRestoreFocus({\n enabled: open,\n container: surface,\n // A context menu returns focus to the opener (the focused row), not to the region.\n triggerRef: openOnContext ? undefined : triggerFocusRef,\n finalFocusRef: openOnContext ? contextOpener : undefined,\n fallback: getReturnFocus,\n onlyIfFocusInside: true,\n // A hover close moves no focus (a submenu closing with it is taken along by the hook).\n isHoverClose,\n });\n\n // C-DEV: a surface that no trigger labels needs its own name.\n const unnamed =\n isMounted &&\n (openOnContext || (target != null && !triggerElement)) &&\n rest['aria-label'] === undefined &&\n rest['aria-labelledby'] === undefined;\n React.useEffect(() => {\n if (!unnamed) return;\n warnOnce(\n 'Menu.Popover:name',\n 'Menu.Popover: this menu has no trigger to name it (a context menu, or a menu placed at a `target` without Menu.Trigger): give Menu.Popover an aria-label or aria-labelledby.',\n );\n }, [unnamed]);\n\n const {\n containerProps: { ref: rovingRef },\n handleKeyDown: rovingKeyDown,\n handleKeyDownCapture: rovingKeyDownCapture,\n handleFocus: rovingFocus,\n focusFirst,\n focusLast,\n } = useRovingTabIndex({\n orientation: 'vertical',\n loop: true,\n typeahead: true,\n manageTabIndex: true,\n itemSelector: MENU_ITEM_SELECTOR,\n });\n\n const mergedRef = useMergedRefs<HTMLDivElement>(\n ref,\n setSurfaceElement,\n rovingRef,\n setFloating,\n presenceRef,\n );\n\n // Lets the trigger move focus into an already open menu (ArrowDown/ArrowUp on the trigger) and\n // the root reach the surface. Only an open surface registers, and it unregisters in the commit\n // that closes the menu: a surface that stays mounted while it exits would otherwise make the next\n // opening focus its (inert) items instead of opening the menu.\n React.useLayoutEffect(() => {\n if (!surface || !open) return;\n registerSurface({ focusFirst, focusLast, surface, layerId, getReturnFocus });\n return () => registerSurface(null);\n }, [surface, open, registerSurface, focusFirst, focusLast, layerId, getReturnFocus]);\n\n // Focus before close, on every close: when the menu closes with focus inside it, focus moves in\n // the closing commit to where useRestoreFocus would put it, in its order: the context opener,\n // the element focused when the menu opened (the trigger's focus target first, but not in a\n // context menu, whose region is no opener), then the return target (a menu with a `target` and\n // no trigger returns focus to its opener, not to a focusable target element). A Dialog opened\n // by the item that closed the menu then records that element as its opener, not the item, which\n // the exiting surface still holds. Unmounting is left to useRestoreFocus.\n useFocusBeforeClose({\n open,\n surfaceRef,\n captureOpener: () => (openOnContext ? null : triggerFocusRef.current),\n candidates: (opener) => [\n openOnContext ? contextOpener.current : null,\n opener,\n getReturnFocus(),\n ],\n });\n\n // Initial focus: the first (or last) enabled item, unless focus is already inside. A hover\n // opening moves no focus.\n React.useLayoutEffect(() => {\n if (!open || !surface) return;\n if (surface.contains(surface.ownerDocument.activeElement)) return;\n const target = takeInitialFocus();\n if (target === 'last') focusLast();\n else if (target === 'first') focusFirst();\n }, [open, surface, takeInitialFocus, focusFirst, focusLast]);\n\n // The initial focus lands before the surface is limited to the available height (floating-ui\n // measures after mount), so it scrolls nothing: once positioned, the focused item (the last one\n // after ArrowUp) is scrolled into view. Later focus moves scroll through the native focus().\n React.useLayoutEffect(() => {\n if (!isPositioned || !surface) return;\n const active = surface.ownerDocument.activeElement as HTMLElement | null;\n if (active && active !== surface && surface.contains(active)) {\n active.scrollIntoView?.({ block: 'nearest' });\n }\n }, [isPositioned, surface]);\n\n // The list the items render in. Its children sit inside the Portal, one portal level deeper.\n // Item activation closes the whole chain; the item under the mouse takes focus while focus is\n // inside the menu tree.\n const portalDepth = React.useContext(PortalDepthContext) + 1;\n const registerCheckable = useCheckableRegistry();\n const { hoverGroup, isHoverFocusing, onPointerMove: listPointerMove } = useMenuListPointer(menu);\n const listContext = React.useMemo<MenuListContextValue>(\n () => ({\n menu,\n isStatic: false,\n portalDepth,\n closeFromItem: closeChain,\n registerCheckable,\n hoverGroup,\n isHoverFocusing,\n }),\n [menu, portalDepth, closeChain, registerCheckable, hoverGroup, isHoverFocusing],\n );\n\n // C-COMPOSE: the consumer's onKeyDown runs first; preventDefault() skips the built-in keys. A key\n // from a portal opened inside the menu (a Popover of an item, a submenu) is that portal's: Tab\n // moves on inside it and never closes the menu.\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || !isOwnEvent(event)) return;\n if (event.key === 'Tab') {\n // Close every menu of the chain and put focus on the root trigger; the default Tab action\n // then continues from there.\n closeChain();\n return;\n }\n // \"Previous\" (ArrowLeft, ArrowRight in RTL) closes a submenu and returns to its trigger item.\n if (\n isSubmenu &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !isEditableTarget(event.target) &&\n getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n }) === 'prev'\n ) {\n event.preventDefault();\n getReturnFocus()?.focus({ preventScroll: true });\n requestClose();\n return;\n }\n rovingKeyDown(event);\n };\n\n if (!isMounted) return null;\n\n return (\n <Portal layerId={layerId}>\n <MenuListContext.Provider value={listContext}>\n <div\n role=\"menu\"\n {...rest}\n // After the spread: a consumer name wins when it is defined, and a forwarded key that\n // holds `undefined` does not remove the trigger's. A context region's whole text is no\n // name: a context menu is named by aria-label.\n aria-labelledby={\n rest['aria-labelledby'] !== undefined\n ? rest['aria-labelledby']\n : triggerElement && !openOnContext && rest['aria-label'] === undefined\n ? labelledBy\n : undefined\n }\n {...presenceProps}\n ref={mergedRef}\n id={menuId}\n data-state={open ? 'open' : 'closed'}\n data-side={floatingProps['data-side']}\n data-align={floatingProps['data-align']}\n data-roving-container=\"\"\n style={{ ...positionStyle, ...style }}\n onKeyDown={handleKeyDown}\n onKeyDownCapture={withTypeaheadText(\n composeEventHandlers(onKeyDownCapture, rovingKeyDownCapture),\n )}\n onFocus={composeEventHandlers(onFocus, rovingFocus, { checkDefaultPrevented: false })}\n onPointerEnter={composeEventHandlers(onPointerEnter, hoverSurfaceHandlers.onPointerEnter)}\n onPointerLeave={composeEventHandlers(onPointerLeave, hoverSurfaceHandlers.onPointerLeave)}\n onPointerMove={composeEventHandlers(onPointerMove, listPointerMove)}\n onContextMenu={composeEventHandlers(onContextMenu, contextSurfaceHandlers.onContextMenu)}\n className={cn(menuPopoverClassNames.root, menuPopoverClasses, motionClassName, className)}\n >\n {children}\n </div>\n </MenuListContext.Provider>\n </Portal>\n );\n};\nMenuPopover.displayName = 'MenuPopover';\n"],"mappings":"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"}
|