@mortenbrudvik/waveui 0.14.1 → 0.16.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.
Files changed (265) hide show
  1. package/README.md +413 -53
  2. package/dist/components/data-display/InfoButton.cjs +1 -1
  3. package/dist/components/data-display/InfoButton.cjs.map +1 -1
  4. package/dist/components/data-display/InfoButton.mjs +90 -82
  5. package/dist/components/data-display/InfoButton.mjs.map +1 -1
  6. package/dist/components/data-display/InfoLabel.cjs +1 -1
  7. package/dist/components/data-display/InfoLabel.cjs.map +1 -1
  8. package/dist/components/data-display/InfoLabel.mjs +19 -18
  9. package/dist/components/data-display/InfoLabel.mjs.map +1 -1
  10. package/dist/components/data-display/List.cjs +1 -1
  11. package/dist/components/data-display/List.cjs.map +1 -1
  12. package/dist/components/data-display/List.mjs +405 -219
  13. package/dist/components/data-display/List.mjs.map +1 -1
  14. package/dist/components/data-display/List.registry.cjs +1 -1
  15. package/dist/components/data-display/List.registry.cjs.map +1 -1
  16. package/dist/components/data-display/List.registry.mjs +12 -6
  17. package/dist/components/data-display/List.registry.mjs.map +1 -1
  18. package/dist/components/feedback/MessageBarGroup.cjs +2 -0
  19. package/dist/components/feedback/MessageBarGroup.cjs.map +1 -0
  20. package/dist/components/feedback/MessageBarGroup.mjs +63 -0
  21. package/dist/components/feedback/MessageBarGroup.mjs.map +1 -0
  22. package/dist/components/feedback/ProgressBar.cjs +1 -1
  23. package/dist/components/feedback/ProgressBar.cjs.map +1 -1
  24. package/dist/components/feedback/ProgressBar.mjs +41 -39
  25. package/dist/components/feedback/ProgressBar.mjs.map +1 -1
  26. package/dist/components/feedback/Toaster.cjs +1 -1
  27. package/dist/components/feedback/Toaster.cjs.map +1 -1
  28. package/dist/components/feedback/Toaster.mjs +222 -216
  29. package/dist/components/feedback/Toaster.mjs.map +1 -1
  30. package/dist/components/input/Combobox.cjs +1 -1
  31. package/dist/components/input/Combobox.cjs.map +1 -1
  32. package/dist/components/input/Combobox.mjs +163 -148
  33. package/dist/components/input/Combobox.mjs.map +1 -1
  34. package/dist/components/input/Dropdown.cjs +1 -1
  35. package/dist/components/input/Dropdown.cjs.map +1 -1
  36. package/dist/components/input/Dropdown.mjs +132 -117
  37. package/dist/components/input/Dropdown.mjs.map +1 -1
  38. package/dist/components/input/Listbox.cjs +1 -1
  39. package/dist/components/input/Listbox.cjs.map +1 -1
  40. package/dist/components/input/Listbox.mjs +90 -78
  41. package/dist/components/input/Listbox.mjs.map +1 -1
  42. package/dist/components/input/Option.cjs +1 -1
  43. package/dist/components/input/Option.cjs.map +1 -1
  44. package/dist/components/input/Option.data.cjs +2 -0
  45. package/dist/components/input/Option.data.cjs.map +1 -0
  46. package/dist/components/input/Option.data.mjs +114 -0
  47. package/dist/components/input/Option.data.mjs.map +1 -0
  48. package/dist/components/input/Option.mjs +21 -17
  49. package/dist/components/input/Option.mjs.map +1 -1
  50. package/dist/components/layout/Accordion.cjs +1 -1
  51. package/dist/components/layout/Accordion.cjs.map +1 -1
  52. package/dist/components/layout/Accordion.mjs +124 -109
  53. package/dist/components/layout/Accordion.mjs.map +1 -1
  54. package/dist/components/layout/Carousel.cjs +1 -1
  55. package/dist/components/layout/Carousel.cjs.map +1 -1
  56. package/dist/components/layout/Carousel.mjs +207 -193
  57. package/dist/components/layout/Carousel.mjs.map +1 -1
  58. package/dist/components/layout/FlatTree.cjs +2 -0
  59. package/dist/components/layout/FlatTree.cjs.map +1 -0
  60. package/dist/components/layout/FlatTree.context.cjs +2 -0
  61. package/dist/components/layout/FlatTree.context.cjs.map +1 -0
  62. package/dist/components/layout/FlatTree.context.mjs +20 -0
  63. package/dist/components/layout/FlatTree.context.mjs.map +1 -0
  64. package/dist/components/layout/FlatTree.item.cjs +2 -0
  65. package/dist/components/layout/FlatTree.item.cjs.map +1 -0
  66. package/dist/components/layout/FlatTree.item.mjs +90 -0
  67. package/dist/components/layout/FlatTree.item.mjs.map +1 -0
  68. package/dist/components/layout/FlatTree.mjs +276 -0
  69. package/dist/components/layout/FlatTree.mjs.map +1 -0
  70. package/dist/components/layout/TabList.cjs +1 -1
  71. package/dist/components/layout/TabList.cjs.map +1 -1
  72. package/dist/components/layout/TabList.mjs +149 -108
  73. package/dist/components/layout/TabList.mjs.map +1 -1
  74. package/dist/components/layout/Tree.cjs.map +1 -1
  75. package/dist/components/layout/Tree.context.cjs +1 -1
  76. package/dist/components/layout/Tree.context.cjs.map +1 -1
  77. package/dist/components/layout/Tree.context.mjs +2 -1
  78. package/dist/components/layout/Tree.context.mjs.map +1 -1
  79. package/dist/components/layout/Tree.core.cjs +1 -1
  80. package/dist/components/layout/Tree.core.cjs.map +1 -1
  81. package/dist/components/layout/Tree.core.mjs +162 -148
  82. package/dist/components/layout/Tree.core.mjs.map +1 -1
  83. package/dist/components/layout/Tree.mjs.map +1 -1
  84. package/dist/components/layout/Tree.selection.cjs +1 -1
  85. package/dist/components/layout/Tree.selection.cjs.map +1 -1
  86. package/dist/components/layout/Tree.selection.mjs +11 -57
  87. package/dist/components/layout/Tree.selection.mjs.map +1 -1
  88. package/dist/components/layout/useFlatTree.cjs +2 -0
  89. package/dist/components/layout/useFlatTree.cjs.map +1 -0
  90. package/dist/components/layout/useFlatTree.mjs +83 -0
  91. package/dist/components/layout/useFlatTree.mjs.map +1 -0
  92. package/dist/components/navigation/Menu.popover.cjs +1 -1
  93. package/dist/components/navigation/Menu.popover.cjs.map +1 -1
  94. package/dist/components/navigation/Menu.popover.mjs +154 -168
  95. package/dist/components/navigation/Menu.popover.mjs.map +1 -1
  96. package/dist/components/navigation/Nav.cjs +1 -1
  97. package/dist/components/navigation/Nav.cjs.map +1 -1
  98. package/dist/components/navigation/Nav.mjs +156 -136
  99. package/dist/components/navigation/Nav.mjs.map +1 -1
  100. package/dist/components/navigation/NavDrawer.cjs +1 -1
  101. package/dist/components/navigation/NavDrawer.cjs.map +1 -1
  102. package/dist/components/navigation/NavDrawer.mjs +48 -45
  103. package/dist/components/navigation/NavDrawer.mjs.map +1 -1
  104. package/dist/components/overlays/Dialog.cjs +1 -1
  105. package/dist/components/overlays/Dialog.cjs.map +1 -1
  106. package/dist/components/overlays/Dialog.mjs +128 -122
  107. package/dist/components/overlays/Dialog.mjs.map +1 -1
  108. package/dist/components/overlays/Dialog.slots.cjs +1 -1
  109. package/dist/components/overlays/Dialog.slots.cjs.map +1 -1
  110. package/dist/components/overlays/Dialog.slots.mjs +12 -12
  111. package/dist/components/overlays/Dialog.slots.mjs.map +1 -1
  112. package/dist/components/overlays/Drawer.cjs.map +1 -1
  113. package/dist/components/overlays/Drawer.mjs.map +1 -1
  114. package/dist/components/overlays/Drawer.panel.cjs +1 -1
  115. package/dist/components/overlays/Drawer.panel.cjs.map +1 -1
  116. package/dist/components/overlays/Drawer.panel.mjs +97 -81
  117. package/dist/components/overlays/Drawer.panel.mjs.map +1 -1
  118. package/dist/components/overlays/Drawer.root.cjs +1 -1
  119. package/dist/components/overlays/Drawer.root.cjs.map +1 -1
  120. package/dist/components/overlays/Drawer.root.mjs +34 -31
  121. package/dist/components/overlays/Drawer.root.mjs.map +1 -1
  122. package/dist/components/overlays/Popover.cjs +1 -1
  123. package/dist/components/overlays/Popover.cjs.map +1 -1
  124. package/dist/components/overlays/Popover.mjs +231 -216
  125. package/dist/components/overlays/Popover.mjs.map +1 -1
  126. package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
  127. package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
  128. package/dist/components/overlays/TeachingPopover.parts.cjs +1 -1
  129. package/dist/components/overlays/TeachingPopover.parts.cjs.map +1 -1
  130. package/dist/components/overlays/TeachingPopover.parts.mjs +199 -177
  131. package/dist/components/overlays/TeachingPopover.parts.mjs.map +1 -1
  132. package/dist/components/overlays/TeachingPopover.root.cjs +1 -1
  133. package/dist/components/overlays/TeachingPopover.root.cjs.map +1 -1
  134. package/dist/components/overlays/TeachingPopover.root.mjs +93 -92
  135. package/dist/components/overlays/TeachingPopover.root.mjs.map +1 -1
  136. package/dist/components/overlays/Tooltip.cjs +1 -1
  137. package/dist/components/overlays/Tooltip.cjs.map +1 -1
  138. package/dist/components/overlays/Tooltip.mjs +66 -61
  139. package/dist/components/overlays/Tooltip.mjs.map +1 -1
  140. package/dist/components/provider/WaveProvider.cjs +1 -1
  141. package/dist/components/provider/WaveProvider.cjs.map +1 -1
  142. package/dist/components/provider/WaveProvider.mjs +26 -23
  143. package/dist/components/provider/WaveProvider.mjs.map +1 -1
  144. package/dist/components/table/DataGrid.cjs +1 -1
  145. package/dist/components/table/DataGrid.cjs.map +1 -1
  146. package/dist/components/table/DataGrid.context.cjs +2 -0
  147. package/dist/components/table/DataGrid.context.cjs.map +1 -0
  148. package/dist/components/table/DataGrid.context.mjs +74 -0
  149. package/dist/components/table/DataGrid.context.mjs.map +1 -0
  150. package/dist/components/table/DataGrid.header.cjs +2 -0
  151. package/dist/components/table/DataGrid.header.cjs.map +1 -0
  152. package/dist/components/table/DataGrid.header.mjs +168 -0
  153. package/dist/components/table/DataGrid.header.mjs.map +1 -0
  154. package/dist/components/table/DataGrid.mjs +488 -591
  155. package/dist/components/table/DataGrid.mjs.map +1 -1
  156. package/dist/components/table/DataGrid.sizing.cjs +2 -0
  157. package/dist/components/table/DataGrid.sizing.cjs.map +1 -0
  158. package/dist/components/table/DataGrid.sizing.mjs +187 -0
  159. package/dist/components/table/DataGrid.sizing.mjs.map +1 -0
  160. package/dist/components/table/DataGrid.store.cjs +2 -0
  161. package/dist/components/table/DataGrid.store.cjs.map +1 -0
  162. package/dist/components/table/DataGrid.store.mjs +108 -0
  163. package/dist/components/table/DataGrid.store.mjs.map +1 -0
  164. package/dist/components/table/DataGrid.window.cjs +2 -0
  165. package/dist/components/table/DataGrid.window.cjs.map +1 -0
  166. package/dist/components/table/DataGrid.window.mjs +165 -0
  167. package/dist/components/table/DataGrid.window.mjs.map +1 -0
  168. package/dist/components/table/Table.cjs +1 -1
  169. package/dist/components/table/Table.cjs.map +1 -1
  170. package/dist/components/table/Table.mjs +74 -72
  171. package/dist/components/table/Table.mjs.map +1 -1
  172. package/dist/components/table/Table.resize.cjs +2 -0
  173. package/dist/components/table/Table.resize.cjs.map +1 -0
  174. package/dist/components/table/Table.resize.mjs +98 -0
  175. package/dist/components/table/Table.resize.mjs.map +1 -0
  176. package/dist/components/table/useGridNavigation.cjs +1 -1
  177. package/dist/components/table/useGridNavigation.cjs.map +1 -1
  178. package/dist/components/table/useGridNavigation.mjs +343 -140
  179. package/dist/components/table/useGridNavigation.mjs.map +1 -1
  180. package/dist/components/table/useTableColumnSizing.cjs +2 -0
  181. package/dist/components/table/useTableColumnSizing.cjs.map +1 -0
  182. package/dist/components/table/useTableColumnSizing.mjs +76 -0
  183. package/dist/components/table/useTableColumnSizing.mjs.map +1 -0
  184. package/dist/components/table/useTableFeatures.cjs +2 -0
  185. package/dist/components/table/useTableFeatures.cjs.map +1 -0
  186. package/dist/components/table/useTableFeatures.mjs +110 -0
  187. package/dist/components/table/useTableFeatures.mjs.map +1 -0
  188. package/dist/components/table/useTableSelection.cjs +2 -0
  189. package/dist/components/table/useTableSelection.cjs.map +1 -0
  190. package/dist/components/table/useTableSelection.mjs +39 -0
  191. package/dist/components/table/useTableSelection.mjs.map +1 -0
  192. package/dist/components/table/useTableSort.cjs +2 -0
  193. package/dist/components/table/useTableSort.cjs.map +1 -0
  194. package/dist/components/table/useTableSort.mjs +58 -0
  195. package/dist/components/table/useTableSort.mjs.map +1 -0
  196. package/dist/hooks/useActiveDescendant.cjs +1 -1
  197. package/dist/hooks/useActiveDescendant.cjs.map +1 -1
  198. package/dist/hooks/useActiveDescendant.mjs +33 -25
  199. package/dist/hooks/useActiveDescendant.mjs.map +1 -1
  200. package/dist/hooks/useCollapsePresence.cjs +2 -0
  201. package/dist/hooks/useCollapsePresence.cjs.map +1 -0
  202. package/dist/hooks/useCollapsePresence.mjs +21 -0
  203. package/dist/hooks/useCollapsePresence.mjs.map +1 -0
  204. package/dist/hooks/useFocusBeforeClose.cjs +2 -0
  205. package/dist/hooks/useFocusBeforeClose.cjs.map +1 -0
  206. package/dist/hooks/useFocusBeforeClose.mjs +33 -0
  207. package/dist/hooks/useFocusBeforeClose.mjs.map +1 -0
  208. package/dist/hooks/useListbox.cjs +1 -1
  209. package/dist/hooks/useListbox.cjs.map +1 -1
  210. package/dist/hooks/useListbox.mjs +140 -130
  211. package/dist/hooks/useListbox.mjs.map +1 -1
  212. package/dist/hooks/useMotion.cjs +2 -0
  213. package/dist/hooks/useMotion.cjs.map +1 -0
  214. package/dist/hooks/useMotion.mjs +14 -0
  215. package/dist/hooks/useMotion.mjs.map +1 -0
  216. package/dist/hooks/usePresenceGroup.cjs +2 -0
  217. package/dist/hooks/usePresenceGroup.cjs.map +1 -0
  218. package/dist/hooks/usePresenceGroup.mjs +68 -0
  219. package/dist/hooks/usePresenceGroup.mjs.map +1 -0
  220. package/dist/hooks/useRovingTabIndex.cjs +1 -1
  221. package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
  222. package/dist/hooks/useRovingTabIndex.mjs +1 -1
  223. package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
  224. package/dist/hooks/useSelection.cjs +2 -0
  225. package/dist/hooks/useSelection.cjs.map +1 -0
  226. package/dist/hooks/useSelection.mjs +57 -0
  227. package/dist/hooks/useSelection.mjs.map +1 -0
  228. package/dist/hooks/useVirtualWindow.cjs +2 -0
  229. package/dist/hooks/useVirtualWindow.cjs.map +1 -0
  230. package/dist/hooks/useVirtualWindow.mjs +102 -0
  231. package/dist/hooks/useVirtualWindow.mjs.map +1 -0
  232. package/dist/index.cjs +1 -1
  233. package/dist/index.d.cts +2249 -179
  234. package/dist/index.d.ts +2249 -179
  235. package/dist/index.mjs +147 -135
  236. package/dist/lib/classNames.cjs +1 -1
  237. package/dist/lib/classNames.cjs.map +1 -1
  238. package/dist/lib/classNames.mjs +125 -95
  239. package/dist/lib/classNames.mjs.map +1 -1
  240. package/dist/lib/columnSizing.cjs +2 -0
  241. package/dist/lib/columnSizing.cjs.map +1 -0
  242. package/dist/lib/columnSizing.mjs +27 -0
  243. package/dist/lib/columnSizing.mjs.map +1 -0
  244. package/dist/lib/flatTree.cjs +2 -0
  245. package/dist/lib/flatTree.cjs.map +1 -0
  246. package/dist/lib/flatTree.mjs +118 -0
  247. package/dist/lib/flatTree.mjs.map +1 -0
  248. package/dist/lib/motion.cjs +2 -0
  249. package/dist/lib/motion.cjs.map +1 -0
  250. package/dist/lib/motion.mjs +43 -0
  251. package/dist/lib/motion.mjs.map +1 -0
  252. package/dist/lib/selection.cjs +2 -0
  253. package/dist/lib/selection.cjs.map +1 -0
  254. package/dist/lib/selection.mjs +28 -0
  255. package/dist/lib/selection.mjs.map +1 -0
  256. package/dist/lib/treeCascade.cjs +2 -0
  257. package/dist/lib/treeCascade.cjs.map +1 -0
  258. package/dist/lib/treeCascade.mjs +52 -0
  259. package/dist/lib/treeCascade.mjs.map +1 -0
  260. package/dist/lib/virtual.cjs +2 -0
  261. package/dist/lib/virtual.cjs.map +1 -0
  262. package/dist/lib/virtual.mjs +54 -0
  263. package/dist/lib/virtual.mjs.map +1 -0
  264. package/dist/styles.css +1 -1
  265. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Nav.mjs","names":["_Fragment","useId","useId$1","React","iconClasses","renderIcon","icon","slotRendersContent","renderSlot","cn","className","itemClasses","focusRingInset","disabledStyles","subItemClasses","rowClasses","rowHoverClasses","actionsClasses","categoryButtonClasses","opensElsewhere","event","link","target","renderNavEntry","rest","props","isSelected","context","value","isLink","href","rovingProps","roving","hasActions","actions","itemId","generatedId","idProps","handleClick","disabled","onClick","content","Fragment","withIcon","stable","children","entryClassName","classes","listItemClassName","actionsGroup","materialiseSlotContent","buttonRest","NavCategory","useNavContext","NavRovingContext","currentValue","listId","isOpen","openCategories","holdsCurrentChild","containsValue","holdsShownCurrent","categoryStore","containsCurrent","currentCategory","listRef","buttonLabel","label","items","parts","isText","part","navCategoryClassNames","toggleCategory","ChevronDownIcon","NavCategoryValueContext","markNavPart","NavItem","useNavValue","useRecordCategory","navItemClassNames","NavSubItem","navSubItemClassNames","Nav","NavRoot","NavSectionHeader","NavDivider","NavAppItem","NavAppItemStatic"],"sources":["../../../src/components/navigation/Nav.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n navCategoryClassNames,\n navItemClassNames,\n navSubItemClassNames,\n} from '../../lib/classNames';\nimport type { Slot } from '../../lib/types';\nimport { materialiseSlotContent, renderSlot, slotRendersContent } from '../../lib/slot';\nimport { warnDeprecated } from '../../lib/dev';\nimport { ChevronDownIcon } from '../../lib/icons';\nimport { disabledStyles, focusRingInset } from '../../lib/styles';\nimport { useId } from '../../hooks/useId';\nimport {\n NavCategoryValueContext,\n NavRovingContext,\n containsValue,\n markNavPart,\n useNavContext,\n useNavListChildCheck,\n useNavValue,\n useRecordCategory,\n type NavContextValue,\n type NavRovingContextValue,\n type NoAnchorOnlyAttributes,\n} from './Nav.context';\nimport { NavAppItem, NavAppItemStatic, NavDivider, NavSectionHeader } from './Nav.parts';\nimport { NavRoot } from './Nav.root';\n\n/*\n * The Nav compound: the item types, styles and rendering of Nav.Item and Nav.SubItem, Nav.Category,\n * the `Object.assign` with its JSDoc, the flat names and the type re-exports. Nothing imports this\n * module but the barrel: the root (`Nav.root.tsx`) and the contexts (`Nav.context.ts`) recognise\n * the parts by the markers set next to each `displayName` below; the structural parts live in\n * `Nav.parts.tsx`.\n */\n\nexport type { NavProps } from './Nav.root';\nexport type {\n NavSectionHeaderProps,\n NavDividerProps,\n NavAppItemOwnProps,\n NavAppItemAnchorProps,\n NavAppItemButtonProps,\n NavAppItemProps,\n NavAppItemDynamicProps,\n NavAppItemStaticProps,\n} from './Nav.parts';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Properties for the NavCategory sub-component. */\nexport interface NavCategoryProps extends React.HTMLAttributes<HTMLLIElement> {\n /**\n * Value identifying this category (used by `openCategories`), unique among the categories of\n * the Nav (a duplicate warns in development).\n */\n value: string;\n /**\n * Label of the category's toggle button (any content). Without it, the text children are used\n * as the label — deprecated: pass the label here and only the sub-items as children.\n */\n label?: React.ReactNode;\n /**\n * Icon displayed before the category label. Rendered with `aria-hidden=\"true\"`. A falsy icon\n * (`''`, `0`) or a list of nothing renders no icon box.\n */\n icon?: Slot<'span'>;\n /**\n * The category's sub-items (`Nav.SubItem`), and `Nav.SectionHeader` and `Nav.Divider`, rendered\n * in its list while it is open.\n */\n children?: React.ReactNode;\n /** Ref to the category's `<li>` element. */\n ref?: React.Ref<HTMLLIElement>;\n}\n\n/**\n * The props of Nav.Item that every branch shares ({@link NavItemAnchorProps},\n * {@link NavItemButtonProps}, {@link NavItemDynamicProps}).\n */\nexport interface NavItemOwnProps {\n /**\n * Value identifying this nav item, unique among the items and sub-items of the Nav (a duplicate\n * warns in development).\n */\n value: string;\n /**\n * Icon displayed before the item label. Rendered with `aria-hidden=\"true\"`. A falsy icon (`''`,\n * `0`) or a list of nothing renders no icon box.\n */\n icon?: Slot<'span'>;\n /**\n * Whether the item is disabled: a native `disabled` button, or an `aria-disabled` link without\n * `href`. Activating a disabled item never selects it; a disabled item whose value is the\n * current `value` still shows as current (`aria-current=\"page\"` and the selected look), because\n * the current value belongs to the app.\n */\n disabled?: boolean;\n /** Label content. */\n children?: React.ReactNode;\n /**\n * Controls beside the item in its row (Fluent's SplitNavItem): a ToggleButton that pins the\n * page, a MenuButton with more commands, each with its own name (a Tooltip with\n * `relationship=\"label\"` names an icon-only one). They render after the item's link or button,\n * never inside it, in a group named by the item; each is a Tab stop after the item, and a click\n * or key on one never selects the item. They are drawn while the row is hovered or has focus,\n * while one of them is pressed or has its popup open, and always in forced colours and on touch\n * screens; otherwise they are transparent and still focusable. They stay enabled when the item\n * is `disabled`. With actions, the selected background and indicator are drawn on the row (the\n * item's list item, `.wave-nav-item__list-item`), so a `className` on the item no longer covers\n * them. Content that renders nothing renders no group. Fluent's `actionButton`, `toggleButton`\n * and `menuButton` slots and their tooltips are your own controls here.\n */\n actions?: React.ReactNode;\n}\n\n/**\n * Nav.Item rendered as a link (`href` given): anchor attributes, and handlers typed on\n * `HTMLAnchorElement`. 0.4 typed every item's handlers on `HTMLButtonElement`, so with a string\n * `href` an unannotated 0.4 handler that reads a button-only member (such as\n * `e.currentTarget.form`) no longer compiles; a handler already typed as\n * `React.MouseEventHandler<HTMLButtonElement>` still does (React handler types are bivariant).\n */\nexport interface NavItemAnchorProps\n extends\n NavItemOwnProps,\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof NavItemOwnProps> {\n /**\n * URL to navigate to; renders an `<a>`. Required in this branch, so `href` discriminates the\n * union and handlers without `href` are typed as button handlers.\n */\n href: string;\n /** Ref to the `<a>` element. */\n ref?: React.Ref<HTMLAnchorElement>;\n}\n\n/** Nav.Item rendered as a button (no `href`): button attributes (a `rel` is not rendered). */\nexport interface NavItemButtonProps\n extends\n NavItemOwnProps,\n NoAnchorOnlyAttributes,\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof NavItemOwnProps> {\n /** Button items have no `href`. */\n href?: undefined;\n /** Ref to the `<button>` element. */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * Properties for the NavItem sub-component: link props with `href`, button props without.\n *\n * A union type (0.4 had an interface): an interface cannot extend it, so extend one branch\n * (`interface X extends NavItemButtonProps`) or intersect (`type X = NavItemProps & { … }`).\n * `React.ComponentProps<typeof Nav.Item>` resolves to the last overload,\n * {@link NavItemDynamicProps}.\n */\nexport type NavItemProps = NavItemAnchorProps | NavItemButtonProps;\n\n/**\n * Nav.Item with an `href` known only at run time (`string | undefined`): a link when it is a\n * string, a button otherwise. Resolved after the button and link signatures.\n *\n * Only the attributes both elements share are accepted (no `target`, `download`, `type`, `form`,\n * …), and handlers receive events of either element (`HTMLAnchorElement | HTMLButtonElement`).\n * 0.4 typed them as button events (`HTMLAttributes<HTMLButtonElement>`), so an unannotated 0.4\n * handler that reads a button-only member (such as `e.currentTarget.form`) no longer compiles here;\n * narrow `e.currentTarget` first. (A string `href` types handlers on `HTMLAnchorElement`, see\n * {@link NavItemAnchorProps}; no `href` keeps `HTMLButtonElement`.)\n */\nexport interface NavItemDynamicProps\n extends\n NavItemOwnProps,\n Omit<React.HTMLAttributes<HTMLAnchorElement | HTMLButtonElement>, keyof NavItemOwnProps> {\n /** URL to navigate to; renders an `<a>` when defined, a `<button>` otherwise. */\n href?: string;\n /** Ref to the rendered `<a>` or `<button>` element. */\n ref?: React.Ref<HTMLAnchorElement | HTMLButtonElement>;\n}\n\n/**\n * The props of Nav.SubItem that every branch shares: those of {@link NavItemOwnProps} without\n * `icon`.\n */\nexport type NavSubItemOwnProps = Omit<NavItemOwnProps, 'icon'>;\n\n/**\n * Nav.SubItem rendered as a link (`href` given): anchor attributes, and handlers typed on\n * `HTMLAnchorElement` (0.4: `HTMLButtonElement`); see {@link NavItemAnchorProps}.\n */\nexport interface NavSubItemAnchorProps\n extends\n NavSubItemOwnProps,\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof NavSubItemOwnProps> {\n /**\n * URL to navigate to; renders an `<a>`. Required in this branch, so `href` discriminates the\n * union and handlers without `href` are typed as button handlers.\n */\n href: string;\n /** Ref to the `<a>` element. */\n ref?: React.Ref<HTMLAnchorElement>;\n}\n\n/** Nav.SubItem rendered as a button (no `href`): button attributes (a `rel` is not rendered). */\nexport interface NavSubItemButtonProps\n extends\n NavSubItemOwnProps,\n NoAnchorOnlyAttributes,\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof NavSubItemOwnProps> {\n /** Button sub-items have no `href`. */\n href?: undefined;\n /** Ref to the `<button>` element. */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * Properties for the NavSubItem sub-component: link props with `href`, button props without.\n * A union type like {@link NavItemProps} (extend a branch or intersect; `React.ComponentProps`\n * resolves to {@link NavSubItemDynamicProps}).\n */\nexport type NavSubItemProps = NavSubItemAnchorProps | NavSubItemButtonProps;\n\n/**\n * Nav.SubItem with an `href` known only at run time (`string | undefined`): a link when it is a\n * string, a button otherwise. Only the attributes both elements share are accepted, and handlers\n * receive events of either element (0.4 typed them as button events); see\n * {@link NavItemDynamicProps}.\n */\nexport interface NavSubItemDynamicProps\n extends\n NavSubItemOwnProps,\n Omit<React.HTMLAttributes<HTMLAnchorElement | HTMLButtonElement>, keyof NavSubItemOwnProps> {\n /** URL to navigate to; renders an `<a>` when defined, a `<button>` otherwise. */\n href?: string;\n /** Ref to the rendered `<a>` or `<button>` element. */\n ref?: React.Ref<HTMLAnchorElement | HTMLButtonElement>;\n}\n\n/** The props both entry kinds share at runtime (the union narrowed by `href`). */\ntype NavEntryProps = NavItemOwnProps &\n Omit<React.AllHTMLAttributes<HTMLElement>, keyof NavItemOwnProps | 'ref'> & {\n ref?: React.Ref<HTMLElement>;\n };\n\n// ---------------------------------------------------------------------------\n// Styles\n// ---------------------------------------------------------------------------\n\nconst iconClasses = 'flex h-5 w-5 shrink-0 items-center justify-center';\n\n/**\n * The `icon` slot of Nav.Item and Nav.Category, or `null` when it renders nothing. A falsy icon\n * (`icon={name && <Icon />}` with `name` '' or a count of 0) is no icon, as in 0.4 and as in\n * Avatar, and so is a collection whose items render nothing, so no empty 20px box is rendered\n * before the label. The check does not consume a generator: renderSlot still renders its items.\n */\nfunction renderIcon(\n icon: Slot<'span'> | undefined,\n className: string | undefined,\n): React.ReactElement | null {\n return icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(className, iconClasses), { 'aria-hidden': true })\n : null;\n}\n\nconst itemClasses = {\n base: cn(\n 'flex w-full items-center gap-2 px-4 py-2 text-body-1 text-start no-underline transition-colors motion-reduce:transition-none',\n focusRingInset,\n disabledStyles,\n ),\n selected: 'bg-subtle-selected text-primary font-semibold border-s-2 border-s-primary',\n idle: 'text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover',\n // With actions, the selected background and indicator move to the row (D121).\n selectedInRow: 'text-primary font-semibold',\n rowSelected: 'bg-subtle-selected border-s-2 border-s-primary',\n};\n\nconst subItemClasses = {\n base: cn(\n 'flex w-full items-center ps-11 pe-4 py-1.5 text-body-1 text-start no-underline transition-colors motion-reduce:transition-none',\n focusRingInset,\n disabledStyles,\n ),\n selected: 'text-primary font-semibold',\n idle: 'text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover',\n // Sub-items have no selected background: a sub-item row gets only the hover.\n selectedInRow: 'text-primary font-semibold',\n rowSelected: undefined,\n};\n\n/** The classes an entry's link or button and its row share. */\ninterface NavEntryClasses {\n base: string;\n selected: string;\n idle: string;\n selectedInRow: string;\n rowSelected: string | undefined;\n}\n\n/**\n * The row of an entry with actions (D121): the list item lays out the link or button and the\n * actions side by side and carries the selected look, or the hover of an enabled entry. A list\n * item cannot be disabled, so its hover needs no gate.\n */\nconst rowClasses =\n 'group/nav-row flex items-center transition-colors motion-reduce:transition-none';\nconst rowHoverClasses = 'hover:bg-subtle-hover';\n\n/**\n * The actions element (D120). Each direct child is transparent until the row is hovered or has\n * focus inside it, and is always drawn in forced colours and on devices without hover; a child\n * that is or holds a pressed toggle or an expanded trigger stays drawn (the first pair covers an\n * action wrapped in a Tooltip's span, the second a bare one). Opacity keeps every action\n * focusable, so Shift+Tab and a focus return reach it. No motion.\n */\nconst actionsClasses = cn(\n 'flex shrink-0 items-center gap-1 pe-2',\n '*:opacity-0 group-hover/nav-row:*:opacity-100 group-focus-within/nav-row:*:opacity-100',\n 'forced-colors:*:opacity-100 [@media(hover:none)]:*:opacity-100',\n '*:has-[[aria-pressed=true]]:opacity-100 *:has-[[aria-expanded=true]]:opacity-100',\n '[&>[aria-pressed=true]]:opacity-100 [&>[aria-expanded=true]]:opacity-100',\n);\n\nconst categoryButtonClasses = cn(\n 'flex w-full items-center gap-2 px-4 py-2 text-body-1 font-semibold text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover transition-colors motion-reduce:transition-none',\n // A closed category that contains the current page shows the selected look of an item.\n 'data-[contains-current]:bg-subtle-selected data-[contains-current]:text-primary data-[contains-current]:border-s-2 data-[contains-current]:border-s-primary',\n focusRingInset,\n);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Whether a click on a link opens it somewhere other than the current page, checked as routers\n * do: a modifier key (a new tab or window, a download), a mouse button other than the main one, a\n * `target` other than `_self`, or a `download` link. Only when the default is not prevented does\n * the browser actually open it there.\n */\nfunction opensElsewhere(event: React.MouseEvent<HTMLElement>): boolean {\n if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return true;\n }\n const link = event.currentTarget;\n const target = link.getAttribute('target');\n return (!!target && target.toLowerCase() !== '_self') || link.hasAttribute('download');\n}\n\n/** The stable classes of an entry, written literally by Nav.Item and Nav.SubItem. */\ninterface NavEntryClassNames {\n root: string;\n listItem: string;\n actions: string;\n icon?: string;\n content?: string;\n}\n\n/**\n * Shared rendering of Nav.Item and Nav.SubItem (link or button). Inside an arrow-key body\n * (`roving` provided) the link or button also carries `data-roving-value={value}`, after the\n * consumer's attributes; in a plain Nav nothing is added. With `actions` that render content, the\n * list item becomes the row (D121) and holds the link or button, then the actions in a group named\n * by it through `generatedId` (unless the consumer gave an `id`), siblings, never nested (D119).\n */\nfunction renderNavEntry(\n props: NavEntryProps,\n context: NavContextValue,\n roving: NavRovingContextValue | null,\n classes: NavEntryClasses,\n stable: NavEntryClassNames,\n withIcon: boolean,\n generatedId: string,\n): React.ReactElement {\n const {\n value,\n icon,\n disabled = false,\n href,\n className,\n children,\n onClick,\n actions,\n ref,\n ...rest\n } = props;\n const isSelected = context.value === value;\n const isLink = href !== undefined;\n const rovingProps = roving ? { 'data-roving-value': value } : undefined;\n // No empty group (`actions={cond && <Button />}` with `cond` false); the id is rendered only\n // while the group points at it, so an item without actions keeps its 0.10 HTML.\n const hasActions = slotRendersContent(actions);\n const itemId = rest.id ?? generatedId;\n const idProps = hasActions ? { id: itemId } : undefined;\n\n const handleClick = (event: React.MouseEvent<HTMLElement>) => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n onClick?.(event);\n // A link is still selected when the consumer prevents its default (client-side routing:\n // `preventDefault()` + `router.push(href)`, whatever the modifier keys: the browser then opens\n // nothing elsewhere), but not when the browser opens it elsewhere (the current page does not\n // change); a button honours `preventDefault()` (C-COMPOSE).\n if (isLink ? !event.defaultPrevented && opensElsewhere(event) : event.defaultPrevented) return;\n context.select(value);\n };\n\n const content = (\n <>\n {withIcon && renderIcon(icon, stable.icon)}\n {withIcon ? (\n <span className={cn(stable.content, 'flex-1 text-start')}>{children}</span>\n ) : (\n children\n )}\n </>\n );\n\n const entryClassName = cn(\n stable.root,\n classes.base,\n isSelected ? (hasActions ? classes.selectedInRow : classes.selected) : classes.idle,\n hasActions && 'min-w-0 flex-1',\n className,\n );\n\n const listItemClassName = hasActions\n ? cn(\n stable.listItem,\n rowClasses,\n isSelected && classes.rowSelected ? classes.rowSelected : !disabled && rowHoverClasses,\n )\n : stable.listItem;\n\n const actionsGroup = hasActions ? (\n <span\n role=\"group\"\n aria-labelledby={itemId}\n data-wave-nav-actions=\"\"\n className={cn(stable.actions, actionsClasses)}\n >\n {materialiseSlotContent(actions)}\n </span>\n ) : null;\n\n if (isLink) {\n return (\n <li className={listItemClassName}>\n <a\n {...(rest as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n {...idProps}\n {...rovingProps}\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={disabled ? undefined : href}\n role={disabled ? 'link' : rest.role}\n aria-disabled={disabled ? true : rest['aria-disabled']}\n aria-current={isSelected ? 'page' : undefined}\n onClick={handleClick}\n className={entryClassName}\n >\n {content}\n </a>\n {actionsGroup}\n </li>\n );\n }\n\n // `rel` only belongs on a link: a button item drops it (React types it on every element).\n const { rel, ...buttonRest } = rest;\n return (\n <li className={listItemClassName}>\n <button\n type=\"button\"\n {...(buttonRest as React.ButtonHTMLAttributes<HTMLButtonElement>)}\n {...idProps}\n {...rovingProps}\n ref={ref as React.Ref<HTMLButtonElement>}\n disabled={disabled}\n aria-current={isSelected ? 'page' : undefined}\n onClick={handleClick}\n className={entryClassName}\n >\n {content}\n </button>\n {actionsGroup}\n </li>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Nav.Category\n// ---------------------------------------------------------------------------\n\n/**\n * A collapsible group of sub-items. Its toggle button shows `label` and reports `aria-expanded`\n * (and `aria-controls` while open); the sub-items render in a nested list while it is open.\n * Open state lives on `Nav` (`openCategories`/`defaultOpenCategories`).\n *\n * A closed category that contains the current item marks its toggle button with\n * `aria-current=\"true\"` (the button is not the page's link, so not `\"page\"`),\n * `data-contains-current` and the selected look of `Nav.Item`. It contains the current item when\n * a `Nav.SubItem` with the current value is among its children (through Fragments and wrapper\n * elements, also in the server HTML), when the current sub-item was last shown in it (and has not\n * moved among another category's children since), or when it is the Nav's `currentCategory`. An\n * open category is not marked: its sub-item shows the current page.\n *\n * Also exported as `NavCategory` (import the flat name from React Server Components).\n */\nconst NavCategory = ({\n value,\n label,\n icon,\n className,\n children,\n ref,\n ...rest\n}: NavCategoryProps) => {\n const context = useNavContext('Nav.Category');\n const roving = React.useContext(NavRovingContext);\n const {\n value: currentValue,\n openCategories,\n toggleCategory,\n currentCategory,\n categoryStore,\n } = context;\n useNavValue(context, 'category', value);\n const listId = useId('wave-nav-category');\n const isOpen = openCategories.includes(value);\n\n // The current sub-item is among the children of this closed category (also on the server).\n const holdsCurrentChild = !isOpen && currentValue !== '' && containsValue(children, currentValue);\n // The current sub-item was last shown in this category (none on the server).\n const holdsShownCurrent = React.useSyncExternalStore(\n categoryStore.subscribe,\n () => currentValue !== '' && categoryStore.get(currentValue) === value,\n () => false,\n );\n // Children that hold the current sub-item make this the category the Nav remembers for it, so a\n // category it was shown in before it moved here is no longer marked. The entry is forgotten when\n // they stop holding it (an open category records through its mounted sub-item instead).\n React.useLayoutEffect(() => {\n if (!holdsCurrentChild) return;\n categoryStore.record(currentValue, value);\n return () => categoryStore.forget(currentValue, value);\n }, [categoryStore, holdsCurrentChild, currentValue, value]);\n const containsCurrent =\n !isOpen && (currentCategory === value || holdsShownCurrent || holdsCurrentChild);\n // Inside an arrow-key body: whether this is a closed category that holds the current page (the\n // body's first Tab stop), before paint; nothing is reported in a plain Nav.\n React.useLayoutEffect(() => {\n if (!roving) return;\n roving.reportCurrentCategory(value, containsCurrent);\n return () => roving.reportCurrentCategory(value, false);\n }, [roving, value, containsCurrent]);\n // Development only: every child of the open list is an <li> (`Nav.Category:list-child`).\n const listRef = React.useRef<HTMLUListElement>(null);\n useNavListChildCheck(listRef, 'Nav.Category', 'sub-items');\n\n let buttonLabel: React.ReactNode = label;\n let items: React.ReactNode = children;\n if (label === undefined) {\n // Deprecated 0.4 path: the text children are the label, the other children the sub-items.\n warnDeprecated(\n 'Nav.Category',\n 'text children as the label',\n 'label',\n 'Pass the category label in `label` and only the sub-items as children.',\n );\n const parts = React.Children.toArray(children);\n const isText = (part: unknown) => typeof part === 'string' || typeof part === 'number';\n buttonLabel = parts.filter(isText).join('');\n items = parts.filter((part) => !isText(part));\n }\n\n return (\n <li ref={ref} {...rest} className={cn(navCategoryClassNames.root, className)}>\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? listId : undefined}\n aria-current={containsCurrent ? true : undefined}\n data-contains-current={containsCurrent ? '' : undefined}\n data-roving-value={roving ? `wave-nav-category:${value}` : undefined}\n onClick={() => toggleCategory(value)}\n className={cn(navCategoryClassNames.button, categoryButtonClasses)}\n >\n {renderIcon(icon, navCategoryClassNames.icon)}\n <span className={cn(navCategoryClassNames.label, 'flex-1 text-start')}>{buttonLabel}</span>\n <ChevronDownIcon\n className={cn(\n navCategoryClassNames.expandIcon,\n 'shrink-0 transition-transform motion-reduce:transition-none',\n isOpen && 'rotate-180',\n )}\n />\n </button>\n {isOpen && (\n <NavCategoryValueContext.Provider value={value}>\n <ul\n ref={listRef}\n id={listId}\n className={cn(navCategoryClassNames.list, 'm-0 list-none p-0')}\n >\n {items}\n </ul>\n </NavCategoryValueContext.Provider>\n )}\n </li>\n );\n};\nNavCategory.displayName = 'NavCategory';\nmarkNavPart(NavCategory, 'category');\n\n// ---------------------------------------------------------------------------\n// Nav.Item / Nav.SubItem\n// ---------------------------------------------------------------------------\n\n/**\n * A top-level navigation entry: a link when `href` is given (anchor props), a button otherwise\n * (button props). Clicking selects it (`aria-current=\"page\"`); activating a disabled entry never\n * selects it (a disabled entry whose value is the current value still shows as current).\n *\n * A click that opens a link somewhere other than the current page selects nothing (the consumer's\n * `onClick` still runs, and the browser opens the link): Ctrl/Cmd/Shift/Alt-click, a mouse button\n * other than the main one, a `target` other than `_self`, or a `download` link. When the consumer's\n * `onClick` calls `preventDefault()` (client-side routing), the browser opens nothing, so the item\n * is selected whatever the keys, button or `target`.\n *\n * `actions` puts your own controls (a pin toggle, a menu button) beside the item in its row, in a\n * group named by the item; they never select it.\n *\n * Typed by overloads, resolved in order: without `href` (button props, button events), with a\n * string `href` (anchor props, anchor events), then an `href` that may be `undefined` at run time\n * ({@link NavItemDynamicProps}: events of either element).\n *\n * Also exported as `NavItem` (import the flat name from React Server Components).\n */\nfunction NavItem(props: NavItemButtonProps): React.ReactElement;\nfunction NavItem(props: NavItemAnchorProps): React.ReactElement;\nfunction NavItem(props: NavItemDynamicProps): React.ReactElement;\nfunction NavItem(props: NavItemProps | NavItemDynamicProps): React.ReactElement {\n const context = useNavContext('Nav.Item');\n useNavValue(context, 'item', props.value);\n useRecordCategory(context, props.value);\n const roving = React.useContext(NavRovingContext);\n // Called always, rendered only while the item's actions render (D119).\n const generatedId = useId('wave-nav-item');\n return renderNavEntry(\n props as NavEntryProps,\n context,\n roving,\n itemClasses,\n {\n root: navItemClassNames.root,\n listItem: navItemClassNames.listItem,\n actions: navItemClassNames.actions,\n icon: navItemClassNames.icon,\n content: navItemClassNames.content,\n },\n true,\n generatedId,\n );\n}\nNavItem.displayName = 'NavItem';\nmarkNavPart(NavItem, 'entry');\n\n/**\n * An indented entry inside a `Nav.Category`: a link when `href` is given, a button otherwise.\n * Selected like `Nav.Item` (a click that the browser opens somewhere else selects nothing; one\n * whose default your `onClick` prevents is selected), and typed by overloads like `Nav.Item`\n * (button, link, then {@link NavSubItemDynamicProps}). Takes `actions` like `Nav.Item`.\n *\n * Also exported as `NavSubItem` (import the flat name from React Server Components).\n */\nfunction NavSubItem(props: NavSubItemButtonProps): React.ReactElement;\nfunction NavSubItem(props: NavSubItemAnchorProps): React.ReactElement;\nfunction NavSubItem(props: NavSubItemDynamicProps): React.ReactElement;\nfunction NavSubItem(props: NavSubItemProps | NavSubItemDynamicProps): React.ReactElement {\n const context = useNavContext('Nav.SubItem');\n useNavValue(context, 'item', props.value);\n useRecordCategory(context, props.value);\n const roving = React.useContext(NavRovingContext);\n // Called always, rendered only while the sub-item's actions render (D119).\n const generatedId = useId('wave-nav-item');\n return renderNavEntry(\n props as NavEntryProps,\n context,\n roving,\n subItemClasses,\n {\n root: navSubItemClassNames.root,\n listItem: navSubItemClassNames.listItem,\n actions: navSubItemClassNames.actions,\n },\n false,\n generatedId,\n );\n}\nNavSubItem.displayName = 'NavSubItem';\nmarkNavPart(NavSubItem, 'entry');\n\n/**\n * A vertical side navigation (`<nav>` landmark, default name \"Navigation\") with items, links and\n * collapsible categories.\n *\n * - **Selection**: `value`/`defaultValue`/`onValueChange` (`onValueChange` fires only when the\n * value changes). The deprecated `selectedValue`/`defaultSelectedValue`/`onNavItemSelect` still\n * work; `onNavItemSelect` keeps firing on every activation, re-selection included. A click that\n * opens a link in another tab or window (or downloads it) selects nothing, unless the item's\n * `onClick` prevents the default (client-side routing: then nothing opens elsewhere).\n * - **Categories**: `openCategories`/`defaultOpenCategories`/`onOpenCategoriesChange`. Without\n * `defaultOpenCategories`, the categories containing the selected item (`value` or\n * `defaultValue`) start open. A closed category that contains the selected item marks its toggle\n * (`aria-current=\"true\"`, `data-contains-current`, the selected look); pass `currentCategory`\n * for sub-items your own component renders inside a closed category.\n * - **Values** are unique: among the items and sub-items, and among the categories (a duplicate\n * warns in development).\n * - **Structure**: every child of the Nav, and of a category, is a part or your own `<li>`; a\n * development warning names anything else (a `<div>`, text, the wrapper of a Tooltip around an\n * item). `Nav.SectionHeader` is a heading between groups of items (`<h3>` unless\n * `headingLevel`, which stands for the `as` of Fluent's NavSectionHeader), and `Nav.Divider` a\n * line between groups, hidden from assistive technology (Fluent's NavDivider is a separator).\n * - **App identity**: `Nav.AppItem` shows the app's name and logo at the top, as a link with\n * `href` or a button; it is never selected. `Nav.AppItemStatic` shows them as plain text.\n * - **Item actions**: `actions` on `Nav.Item` and `Nav.SubItem` (Fluent's SplitNavItem) puts your\n * own controls beside the item, in a group named by it; each is a Tab stop after the item, and\n * none selects it. They are drawn while the row is hovered or has focus, while one is pressed or\n * has its menu open, and always on touch screens and in forced colours. With actions, a selected\n * item's background and indicator are drawn on its row (`.wave-nav-item__list-item`).\n *\n * Sub-components are also exported under flat names (`NavCategory`, `NavItem`, `NavSubItem`,\n * `NavSectionHeader`, `NavDivider`, `NavAppItem`, `NavAppItemStatic`): React Server Components\n * import those, because dotted access (`Nav.Item`) needs a client file.\n */\nexport const Nav = /* @__PURE__ */ Object.assign(NavRoot, {\n Category: NavCategory,\n Item: NavItem,\n SubItem: NavSubItem,\n SectionHeader: NavSectionHeader,\n Divider: NavDivider,\n AppItem: NavAppItem,\n AppItemStatic: NavAppItemStatic,\n});\n\nexport {\n NavCategory,\n NavItem,\n NavSubItem,\n NavSectionHeader,\n NavDivider,\n NavAppItem,\n NavAppItemStatic,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Nav.mjs","names":["_Fragment","navActionsReveal","useId","expandIconMotion","expandIconRecipe","useId$1","React","iconClasses","renderIcon","icon","slotRendersContent","renderSlot","cn","className","itemClasses","focusRingInset","disabledStyles","subItemClasses","rowClasses","rowHoverClasses","actionsClasses","categoryButtonClasses","opensElsewhere","event","link","target","renderNavEntry","rest","props","isSelected","context","value","isLink","href","rovingProps","roving","hasActions","actions","itemId","generatedId","idProps","handleClick","disabled","onClick","content","Fragment","withIcon","stable","children","entryClassName","classes","listItemClassName","actionsGroup","motionPreference","navActionsRevealMotion","materialiseSlotContent","buttonRest","NavCategory","expandIconMotion$1","useNavContext","NavRovingContext","currentValue","listId","isOpen","openCategories","holdsCurrentChild","containsValue","holdsShownCurrent","categoryStore","containsCurrent","currentCategory","listRef","buttonRef","isListMounted","collapseRef","collapsePresenceProps","collapseClassName","useCollapsePresence","expandGlyph","expandIconButton","unwrapButtonGlyph","expandIcon","warnOnce","expandIconMotionClassName","useMotionClasses","expandIconMotion","expandIconElement","ChevronDownIcon","navCategoryClassNames","buttonLabel","label","items","parts","isText","part","toggleCategory","NavCategoryValueContext","markNavPart","NavItem","useNavValue","useRecordCategory","useMotionPreference","navItemClassNames","NavSubItem","navSubItemClassNames","Nav","NavRoot","NavSectionHeader","NavDivider","NavAppItem","NavAppItemStatic"],"sources":["../../../src/components/navigation/Nav.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n navCategoryClassNames,\n navItemClassNames,\n navSubItemClassNames,\n} from '../../lib/classNames';\nimport type { MotionPreference, MotionSlot, Slot } from '../../lib/types';\nimport { materialiseSlotContent, renderSlot, slotRendersContent } from '../../lib/slot';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { ChevronDownIcon } from '../../lib/icons';\n// Aliased: `expandIconMotion` is also Nav.Category's prop.\nimport {\n expandIconMotion as expandIconRecipe,\n navActionsRevealMotion as navActionsReveal,\n} from '../../lib/motion';\nimport { disabledStyles, focusRingInset } from '../../lib/styles';\nimport { useCollapsePresence } from '../../hooks/useCollapsePresence';\nimport { useId } from '../../hooks/useId';\nimport { useMotionClasses, useMotionPreference } from '../../hooks/useMotion';\nimport { unwrapButtonGlyph } from '../button/Button.slots';\nimport {\n NavCategoryValueContext,\n NavRovingContext,\n containsValue,\n markNavPart,\n useNavContext,\n useNavListChildCheck,\n useNavValue,\n useRecordCategory,\n type NavContextValue,\n type NavRovingContextValue,\n type NoAnchorOnlyAttributes,\n} from './Nav.context';\nimport { NavAppItem, NavAppItemStatic, NavDivider, NavSectionHeader } from './Nav.parts';\nimport { NavRoot } from './Nav.root';\n\n/*\n * The Nav compound: the item types, styles and rendering of Nav.Item and Nav.SubItem, Nav.Category,\n * the `Object.assign` with its JSDoc, the flat names and the type re-exports. Nothing imports this\n * module but the barrel: the root (`Nav.root.tsx`) and the contexts (`Nav.context.ts`) recognise\n * the parts by the markers set next to each `displayName` below; the structural parts live in\n * `Nav.parts.tsx`.\n */\n\nexport type { NavProps } from './Nav.root';\nexport type {\n NavSectionHeaderProps,\n NavDividerProps,\n NavAppItemOwnProps,\n NavAppItemAnchorProps,\n NavAppItemButtonProps,\n NavAppItemProps,\n NavAppItemDynamicProps,\n NavAppItemStaticProps,\n} from './Nav.parts';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Properties for the NavCategory sub-component. */\nexport interface NavCategoryProps extends React.HTMLAttributes<HTMLLIElement> {\n /**\n * Value identifying this category (used by `openCategories`), unique among the categories of\n * the Nav (a duplicate warns in development).\n */\n value: string;\n /**\n * Label of the category's toggle button (any content). Without it, the text children are used\n * as the label — deprecated: pass the label here and only the sub-items as children.\n */\n label?: React.ReactNode;\n /**\n * Icon displayed before the category label. Rendered with `aria-hidden=\"true\"`. A falsy icon\n * (`''`, `0`) or a list of nothing renders no icon box.\n */\n icon?: Slot<'span'>;\n /**\n * Replaces the expand chevron at the end of the toggle button (decorative, `aria-hidden`).\n * `null`/`undefined` keep the chevron, which turns while the category is open; `false`, or\n * anything that renders nothing, hides it (`aria-expanded` still reports the state). Your glyph\n * renders as given in a span with the expand icon's class and is not turned, so a glyph that\n * shows the state itself works (a plus or a minus, picked from your `openCategories`). It is\n * rendered inside the toggle button: a `<button>` or `Button` passed here (or a slot object\n * whose `as` is one) is not nested (its children become the glyph and its props are dropped,\n * with a development warning).\n */\n expandIcon?: Slot<'span'>;\n /**\n * Replaces the motion of the expand icon (Fluent's `NavCategoryItem expandIconMotion`): by\n * default the chevron's half turn as the category opens and closes is animated over the fast\n * duration (150 ms) with the easy-ease curve, both ways, and so is any transform of the span\n * around your own `expandIcon`. The turn itself is not motion: `null` turns the animation off\n * and the chevron still turns, at once; a class string or `{ className }` replaces it with\n * plain transition classes and a reduced-motion counterpart (the icon has no presence phases).\n * A `WaveProvider` with `motion=\"none\"` turns the default off, and a value here still applies\n * under it.\n * @default the animated turn described above\n */\n expandIconMotion?: MotionSlot | null;\n /**\n * Replaces the collapse of the category's list (Fluent's `NavSubItemGroup collapseMotion`), on\n * the element around its `<ul>`: by default the space the list takes opens from nothing and\n * closes back to it, with a fade, over the normal duration (200 ms) with the max easy-ease\n * curve, both ways. `null` turns it off (the list appears and disappears at once); a class\n * string or `{ className }` replaces it, written as `MotionSlot` describes. A `WaveProvider`\n * with `motion=\"none\"` turns the default off, and a value here still applies under it.\n * @default the collapse described above\n */\n motion?: MotionSlot | null;\n /**\n * The category's sub-items (`Nav.SubItem`), and `Nav.SectionHeader` and `Nav.Divider`, rendered\n * in its list while it is open (and while the list collapses after a close).\n */\n children?: React.ReactNode;\n /** Ref to the category's `<li>` element. */\n ref?: React.Ref<HTMLLIElement>;\n}\n\n/**\n * The props of Nav.Item that every branch shares ({@link NavItemAnchorProps},\n * {@link NavItemButtonProps}, {@link NavItemDynamicProps}).\n */\nexport interface NavItemOwnProps {\n /**\n * Value identifying this nav item, unique among the items and sub-items of the Nav (a duplicate\n * warns in development).\n */\n value: string;\n /**\n * Icon displayed before the item label. Rendered with `aria-hidden=\"true\"`. A falsy icon (`''`,\n * `0`) or a list of nothing renders no icon box.\n */\n icon?: Slot<'span'>;\n /**\n * Whether the item is disabled: a native `disabled` button, or an `aria-disabled` link without\n * `href`. Activating a disabled item never selects it; a disabled item whose value is the\n * current `value` still shows as current (`aria-current=\"page\"` and the selected look), because\n * the current value belongs to the app.\n */\n disabled?: boolean;\n /** Label content. */\n children?: React.ReactNode;\n /**\n * Controls beside the item in its row (Fluent's SplitNavItem): a ToggleButton that pins the\n * page, a MenuButton with more commands, each with its own name (a Tooltip with\n * `relationship=\"label\"` names an icon-only one). They render after the item's link or button,\n * never inside it, in a group named by the item; each is a Tab stop after the item, and a click\n * or key on one never selects the item. They are drawn while the row is hovered or has focus,\n * while one of them is pressed or has its popup open, and always in forced colours and on touch\n * screens; otherwise they are transparent and still focusable. They fade in and out over 150 ms\n * (at once under reduced motion or a `WaveProvider` with `motion=\"none\"`); the fade sets the\n * transition of each direct child of the group, so a transition of your own on one is replaced.\n * They stay enabled when the item is `disabled`. With actions, the selected background and\n * indicator are drawn on the row (the item's list item, `.wave-nav-item__list-item`), so a\n * `className` on the item no longer covers them. Content that renders nothing renders no group.\n * Fluent's `actionButton`, `toggleButton` and `menuButton` slots and their tooltips are your own\n * controls here.\n */\n actions?: React.ReactNode;\n}\n\n/**\n * Nav.Item rendered as a link (`href` given): anchor attributes, and handlers typed on\n * `HTMLAnchorElement`. 0.4 typed every item's handlers on `HTMLButtonElement`, so with a string\n * `href` an unannotated 0.4 handler that reads a button-only member (such as\n * `e.currentTarget.form`) no longer compiles; a handler already typed as\n * `React.MouseEventHandler<HTMLButtonElement>` still does (React handler types are bivariant).\n */\nexport interface NavItemAnchorProps\n extends\n NavItemOwnProps,\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof NavItemOwnProps> {\n /**\n * URL to navigate to; renders an `<a>`. Required in this branch, so `href` discriminates the\n * union and handlers without `href` are typed as button handlers.\n */\n href: string;\n /** Ref to the `<a>` element. */\n ref?: React.Ref<HTMLAnchorElement>;\n}\n\n/** Nav.Item rendered as a button (no `href`): button attributes (a `rel` is not rendered). */\nexport interface NavItemButtonProps\n extends\n NavItemOwnProps,\n NoAnchorOnlyAttributes,\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof NavItemOwnProps> {\n /** Button items have no `href`. */\n href?: undefined;\n /** Ref to the `<button>` element. */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * Properties for the NavItem sub-component: link props with `href`, button props without.\n *\n * A union type (0.4 had an interface): an interface cannot extend it, so extend one branch\n * (`interface X extends NavItemButtonProps`) or intersect (`type X = NavItemProps & { … }`).\n * `React.ComponentProps<typeof Nav.Item>` resolves to the last overload,\n * {@link NavItemDynamicProps}.\n */\nexport type NavItemProps = NavItemAnchorProps | NavItemButtonProps;\n\n/**\n * Nav.Item with an `href` known only at run time (`string | undefined`): a link when it is a\n * string, a button otherwise. Resolved after the button and link signatures.\n *\n * Only the attributes both elements share are accepted (no `target`, `download`, `type`, `form`,\n * …), and handlers receive events of either element (`HTMLAnchorElement | HTMLButtonElement`).\n * 0.4 typed them as button events (`HTMLAttributes<HTMLButtonElement>`), so an unannotated 0.4\n * handler that reads a button-only member (such as `e.currentTarget.form`) no longer compiles here;\n * narrow `e.currentTarget` first. (A string `href` types handlers on `HTMLAnchorElement`, see\n * {@link NavItemAnchorProps}; no `href` keeps `HTMLButtonElement`.)\n */\nexport interface NavItemDynamicProps\n extends\n NavItemOwnProps,\n Omit<React.HTMLAttributes<HTMLAnchorElement | HTMLButtonElement>, keyof NavItemOwnProps> {\n /** URL to navigate to; renders an `<a>` when defined, a `<button>` otherwise. */\n href?: string;\n /** Ref to the rendered `<a>` or `<button>` element. */\n ref?: React.Ref<HTMLAnchorElement | HTMLButtonElement>;\n}\n\n/**\n * The props of Nav.SubItem that every branch shares: those of {@link NavItemOwnProps} without\n * `icon`.\n */\nexport type NavSubItemOwnProps = Omit<NavItemOwnProps, 'icon'>;\n\n/**\n * Nav.SubItem rendered as a link (`href` given): anchor attributes, and handlers typed on\n * `HTMLAnchorElement` (0.4: `HTMLButtonElement`); see {@link NavItemAnchorProps}.\n */\nexport interface NavSubItemAnchorProps\n extends\n NavSubItemOwnProps,\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof NavSubItemOwnProps> {\n /**\n * URL to navigate to; renders an `<a>`. Required in this branch, so `href` discriminates the\n * union and handlers without `href` are typed as button handlers.\n */\n href: string;\n /** Ref to the `<a>` element. */\n ref?: React.Ref<HTMLAnchorElement>;\n}\n\n/** Nav.SubItem rendered as a button (no `href`): button attributes (a `rel` is not rendered). */\nexport interface NavSubItemButtonProps\n extends\n NavSubItemOwnProps,\n NoAnchorOnlyAttributes,\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof NavSubItemOwnProps> {\n /** Button sub-items have no `href`. */\n href?: undefined;\n /** Ref to the `<button>` element. */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * Properties for the NavSubItem sub-component: link props with `href`, button props without.\n * A union type like {@link NavItemProps} (extend a branch or intersect; `React.ComponentProps`\n * resolves to {@link NavSubItemDynamicProps}).\n */\nexport type NavSubItemProps = NavSubItemAnchorProps | NavSubItemButtonProps;\n\n/**\n * Nav.SubItem with an `href` known only at run time (`string | undefined`): a link when it is a\n * string, a button otherwise. Only the attributes both elements share are accepted, and handlers\n * receive events of either element (0.4 typed them as button events); see\n * {@link NavItemDynamicProps}.\n */\nexport interface NavSubItemDynamicProps\n extends\n NavSubItemOwnProps,\n Omit<React.HTMLAttributes<HTMLAnchorElement | HTMLButtonElement>, keyof NavSubItemOwnProps> {\n /** URL to navigate to; renders an `<a>` when defined, a `<button>` otherwise. */\n href?: string;\n /** Ref to the rendered `<a>` or `<button>` element. */\n ref?: React.Ref<HTMLAnchorElement | HTMLButtonElement>;\n}\n\n/** The props both entry kinds share at runtime (the union narrowed by `href`). */\ntype NavEntryProps = NavItemOwnProps &\n Omit<React.AllHTMLAttributes<HTMLElement>, keyof NavItemOwnProps | 'ref'> & {\n ref?: React.Ref<HTMLElement>;\n };\n\n// ---------------------------------------------------------------------------\n// Styles\n// ---------------------------------------------------------------------------\n\nconst iconClasses = 'flex h-5 w-5 shrink-0 items-center justify-center';\n\n/**\n * The `icon` slot of Nav.Item and Nav.Category, or `null` when it renders nothing. A falsy icon\n * (`icon={name && <Icon />}` with `name` '' or a count of 0) is no icon, as in 0.4 and as in\n * Avatar, and so is a collection whose items render nothing, so no empty 20px box is rendered\n * before the label. The check does not consume a generator: renderSlot still renders its items.\n */\nfunction renderIcon(\n icon: Slot<'span'> | undefined,\n className: string | undefined,\n): React.ReactElement | null {\n return icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(className, iconClasses), { 'aria-hidden': true })\n : null;\n}\n\nconst itemClasses = {\n base: cn(\n 'flex w-full items-center gap-2 px-4 py-2 text-body-1 text-start no-underline transition-colors motion-reduce:transition-none',\n focusRingInset,\n disabledStyles,\n ),\n selected: 'bg-subtle-selected text-primary font-semibold border-s-2 border-s-primary',\n idle: 'text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover',\n // With actions, the selected background and indicator move to the row (D121).\n selectedInRow: 'text-primary font-semibold',\n rowSelected: 'bg-subtle-selected border-s-2 border-s-primary',\n};\n\nconst subItemClasses = {\n base: cn(\n 'flex w-full items-center ps-11 pe-4 py-1.5 text-body-1 text-start no-underline transition-colors motion-reduce:transition-none',\n focusRingInset,\n disabledStyles,\n ),\n selected: 'text-primary font-semibold',\n idle: 'text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover',\n // Sub-items have no selected background: a sub-item row gets only the hover.\n selectedInRow: 'text-primary font-semibold',\n rowSelected: undefined,\n};\n\n/** The classes an entry's link or button and its row share. */\ninterface NavEntryClasses {\n base: string;\n selected: string;\n idle: string;\n selectedInRow: string;\n rowSelected: string | undefined;\n}\n\n/**\n * The row of an entry with actions (D121): the list item lays out the link or button and the\n * actions side by side and carries the selected look, or the hover of an enabled entry. A list\n * item cannot be disabled, so its hover needs no gate.\n */\nconst rowClasses =\n 'group/nav-row flex items-center transition-colors motion-reduce:transition-none';\nconst rowHoverClasses = 'hover:bg-subtle-hover';\n\n/**\n * The actions element (D120). Each direct child is transparent until the row is hovered or has\n * focus inside it, and is always drawn in forced colours and on devices without hover; a child\n * that is or holds a pressed toggle or an expanded trigger stays drawn (the first pair covers an\n * action wrapped in a Tooltip's span, the second a bare one). Opacity keeps every action\n * focusable, so Shift+Tab and a focus return reach it. The reveal fades: `renderNavEntry` adds\n * the actions' reveal motion of `lib/motion` to these classes unless the provider's motion is\n * `'none'` (it has no slot: it is not a presence motion).\n */\nconst actionsClasses = cn(\n 'flex shrink-0 items-center gap-1 pe-2',\n '*:opacity-0 group-hover/nav-row:*:opacity-100 group-focus-within/nav-row:*:opacity-100',\n 'forced-colors:*:opacity-100 [@media(hover:none)]:*:opacity-100',\n '*:has-[[aria-pressed=true]]:opacity-100 *:has-[[aria-expanded=true]]:opacity-100',\n '[&>[aria-pressed=true]]:opacity-100 [&>[aria-expanded=true]]:opacity-100',\n);\n\nconst categoryButtonClasses = cn(\n 'flex w-full items-center gap-2 px-4 py-2 text-body-1 font-semibold text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover transition-colors motion-reduce:transition-none',\n // A closed category that contains the current page shows the selected look of an item.\n 'data-[contains-current]:bg-subtle-selected data-[contains-current]:text-primary data-[contains-current]:border-s-2 data-[contains-current]:border-s-primary',\n focusRingInset,\n);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Whether a click on a link opens it somewhere other than the current page, checked as routers\n * do: a modifier key (a new tab or window, a download), a mouse button other than the main one, a\n * `target` other than `_self`, or a `download` link. Only when the default is not prevented does\n * the browser actually open it there.\n */\nfunction opensElsewhere(event: React.MouseEvent<HTMLElement>): boolean {\n if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return true;\n }\n const link = event.currentTarget;\n const target = link.getAttribute('target');\n return (!!target && target.toLowerCase() !== '_self') || link.hasAttribute('download');\n}\n\n/** The stable classes of an entry, written literally by Nav.Item and Nav.SubItem. */\ninterface NavEntryClassNames {\n root: string;\n listItem: string;\n actions: string;\n icon?: string;\n content?: string;\n}\n\n/**\n * Shared rendering of Nav.Item and Nav.SubItem (link or button). Inside an arrow-key body\n * (`roving` provided) the link or button also carries `data-roving-value={value}`, after the\n * consumer's attributes; in a plain Nav nothing is added. With `actions` that render content, the\n * list item becomes the row (D121) and holds the link or button, then the actions in a group named\n * by it through `generatedId` (unless the consumer gave an `id`), siblings, never nested (D119);\n * the group's reveal fades unless `motionPreference` is `'none'`.\n */\nfunction renderNavEntry(\n props: NavEntryProps,\n context: NavContextValue,\n roving: NavRovingContextValue | null,\n classes: NavEntryClasses,\n stable: NavEntryClassNames,\n withIcon: boolean,\n generatedId: string,\n motionPreference: MotionPreference,\n): React.ReactElement {\n const {\n value,\n icon,\n disabled = false,\n href,\n className,\n children,\n onClick,\n actions,\n ref,\n ...rest\n } = props;\n const isSelected = context.value === value;\n const isLink = href !== undefined;\n const rovingProps = roving ? { 'data-roving-value': value } : undefined;\n // No empty group (`actions={cond && <Button />}` with `cond` false); the id is rendered only\n // while the group points at it, so an item without actions keeps its 0.10 HTML.\n const hasActions = slotRendersContent(actions);\n const itemId = rest.id ?? generatedId;\n const idProps = hasActions ? { id: itemId } : undefined;\n\n const handleClick = (event: React.MouseEvent<HTMLElement>) => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n onClick?.(event);\n // A link is still selected when the consumer prevents its default (client-side routing:\n // `preventDefault()` + `router.push(href)`, whatever the modifier keys: the browser then opens\n // nothing elsewhere), but not when the browser opens it elsewhere (the current page does not\n // change); a button honours `preventDefault()` (C-COMPOSE).\n if (isLink ? !event.defaultPrevented && opensElsewhere(event) : event.defaultPrevented) return;\n context.select(value);\n };\n\n const content = (\n <>\n {withIcon && renderIcon(icon, stable.icon)}\n {withIcon ? (\n <span className={cn(stable.content, 'flex-1 text-start')}>{children}</span>\n ) : (\n children\n )}\n </>\n );\n\n const entryClassName = cn(\n stable.root,\n classes.base,\n isSelected ? (hasActions ? classes.selectedInRow : classes.selected) : classes.idle,\n hasActions && 'min-w-0 flex-1',\n className,\n );\n\n const listItemClassName = hasActions\n ? cn(\n stable.listItem,\n rowClasses,\n isSelected && classes.rowSelected ? classes.rowSelected : !disabled && rowHoverClasses,\n )\n : stable.listItem;\n\n const actionsGroup = hasActions ? (\n <span\n role=\"group\"\n aria-labelledby={itemId}\n data-wave-nav-actions=\"\"\n className={cn(\n stable.actions,\n actionsClasses,\n motionPreference === 'none' ? undefined : navActionsReveal,\n )}\n >\n {materialiseSlotContent(actions)}\n </span>\n ) : null;\n\n if (isLink) {\n return (\n <li className={listItemClassName}>\n <a\n {...(rest as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n {...idProps}\n {...rovingProps}\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={disabled ? undefined : href}\n role={disabled ? 'link' : rest.role}\n aria-disabled={disabled ? true : rest['aria-disabled']}\n aria-current={isSelected ? 'page' : undefined}\n onClick={handleClick}\n className={entryClassName}\n >\n {content}\n </a>\n {actionsGroup}\n </li>\n );\n }\n\n // `rel` only belongs on a link: a button item drops it (React types it on every element).\n const { rel, ...buttonRest } = rest;\n return (\n <li className={listItemClassName}>\n <button\n type=\"button\"\n {...(buttonRest as React.ButtonHTMLAttributes<HTMLButtonElement>)}\n {...idProps}\n {...rovingProps}\n ref={ref as React.Ref<HTMLButtonElement>}\n disabled={disabled}\n aria-current={isSelected ? 'page' : undefined}\n onClick={handleClick}\n className={entryClassName}\n >\n {content}\n </button>\n {actionsGroup}\n </li>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Nav.Category\n// ---------------------------------------------------------------------------\n\n/**\n * A collapsible group of sub-items. Its toggle button shows `label` and reports `aria-expanded`\n * (and `aria-controls` while open); the sub-items render in a nested list while it is open and\n * while the list collapses after a close. Open state lives on `Nav`\n * (`openCategories`/`defaultOpenCategories`).\n *\n * The list renders as the only child of a collapse element (its stable class\n * `wave-nav-category__collapse`), which opens and closes the list's space (`motion`) and has no\n * box of its own while the category is open, so the list lays out in the category as before. A\n * category open by default appears without motion. After a close the list stays in the document\n * until the collapse ends, `inert` (its items leave the Tab order and an arrow-key body's arrow\n * keys at once), while the toggle button already reports the category closed, without\n * `aria-controls`; opening the category again during the collapse keeps the same list. Focus\n * inside the list when the category closes moves to the toggle button. The expand chevron turns\n * while the category is open (`expandIcon` replaces it, `expandIconMotion` animates its turn).\n *\n * A closed category that contains the current item marks its toggle button with\n * `aria-current=\"true\"` (the button is not the page's link, so not `\"page\"`),\n * `data-contains-current` and the selected look of `Nav.Item`. It contains the current item when\n * a `Nav.SubItem` with the current value is among its children (through Fragments and wrapper\n * elements, also in the server HTML), when the current sub-item was last shown in it (and has not\n * moved among another category's children since), or when it is the Nav's `currentCategory`. An\n * open category is not marked: its sub-item shows the current page.\n *\n * Also exported as `NavCategory` (import the flat name from React Server Components).\n */\nconst NavCategory = ({\n value,\n label,\n icon,\n expandIcon,\n expandIconMotion,\n motion,\n className,\n children,\n ref,\n ...rest\n}: NavCategoryProps) => {\n const context = useNavContext('Nav.Category');\n const roving = React.useContext(NavRovingContext);\n const {\n value: currentValue,\n openCategories,\n toggleCategory,\n currentCategory,\n categoryStore,\n } = context;\n useNavValue(context, 'category', value);\n const listId = useId('wave-nav-category');\n const isOpen = openCategories.includes(value);\n\n // The current sub-item is among the children of this closed category (also on the server).\n const holdsCurrentChild = !isOpen && currentValue !== '' && containsValue(children, currentValue);\n // The current sub-item was last shown in this category (none on the server).\n const holdsShownCurrent = React.useSyncExternalStore(\n categoryStore.subscribe,\n () => currentValue !== '' && categoryStore.get(currentValue) === value,\n () => false,\n );\n // Children that hold the current sub-item make this the category the Nav remembers for it, so a\n // category it was shown in before it moved here is no longer marked. The entry is forgotten when\n // they stop holding it (an open category records through its mounted sub-item instead).\n React.useLayoutEffect(() => {\n if (!holdsCurrentChild) return;\n categoryStore.record(currentValue, value);\n return () => categoryStore.forget(currentValue, value);\n }, [categoryStore, holdsCurrentChild, currentValue, value]);\n const containsCurrent =\n !isOpen && (currentCategory === value || holdsShownCurrent || holdsCurrentChild);\n // Inside an arrow-key body: whether this is a closed category that holds the current page (the\n // body's first Tab stop), before paint; nothing is reported in a plain Nav.\n React.useLayoutEffect(() => {\n if (!roving) return;\n roving.reportCurrentCategory(value, containsCurrent);\n return () => roving.reportCurrentCategory(value, false);\n }, [roving, value, containsCurrent]);\n // Development only: every child of the open list is an <li> (`Nav.Category:list-child`).\n const listRef = React.useRef<HTMLUListElement>(null);\n useNavListChildCheck(listRef, 'Nav.Category', 'sub-items');\n\n // The list renders in a collapse element (the presence element) while the category is open\n // and, after a close, until that element's motion ends; focus inside the list at the close\n // moves to the toggle button.\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const {\n isMounted: isListMounted,\n wrapperRef: collapseRef,\n presenceProps: collapsePresenceProps,\n className: collapseClassName,\n } = useCollapsePresence(isOpen, {\n motion,\n partRef: listRef,\n getTrigger: () => buttonRef.current,\n });\n\n // The optional-indicator slot rule (C-SLOTS): `null`/`undefined` keep the chevron, which turns\n // while open; `false` or content that renders nothing hides it; a custom glyph is rendered as\n // given in its span and never turned. `expandIconMotion` animates the transform of either. The\n // glyph sits inside the toggle button, so a button passed as the glyph is unwrapped (its\n // children are the glyph, its props are dropped), never nested.\n const { glyph: expandGlyph, button: expandIconButton } = unwrapButtonGlyph(expandIcon);\n React.useEffect(() => {\n if (expandIconButton) {\n warnOnce(\n 'Nav.Category:expandIcon-button',\n `Nav.Category: \\`expandIcon\\` received ${expandIconButton}; its children render as the ` +\n 'glyph of the toggle button and its props were dropped (buttons cannot be nested). ' +\n 'Pass icon content instead, e.g. `expandIcon={<MyIcon />}`.',\n );\n }\n }, [expandIconButton]);\n const expandIconMotionClassName = useMotionClasses(expandIconMotion, expandIconRecipe);\n let expandIconElement: React.ReactNode = null;\n if (expandGlyph === undefined || expandGlyph === null) {\n expandIconElement = (\n <ChevronDownIcon\n className={cn(\n navCategoryClassNames.expandIcon,\n 'shrink-0',\n expandIconMotionClassName,\n isOpen && 'rotate-180',\n )}\n />\n );\n } else if (slotRendersContent(expandGlyph)) {\n expandIconElement = renderSlot(\n expandGlyph,\n 'span',\n cn(navCategoryClassNames.expandIcon, 'inline-flex shrink-0', expandIconMotionClassName),\n { 'aria-hidden': true },\n );\n }\n\n let buttonLabel: React.ReactNode = label;\n let items: React.ReactNode = children;\n if (label === undefined) {\n // Deprecated 0.4 path: the text children are the label, the other children the sub-items.\n warnDeprecated(\n 'Nav.Category',\n 'text children as the label',\n 'label',\n 'Pass the category label in `label` and only the sub-items as children.',\n );\n const parts = React.Children.toArray(children);\n const isText = (part: unknown) => typeof part === 'string' || typeof part === 'number';\n buttonLabel = parts.filter(isText).join('');\n items = parts.filter((part) => !isText(part));\n }\n\n return (\n <li ref={ref} {...rest} className={cn(navCategoryClassNames.root, className)}>\n <button\n ref={buttonRef}\n type=\"button\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? listId : undefined}\n aria-current={containsCurrent ? true : undefined}\n data-contains-current={containsCurrent ? '' : undefined}\n data-roving-value={roving ? `wave-nav-category:${value}` : undefined}\n onClick={() => toggleCategory(value)}\n className={cn(navCategoryClassNames.button, categoryButtonClasses)}\n >\n {renderIcon(icon, navCategoryClassNames.icon)}\n <span className={cn(navCategoryClassNames.label, 'flex-1 text-start')}>{buttonLabel}</span>\n {expandIconElement}\n </button>\n {isListMounted && (\n <NavCategoryValueContext.Provider value={value}>\n <div\n ref={collapseRef}\n {...collapsePresenceProps}\n className={cn(navCategoryClassNames.collapse, collapseClassName)}\n >\n <ul\n ref={listRef}\n id={listId}\n className={cn(navCategoryClassNames.list, 'm-0 list-none p-0')}\n >\n {items}\n </ul>\n </div>\n </NavCategoryValueContext.Provider>\n )}\n </li>\n );\n};\nNavCategory.displayName = 'NavCategory';\nmarkNavPart(NavCategory, 'category');\n\n// ---------------------------------------------------------------------------\n// Nav.Item / Nav.SubItem\n// ---------------------------------------------------------------------------\n\n/**\n * A top-level navigation entry: a link when `href` is given (anchor props), a button otherwise\n * (button props). Clicking selects it (`aria-current=\"page\"`); activating a disabled entry never\n * selects it (a disabled entry whose value is the current value still shows as current).\n *\n * A click that opens a link somewhere other than the current page selects nothing (the consumer's\n * `onClick` still runs, and the browser opens the link): Ctrl/Cmd/Shift/Alt-click, a mouse button\n * other than the main one, a `target` other than `_self`, or a `download` link. When the consumer's\n * `onClick` calls `preventDefault()` (client-side routing), the browser opens nothing, so the item\n * is selected whatever the keys, button or `target`.\n *\n * `actions` puts your own controls (a pin toggle, a menu button) beside the item in its row, in a\n * group named by the item; they never select it.\n *\n * Typed by overloads, resolved in order: without `href` (button props, button events), with a\n * string `href` (anchor props, anchor events), then an `href` that may be `undefined` at run time\n * ({@link NavItemDynamicProps}: events of either element).\n *\n * Also exported as `NavItem` (import the flat name from React Server Components).\n */\nfunction NavItem(props: NavItemButtonProps): React.ReactElement;\nfunction NavItem(props: NavItemAnchorProps): React.ReactElement;\nfunction NavItem(props: NavItemDynamicProps): React.ReactElement;\nfunction NavItem(props: NavItemProps | NavItemDynamicProps): React.ReactElement {\n const context = useNavContext('Nav.Item');\n useNavValue(context, 'item', props.value);\n useRecordCategory(context, props.value);\n const roving = React.useContext(NavRovingContext);\n // Called always, rendered only while the item's actions render (D119).\n const generatedId = useId('wave-nav-item');\n const motionPreference = useMotionPreference();\n return renderNavEntry(\n props as NavEntryProps,\n context,\n roving,\n itemClasses,\n {\n root: navItemClassNames.root,\n listItem: navItemClassNames.listItem,\n actions: navItemClassNames.actions,\n icon: navItemClassNames.icon,\n content: navItemClassNames.content,\n },\n true,\n generatedId,\n motionPreference,\n );\n}\nNavItem.displayName = 'NavItem';\nmarkNavPart(NavItem, 'entry');\n\n/**\n * An indented entry inside a `Nav.Category`: a link when `href` is given, a button otherwise.\n * Selected like `Nav.Item` (a click that the browser opens somewhere else selects nothing; one\n * whose default your `onClick` prevents is selected), and typed by overloads like `Nav.Item`\n * (button, link, then {@link NavSubItemDynamicProps}). Takes `actions` like `Nav.Item`.\n *\n * Also exported as `NavSubItem` (import the flat name from React Server Components).\n */\nfunction NavSubItem(props: NavSubItemButtonProps): React.ReactElement;\nfunction NavSubItem(props: NavSubItemAnchorProps): React.ReactElement;\nfunction NavSubItem(props: NavSubItemDynamicProps): React.ReactElement;\nfunction NavSubItem(props: NavSubItemProps | NavSubItemDynamicProps): React.ReactElement {\n const context = useNavContext('Nav.SubItem');\n useNavValue(context, 'item', props.value);\n useRecordCategory(context, props.value);\n const roving = React.useContext(NavRovingContext);\n // Called always, rendered only while the sub-item's actions render (D119).\n const generatedId = useId('wave-nav-item');\n const motionPreference = useMotionPreference();\n return renderNavEntry(\n props as NavEntryProps,\n context,\n roving,\n subItemClasses,\n {\n root: navSubItemClassNames.root,\n listItem: navSubItemClassNames.listItem,\n actions: navSubItemClassNames.actions,\n },\n false,\n generatedId,\n motionPreference,\n );\n}\nNavSubItem.displayName = 'NavSubItem';\nmarkNavPart(NavSubItem, 'entry');\n\n/**\n * A vertical side navigation (`<nav>` landmark, default name \"Navigation\") with items, links and\n * collapsible categories.\n *\n * - **Selection**: `value`/`defaultValue`/`onValueChange` (`onValueChange` fires only when the\n * value changes). The deprecated `selectedValue`/`defaultSelectedValue`/`onNavItemSelect` still\n * work; `onNavItemSelect` keeps firing on every activation, re-selection included. A click that\n * opens a link in another tab or window (or downloads it) selects nothing, unless the item's\n * `onClick` prevents the default (client-side routing: then nothing opens elsewhere).\n * - **Categories**: `openCategories`/`defaultOpenCategories`/`onOpenCategoriesChange`. Without\n * `defaultOpenCategories`, the categories containing the selected item (`value` or\n * `defaultValue`) start open. A closed category that contains the selected item marks its toggle\n * (`aria-current=\"true\"`, `data-contains-current`, the selected look); pass `currentCategory`\n * for sub-items your own component renders inside a closed category.\n * - **Values** are unique: among the items and sub-items, and among the categories (a duplicate\n * warns in development).\n * - **Structure**: every child of the Nav, and of a category, is a part or your own `<li>`; a\n * development warning names anything else (a `<div>`, text, the wrapper of a Tooltip around an\n * item). `Nav.SectionHeader` is a heading between groups of items (`<h3>` unless\n * `headingLevel`, which stands for the `as` of Fluent's NavSectionHeader), and `Nav.Divider` a\n * line between groups, hidden from assistive technology (Fluent's NavDivider is a separator).\n * - **App identity**: `Nav.AppItem` shows the app's name and logo at the top, as a link with\n * `href` or a button; it is never selected. `Nav.AppItemStatic` shows them as plain text.\n * - **Item actions**: `actions` on `Nav.Item` and `Nav.SubItem` (Fluent's SplitNavItem) puts your\n * own controls beside the item, in a group named by it; each is a Tab stop after the item, and\n * none selects it. They fade in while the row is hovered or has focus, while one is pressed or\n * has its menu open, and are always drawn on touch screens and in forced colours. With actions, a\n * selected item's background and indicator are drawn on its row (`.wave-nav-item__list-item`).\n * - **Motion**: a category's list opens and closes its space with a short collapse and fade\n * (`motion` on `Nav.Category`), its chevron's turn is animated (`expandIconMotion`) and item\n * actions fade in. None of these defaults runs under reduced motion, and a `WaveProvider` with\n * `motion=\"none\"` turns them off, while a category's own `motion` or `expandIconMotion` value\n * still applies. Focus inside a list that closes moves to its category's toggle button.\n *\n * Sub-components are also exported under flat names (`NavCategory`, `NavItem`, `NavSubItem`,\n * `NavSectionHeader`, `NavDivider`, `NavAppItem`, `NavAppItemStatic`): React Server Components\n * import those, because dotted access (`Nav.Item`) needs a client file.\n */\nexport const Nav = /* @__PURE__ */ Object.assign(NavRoot, {\n Category: NavCategory,\n Item: NavItem,\n SubItem: NavSubItem,\n SectionHeader: NavSectionHeader,\n Divider: NavDivider,\n AppItem: NavAppItem,\n AppItemStatic: NavAppItemStatic,\n});\n\nexport {\n NavCategory,\n NavItem,\n NavSubItem,\n NavSectionHeader,\n NavDivider,\n NavAppItem,\n NavAppItemStatic,\n};\n"],"mappings":"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"}
@@ -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/useId.cjs"),o=require("../../hooks/useRovingTabIndex.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../button/Toolbar.navigation.cjs"),l=require("./Nav.context.cjs"),u=require("./Nav.root.cjs"),d=require("../overlays/Dialog.shared.cjs"),f=require("../overlays/Drawer.panel.cjs"),p=require("../overlays/Drawer.scroll.cjs"),m=require("./NavDrawer.context.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime");var _=`NavDrawer:unreachable`,v="NavDrawer is closed and nothing can open it: it is uncontrolled (no `open` prop), and a Hamburger inside it cannot be reached while it is closed. Control it with `open` and `onOpenChange`, and open it from a Hamburger (or any button) outside it.",y=`NavDrawer:loose-items`,b=`NavDrawer: a list item sits outside NavDrawer.Body and NavDrawer.Footer, the parts that render a list. Move Nav.Item, Nav.Category and the other Nav parts into NavDrawer.Body or NavDrawer.Footer.`;function x(e){for(let t of Array.from(e.querySelectorAll(`li`))){let e=t.parentElement?.localName;if(e!==`ul`&&e!==`ol`)return!0}return!1}var S={scrollState:`none`,registerBody:()=>()=>{}};function C(e){return h.useContext(m.NavDrawerLayoutContext)||(n.reportMissingContext(e,`NavDrawer`),S)}var w=({type:e=`overlay`,open:r,defaultOpen:o,onOpenChange:s,onItemSelect:c,position:S=`start`,size:C=`small`,separator:w=!0,modalType:T=`modal`,unmountOnClose:E=!0,finalFocusRef:D,backdrop:O,value:k,defaultValue:A,onValueChange:j,openCategories:M,defaultOpenCategories:N,onOpenCategoriesChange:P,currentCategory:F,"aria-label":I,"aria-labelledby":L,"aria-describedby":R,id:z,children:B,ref:V,...H})=>{let[U,W]=d.useModalOpenState(r,o,s),G=f.useDrawerOpen(e,U),K=u.useNavRootState({componentName:`NavDrawer`,value:k,defaultValue:A??``,onValueChange:j,onActivate:c,openCategories:M,defaultOpenCategories:N,onOpenCategoriesChange:P,currentCategory:F,children:B}),ee=T===`non-modal`?`non-modal`:`modal`,te=a.useId(`wave-nav-drawer`),q=z??te,[ne,J]=h.useState(null),Y=h.useCallback(e=>(J(t=>t??e),()=>J(t=>t===e?null:t)),[]),X=p.useScrollState(ne),re=h.useMemo(()=>({scrollState:X,registerBody:Y}),[X,Y]),ie=h.useMemo(()=>({open:G,requestOpen:W,panelId:q,type:e}),[G,W,q,e]),Z=r===void 0&&!U;h.useEffect(()=>{Z&&n.warnOnce(_,v)},[Z]);let Q=h.useRef(null);h.useEffect(()=>{if(!n.isDev||n.hasWarned(y))return;let e=Q.current;e&&x(e)&&n.warnOnce(y,b)});let $={"aria-label":I??(L===void 0?`Navigation`:void 0),"aria-labelledby":L,"aria-describedby":R},ae=e===`overlay`?$:void 0,oe=(0,g.jsx)(f.DrawerPanel,{componentName:`NavDrawer`,type:e,open:G,requestOpen:W,position:S,size:C,separator:w,modalType:ee,unmountOnClose:E,inlineAs:`div`,trigger:d.inertModalTrigger,finalFocusRef:D,rootClassName:t.cn(i.drawerClassNames.root,i.navDrawerClassNames.root),backdropClassName:t.cn(i.drawerClassNames.backdrop,i.navDrawerClassNames.backdrop),backdrop:O,id:q,...ae,...H,ref:V,children:(0,g.jsx)(`nav`,{ref:Q,...$,className:t.cn(i.navDrawerClassNames.nav,`flex min-h-0 flex-1 flex-col`),children:B})});return d.useModalTriggerSession(d.inertModalTrigger,G),(0,g.jsx)(l.NavContext.Provider,{value:K,children:(0,g.jsx)(m.NavDrawerContext.Provider,{value:ie,children:(0,g.jsx)(m.NavDrawerLayoutContext.Provider,{value:re,children:oe})})})};w.displayName=`NavDrawer`;var T=({className:e,children:n,ref:r,...a})=>{let{scrollState:o}=C(`NavDrawer.Header`);return(0,g.jsx)(`div`,{"data-scroll-state":o,...a,ref:r,className:t.cn(i.navDrawerHeaderClassNames.root,`flex shrink-0 items-center gap-2 ps-2.5 pe-2 py-2`,p.scrollSeparatorClasses.header,e),children:n})};T.displayName=`NavDrawerHeader`;var E=({focusMode:e=`tab`,className:n,onKeyDown:a,onFocus:u,children:d,ref:f,...p})=>{let{scrollState:m,registerBody:_}=C(`NavDrawer.Body`),v=h.useContext(l.NavContext),y=e===`arrow`,[b,x]=h.useState(null),S=h.useCallback((e,t)=>{x(n=>t?e:n===e?null:n)},[]),w=h.useMemo(()=>({reportCurrentCategory:S}),[S]),T=v?.value??``,E=b===null?T||null:`wave-nav-category:${b}`,{containerProps:D}=o.useRovingTabIndex({itemSelector:c.TOOLBAR_ITEM_SELECTOR,manageTabIndex:!0,tabStop:`last-focused`,orientation:`both`,loop:!0,homeEndKeys:!0,typeahead:!1,activeValue:E}),O=h.useCallback(e=>e?_(e):void 0,[_]),k=s.useMergedRefs(f,O,y?D.ref:null),A=h.useRef(null);return l.useNavListChildCheck(A,`NavDrawer.Body`,`items`),(0,g.jsx)(`div`,{"data-focus-mode":e,"data-scroll-state":m,...p,ref:k,"data-roving-container":y?``:void 0,onKeyDown:r.composeEventHandlers(a,y?D.onKeyDown:void 0),onFocus:r.composeEventHandlers(u,y?D.onFocus:void 0,{checkDefaultPrevented:!1}),className:t.cn(i.navDrawerBodyClassNames.root,`min-h-0 flex-1 overflow-y-auto py-2`,n),children:(0,g.jsx)(l.NavRovingContext.Provider,{value:y?w:null,children:(0,g.jsx)(`ul`,{ref:A,className:t.cn(i.navDrawerBodyClassNames.list,`m-0 list-none p-0`),children:d})})})};E.displayName=`NavDrawerBody`;var D=({className:e,children:n,ref:r,...a})=>{let{scrollState:o}=C(`NavDrawer.Footer`),s=h.useRef(null);return l.useNavListChildCheck(s,`NavDrawer.Footer`,`items`),(0,g.jsx)(`div`,{"data-scroll-state":o,...a,ref:r,className:t.cn(i.navDrawerFooterClassNames.root,`shrink-0 py-2`,p.scrollSeparatorClasses.footer,e),children:(0,g.jsx)(`ul`,{ref:s,className:t.cn(i.navDrawerFooterClassNames.list,`m-0 list-none p-0`),children:n})})};D.displayName=`NavDrawerFooter`;var O=Object.assign(w,{Header:T,Body:E,Footer:D});exports.NavDrawer=O,exports.NavDrawerBody=E,exports.NavDrawerFooter=D,exports.NavDrawerHeader=T;
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/useId.cjs"),o=require("../../hooks/useRovingTabIndex.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../button/Toolbar.navigation.cjs"),l=require("./Nav.context.cjs"),u=require("./Nav.root.cjs"),d=require("../overlays/Dialog.shared.cjs"),f=require("../overlays/Drawer.panel.cjs"),p=require("../overlays/Drawer.scroll.cjs"),m=require("./NavDrawer.context.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime");var _=`NavDrawer:unreachable`,v="NavDrawer is closed and nothing can open it: it is uncontrolled (no `open` prop), and a Hamburger inside it cannot be reached while it is closed. Control it with `open` and `onOpenChange`, and open it from a Hamburger (or any button) outside it.",y=`NavDrawer:loose-items`,b=`NavDrawer: a list item sits outside NavDrawer.Body and NavDrawer.Footer, the parts that render a list. Move Nav.Item, Nav.Category and the other Nav parts into NavDrawer.Body or NavDrawer.Footer.`;function x(e){for(let t of Array.from(e.querySelectorAll(`li`))){let e=t.parentElement?.localName;if(e!==`ul`&&e!==`ol`)return!0}return!1}var S={scrollState:`none`,registerBody:()=>()=>{}};function C(e){return h.useContext(m.NavDrawerLayoutContext)||(n.reportMissingContext(e,`NavDrawer`),S)}var w=({type:e=`overlay`,open:r,defaultOpen:o,onOpenChange:s,onItemSelect:c,position:S=`start`,size:C=`small`,separator:w=!0,modalType:T=`modal`,unmountOnClose:E=!0,finalFocusRef:D,backdrop:O,motion:k,backdropMotion:A,value:j,defaultValue:ee,onValueChange:te,openCategories:M,defaultOpenCategories:N,onOpenCategoriesChange:P,currentCategory:F,"aria-label":I,"aria-labelledby":L,"aria-describedby":ne,id:re,children:R,ref:ie,...z})=>{let[B,V]=d.useModalOpenState(r,o,s),H=f.useDrawerOpen(e,B),U=u.useNavRootState({componentName:`NavDrawer`,value:j,defaultValue:ee??``,onValueChange:te,onActivate:c,openCategories:M,defaultOpenCategories:N,onOpenCategoriesChange:P,currentCategory:F,children:R}),W=T===`non-modal`?`non-modal`:`modal`,G=a.useId(`wave-nav-drawer`),K=re??G,[q,J]=h.useState(null),Y=h.useCallback(e=>(J(t=>t??e),()=>J(t=>t===e?null:t)),[]),X=p.useScrollState(q),ae=h.useMemo(()=>({scrollState:X,registerBody:Y}),[X,Y]),oe=h.useMemo(()=>({open:H,requestOpen:V,panelId:K,type:e}),[H,V,K,e]),Z=r===void 0&&!B;h.useEffect(()=>{Z&&n.warnOnce(_,v)},[Z]);let Q=h.useRef(null);h.useEffect(()=>{if(!n.isDev||n.hasWarned(y))return;let e=Q.current;e&&x(e)&&n.warnOnce(y,b)});let $={"aria-label":I??(L===void 0?`Navigation`:void 0),"aria-labelledby":L,"aria-describedby":ne},se=e===`overlay`?$:void 0,ce=(0,g.jsx)(f.DrawerPanel,{componentName:`NavDrawer`,type:e,open:H,requestOpen:V,position:S,size:C,separator:w,modalType:W,unmountOnClose:E,inlineAs:`div`,trigger:d.inertModalTrigger,finalFocusRef:D,rootClassName:t.cn(i.drawerClassNames.root,i.navDrawerClassNames.root),backdropClassName:t.cn(i.drawerClassNames.backdrop,i.navDrawerClassNames.backdrop),collapseClassName:t.cn(i.drawerClassNames.collapse,i.navDrawerClassNames.collapse),backdrop:O,motion:k,backdropMotion:A,id:K,...se,...z,ref:ie,children:(0,g.jsx)(`nav`,{ref:Q,...$,className:t.cn(i.navDrawerClassNames.nav,`flex min-h-0 flex-1 flex-col`),children:R})});return d.useModalTriggerSession(d.inertModalTrigger,H),(0,g.jsx)(l.NavContext.Provider,{value:U,children:(0,g.jsx)(m.NavDrawerContext.Provider,{value:oe,children:(0,g.jsx)(m.NavDrawerLayoutContext.Provider,{value:ae,children:ce})})})};w.displayName=`NavDrawer`;var T=({className:e,children:n,ref:r,...a})=>{let{scrollState:o}=C(`NavDrawer.Header`);return(0,g.jsx)(`div`,{"data-scroll-state":o,...a,ref:r,className:t.cn(i.navDrawerHeaderClassNames.root,`flex shrink-0 items-center gap-2 ps-2.5 pe-2 py-2`,p.scrollSeparatorClasses.header,e),children:n})};T.displayName=`NavDrawerHeader`;var E=({focusMode:e=`tab`,className:n,onKeyDown:a,onFocus:u,children:d,ref:f,...p})=>{let{scrollState:m,registerBody:_}=C(`NavDrawer.Body`),v=h.useContext(l.NavContext),y=e===`arrow`,[b,x]=h.useState(null),S=h.useCallback((e,t)=>{x(n=>t?e:n===e?null:n)},[]),w=h.useMemo(()=>({reportCurrentCategory:S}),[S]),T=v?.value??``,E=b===null?T||null:`wave-nav-category:${b}`,{containerProps:D}=o.useRovingTabIndex({itemSelector:c.TOOLBAR_ITEM_SELECTOR,manageTabIndex:!0,tabStop:`last-focused`,orientation:`both`,loop:!0,homeEndKeys:!0,typeahead:!1,activeValue:E}),O=h.useCallback(e=>e?_(e):void 0,[_]),k=s.useMergedRefs(f,O,y?D.ref:null),A=h.useRef(null);return l.useNavListChildCheck(A,`NavDrawer.Body`,`items`),(0,g.jsx)(`div`,{"data-focus-mode":e,"data-scroll-state":m,...p,ref:k,"data-roving-container":y?``:void 0,onKeyDown:r.composeEventHandlers(a,y?D.onKeyDown:void 0),onFocus:r.composeEventHandlers(u,y?D.onFocus:void 0,{checkDefaultPrevented:!1}),className:t.cn(i.navDrawerBodyClassNames.root,`min-h-0 flex-1 overflow-y-auto py-2`,n),children:(0,g.jsx)(l.NavRovingContext.Provider,{value:y?w:null,children:(0,g.jsx)(`ul`,{ref:A,className:t.cn(i.navDrawerBodyClassNames.list,`m-0 list-none p-0`),children:d})})})};E.displayName=`NavDrawerBody`;var D=({className:e,children:n,ref:r,...a})=>{let{scrollState:o}=C(`NavDrawer.Footer`),s=h.useRef(null);return l.useNavListChildCheck(s,`NavDrawer.Footer`,`items`),(0,g.jsx)(`div`,{"data-scroll-state":o,...a,ref:r,className:t.cn(i.navDrawerFooterClassNames.root,`shrink-0 py-2`,p.scrollSeparatorClasses.footer,e),children:(0,g.jsx)(`ul`,{ref:s,className:t.cn(i.navDrawerFooterClassNames.list,`m-0 list-none p-0`),children:n})})};D.displayName=`NavDrawerFooter`;var O=Object.assign(w,{Header:T,Body:E,Footer:D});exports.NavDrawer=O,exports.NavDrawerBody=E,exports.NavDrawerFooter=D,exports.NavDrawerHeader=T;
2
2
  //# sourceMappingURL=NavDrawer.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"NavDrawer.cjs","names":["React","NavDrawerLayoutContext","useModalOpenState","useDrawerOpen","useNavRootState","useId","useScrollState","isDev","hasWarned","DrawerPanel","inertModalTrigger","cn","drawerClassNames","navDrawerClassNames","NavContext","NavDrawerContext","navDrawerHeaderClassNames","scrollSeparatorClasses","useRovingTabIndex","TOOLBAR_ITEM_SELECTOR","useMergedRefs","composeEventHandlers","navDrawerBodyClassNames","NavRovingContext","navDrawerFooterClassNames","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useId","require_useRovingTabIndex","require_useMergedRefs","require_Toolbar_navigation","require_Nav_context","require_Nav_root","require_Dialog_shared","require_Drawer_panel","require_Drawer_scroll","require_NavDrawer_context","react","react_jsx_runtime","UNREACHABLE_WARNING_KEY","UNREACHABLE_WARNING","LOOSE_ITEMS_WARNING_KEY","LOOSE_ITEMS_WARNING","hasLooseListItem","item","nav","parent","INERT_LAYOUT","useNavDrawerLayout","componentName","NavDrawerRoot","openProp","modalTypeProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","rest","openState","requestOpen","defaultOpen","onOpenChange","open","type","navState","defaultValue","onItemSelect","modalType","generatedId","panelId","id","body","setBody","registerBody","previous","element","scrollState","layout","drawer","unreachable","navRef","nameProps","panelNameProps","panel","NavDrawerHeader","className","NavDrawerBody","arrow","focusMode","currentCategory","setCurrentCategory","reportCurrentCategory","holdsCurrent","category","roving","selected","activeValue","attachBody","mergedRef","ref","containerProps","listRef","onKeyDown","onFocus","NavDrawerFooter","NavDrawer"],"sources":["../../../src/components/navigation/NavDrawer.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n drawerClassNames,\n navDrawerBodyClassNames,\n navDrawerClassNames,\n navDrawerFooterClassNames,\n navDrawerHeaderClassNames,\n} from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { hasWarned, isDev, reportMissingContext, warnOnce } from '../../lib/dev';\nimport type { Slot, SlotObject } from '../../lib/slot';\nimport type { BackdropAppearance, FocusMode, ModalType } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { TOOLBAR_ITEM_SELECTOR } from '../button/Toolbar.navigation';\nimport {\n inertModalTrigger,\n useModalOpenState,\n useModalTriggerSession,\n} from '../overlays/Dialog.shared';\nimport type {\n DrawerOpenChangeDetails,\n DrawerPosition,\n DrawerSize,\n DrawerType,\n} from '../overlays/Drawer.context';\nimport { DrawerPanel, useDrawerOpen } from '../overlays/Drawer.panel';\nimport { scrollSeparatorClasses, useScrollState } from '../overlays/Drawer.scroll';\nimport {\n NavContext,\n NavRovingContext,\n useNavListChildCheck,\n type NavRovingContextValue,\n} from './Nav.context';\nimport { useNavRootState, type NavProps } from './Nav.root';\nimport {\n NavDrawerContext,\n NavDrawerLayoutContext,\n type NavDrawerContextValue,\n type NavDrawerLayoutContextValue,\n} from './NavDrawer.context';\n\n/*\n * NavDrawer: Nav's state (`useNavRootState`) and a navigation landmark in the drawer panel shell\n * (`DrawerPanel`), with its Header, Body and Footer parts. Imports the Nav root and context modules\n * (never `Nav.tsx`) and the shell's modules (never Drawer's root or compound); Nav never imports\n * it, and `Hamburger.tsx` reads only `NavDrawer.context.ts`.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Properties for the NavDrawer component. */\nexport interface NavDrawerProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'>,\n Pick<\n NavProps,\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'openCategories'\n | 'defaultOpenCategories'\n | 'onOpenCategoriesChange'\n | 'currentCategory'\n > {\n /**\n * How the drawer sits on the page (Fluent's `type`).\n * - `overlay`: a panel over the page, rendered in a portal while open (in the browser only: an\n * open overlay is closed in the server HTML and opens once hydrated). Modal by default: focus\n * moves in and stays there, the rest of the page is `inert` and does not scroll, and Escape\n * and a backdrop press close it. It is a dialog with the navigation's name.\n * - `inline`: a panel in the page layout, rendered where the NavDrawer is (also in the server\n * HTML). The page stays usable around it; Escape and presses outside do nothing; opening it\n * moves no focus, and closing it while focus is inside returns focus to `finalFocusRef`, else\n * to the element that opened it.\n *\n * Changing `type` remounts the panel; the selection and the open categories are kept. Rendered\n * as `data-type`.\n * @default 'overlay'\n */\n type?: DrawerType;\n /** Controlled open state. */\n open?: boolean;\n /**\n * Open state for uncontrolled usage. Keep the drawer controlled instead: a closed uncontrolled\n * NavDrawer cannot be opened again (a Hamburger inside it is not shown while it is closed).\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the new open state when it changes, with `details.reason`: `trigger` (a Hamburger\n * inside the drawer), `escape` and `outside-press` (the backdrop; overlay only). `details` is\n * typed optional until 1.0. A controlled drawer stays as it is until you update `open`.\n */\n onOpenChange?: (open: boolean, details?: DrawerOpenChangeDetails) => void;\n /**\n * Called with an item's value every time an item is activated, also when the current page is\n * activated again (a disabled item, a link opened in another tab or window, and a button item\n * whose `onClick` calls `preventDefault()` are not activations). Close an overlay drawer here:\n * `onValueChange` fires only when the value changes. Fluent's `onNavItemSelect`.\n */\n onItemSelect?: (value: string) => void;\n /**\n * The edge the panel is attached to: an overlay's screen edge; an inline panel's inner edge is\n * the opposite one. `start`/`end` follow the text direction; `left`/`right` are physical sides;\n * `bottom` runs along the bottom edge. Unlike Drawer's (`'end'`), the default is the start edge,\n * where navigation sits (Fluent's). Rendered as `data-position`.\n * @default 'start'\n */\n position?: DrawerPosition;\n /**\n * The panel's width at a side (its height at the bottom), on Drawer's scale: `small` 320px,\n * `medium` 592px, `large` 940px, `full` the viewport (inline: the container). A width class in\n * `className` replaces it (Fluent's navigation pane is 260px wide: the width class of 65\n * spacing steps). Rendered as `data-size`. Drawer's default too.\n * @default 'small'\n */\n size?: DrawerSize;\n /**\n * Inline drawers: draws a line on the panel's inner edge (`data-separator`), as Nav does\n * (Drawer's `separator` defaults to `false`). An overlay always draws that edge; forced colours\n * always draw it.\n * @default true\n */\n separator?: boolean;\n /**\n * Overlay drawers: `modal` (backdrop, focus trapped, page inert and not scrolling) or\n * `non-modal` (no backdrop, no trap, nothing inert; Escape closes it while focus is inside, and\n * its Tab place follows the element that opened it). A non-modal overlay covers the page under\n * it while the page keeps its Tab order: keep the page's controls clear of it (reserve its width,\n * or its height at the bottom, in your layout while it is open) or use `type=\"inline\"`; with\n * `size=\"full\"` it hides the whole page and warns. Ignored by inline drawers. Rendered as\n * `data-modal-type` on an overlay's panel. Fluent's `modalType` (without `alert`: a navigation\n * pane is never an alert, so an `'alert'` is treated as `'modal'`). Drawer's default too.\n * @default 'modal'\n */\n modalType?: Extract<ModalType, 'modal' | 'non-modal'>;\n /**\n * Removes the panel when the drawer closes. `false` keeps it mounted while closed, out of view\n * and `inert`, so the state of what is inside survives, and a Hamburger outside can point\n * `aria-controls` at it at all times: always for an inline drawer, and once the page has\n * hydrated for an overlay (whose panel is not in the server HTML). Fluent's `unmountOnClose`.\n * Drawer's default too.\n * @default true\n */\n unmountOnClose?: boolean;\n /**\n * Where focus goes when the drawer closes with focus inside it (a modal overlay: whenever it\n * closes). Pass your page's Hamburger, so a Hamburger inside the drawer that closes it hands\n * focus to the one that opens it again.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * The backdrop of a modal overlay (Drawer's `backdrop` slot: `null` renders none, a slot\n * object's `appearance` picks the fill). Ignored, with a development warning, by a non-modal or\n * inline drawer.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /**\n * Name of the navigation landmark (and of an overlay's dialog). Localize it; rename it when the\n * page has another navigation landmark (two with one name are ambiguous). An `aria-labelledby`\n * replaces the default.\n * @default 'Navigation'\n */\n 'aria-label'?: string;\n /** `NavDrawer.Header`, `NavDrawer.Body` and `NavDrawer.Footer`, rendered in the order written. */\n children?: React.ReactNode;\n /** Ref to the panel: the `role=\"dialog\"` element of an overlay drawer, the panel element of an inline one. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the NavDrawerHeader sub-component. */\nexport interface NavDrawerHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** A Hamburger, the app's name, …: any content (Nav items go in the body or the footer). */\n children?: React.ReactNode;\n /** Ref to the header element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the NavDrawerBody sub-component. */\nexport interface NavDrawerBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * How the keyboard reaches the items. `'tab'`: every item is a Tab stop and the arrow keys do\n * nothing (Nav's model). `'arrow'`: the body is one Tab stop, the last focused element (at first\n * the current page, or the closed category that holds it, else the first item); Down and Right\n * move to the next element and Up and Left to the previous one (Left and Right swap in a\n * right-to-left layout), wrapping, and Home and End go to the ends. Every focusable element in\n * the body joins the order, item actions included. Screen readers do not announce arrow keys in\n * a navigation landmark: prefer `'tab'` unless your users expect an app pane. Rendered as\n * `data-focus-mode`. Fluent's NavDrawer uses arrow keys by default (its `tabbable` adds Tab\n * stops).\n * @default 'tab'\n */\n focusMode?: FocusMode;\n /** Nav parts: `Nav.Item`, `Nav.Category`, `Nav.SectionHeader`, … (each renders its own list item). */\n children?: React.ReactNode;\n /** Ref to the scrolling body element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the NavDrawerFooter sub-component. */\nexport interface NavDrawerFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Nav parts pinned below the body (Settings, Help); wrap other content in an `<li>`. */\n children?: React.ReactNode;\n /** Ref to the footer element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// Development checks\n// ---------------------------------------------------------------------------\n\nconst UNREACHABLE_WARNING_KEY = 'NavDrawer:unreachable';\nconst UNREACHABLE_WARNING =\n 'NavDrawer is closed and nothing can open it: it is uncontrolled (no `open` prop), and a Hamburger inside it cannot be reached while it is closed. Control it with `open` and `onOpenChange`, and open it from a Hamburger (or any button) outside it.';\n\nconst LOOSE_ITEMS_WARNING_KEY = 'NavDrawer:loose-items';\nconst LOOSE_ITEMS_WARNING =\n 'NavDrawer: a list item sits outside NavDrawer.Body and NavDrawer.Footer, the parts that render a list. Move Nav.Item, Nav.Category and the other Nav parts into NavDrawer.Body or NavDrawer.Footer.';\n\n/** Whether `nav` holds an `<li>` whose parent is not a `<ul>` or `<ol>`. */\nfunction hasLooseListItem(nav: HTMLElement): boolean {\n for (const item of Array.from(nav.querySelectorAll('li'))) {\n const parent = item.parentElement?.localName;\n if (parent !== 'ul' && parent !== 'ol') return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Root\n// ---------------------------------------------------------------------------\n\n/** The scroll state and body registry the parts read outside a NavDrawer in production. */\nconst INERT_LAYOUT: NavDrawerLayoutContextValue = {\n scrollState: 'none',\n registerBody: () => () => {},\n};\n\n/** C-CONTEXT: the enclosing NavDrawer's layout for the part `componentName`. */\nfunction useNavDrawerLayout(componentName: string): NavDrawerLayoutContextValue {\n const context = React.useContext(NavDrawerLayoutContext);\n if (context) return context;\n reportMissingContext(componentName, 'NavDrawer');\n return INERT_LAYOUT;\n}\n\n// The root of `NavDrawer` (documented on the export below).\nconst NavDrawerRoot = ({\n type = 'overlay',\n open: openProp,\n defaultOpen,\n onOpenChange,\n onItemSelect,\n position = 'start',\n size = 'small',\n separator = true,\n modalType: modalTypeProp = 'modal',\n unmountOnClose = true,\n finalFocusRef,\n backdrop,\n value,\n defaultValue,\n onValueChange,\n openCategories,\n defaultOpenCategories,\n onOpenCategoriesChange,\n currentCategory,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n id,\n children,\n ref,\n ...rest\n}: NavDrawerProps) => {\n const [openState, requestOpen] = useModalOpenState(openProp, defaultOpen, onOpenChange);\n // An overlay reports itself closed until the page has hydrated (its portal renders only in the\n // browser), so a Hamburger's aria-controls never names a panel that is not there.\n const open = useDrawerOpen(type, openState);\n const navState = useNavRootState({\n componentName: 'NavDrawer',\n value,\n defaultValue: defaultValue ?? '',\n onValueChange,\n onActivate: onItemSelect,\n openCategories,\n defaultOpenCategories,\n onOpenCategoriesChange,\n currentCategory,\n children,\n });\n // A navigation pane is never an alert: an 'alert' passed at run time is a modal one.\n const modalType: ModalType = modalTypeProp === 'non-modal' ? 'non-modal' : 'modal';\n const generatedId = useId('wave-nav-drawer');\n const panelId = id ?? generatedId;\n\n // The first mounted body, measured for the scroll-state separators of the parts.\n const [body, setBody] = React.useState<HTMLElement | null>(null);\n const registerBody = React.useCallback((element: HTMLElement) => {\n setBody((previous) => previous ?? element);\n return () => setBody((previous) => (previous === element ? null : previous));\n }, []);\n const scrollState = useScrollState(body);\n const layout = React.useMemo<NavDrawerLayoutContextValue>(\n () => ({ scrollState, registerBody }),\n [scrollState, registerBody],\n );\n const drawer = React.useMemo<NavDrawerContextValue>(\n () => ({ open, requestOpen, panelId, type }),\n [open, requestOpen, panelId, type],\n );\n\n // An uncontrolled drawer that is closed has no way back: its Hamburgers are inside it.\n const unreachable = openProp === undefined && !openState;\n React.useEffect(() => {\n if (unreachable) warnOnce(UNREACHABLE_WARNING_KEY, UNREACHABLE_WARNING);\n }, [unreachable]);\n\n // Development only: after every commit, a list item outside the Body's and Footer's lists.\n const navRef = React.useRef<HTMLElement>(null);\n React.useEffect(() => {\n if (!isDev || hasWarned(LOOSE_ITEMS_WARNING_KEY)) return;\n const nav = navRef.current;\n if (nav && hasLooseListItem(nav)) warnOnce(LOOSE_ITEMS_WARNING_KEY, LOOSE_ITEMS_WARNING);\n });\n\n // The name goes to the <nav> in both types and, in an overlay, also to its dialog panel. An\n // aria-labelledby without aria-label drops the default.\n const nameProps = {\n 'aria-label': ariaLabel ?? (ariaLabelledBy === undefined ? 'Navigation' : undefined),\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n };\n const panelNameProps = type === 'overlay' ? nameProps : undefined;\n\n const panel = (\n <DrawerPanel\n componentName=\"NavDrawer\"\n type={type}\n open={open}\n requestOpen={requestOpen}\n position={position}\n size={size}\n separator={separator}\n modalType={modalType}\n unmountOnClose={unmountOnClose}\n inlineAs=\"div\"\n trigger={inertModalTrigger}\n finalFocusRef={finalFocusRef}\n rootClassName={cn(drawerClassNames.root, navDrawerClassNames.root)}\n backdropClassName={cn(drawerClassNames.backdrop, navDrawerClassNames.backdrop)}\n backdrop={backdrop}\n id={panelId}\n {...panelNameProps}\n {...rest}\n ref={ref as React.Ref<HTMLElement> | undefined}\n >\n <nav\n ref={navRef}\n {...nameProps}\n className={cn(navDrawerClassNames.nav, 'flex min-h-0 flex-1 flex-col')}\n >\n {children}\n </nav>\n </DrawerPanel>\n );\n // After the shell's effects (focus restore), as the shell's contract asks.\n useModalTriggerSession(inertModalTrigger, open);\n\n return (\n <NavContext.Provider value={navState}>\n <NavDrawerContext.Provider value={drawer}>\n <NavDrawerLayoutContext.Provider value={layout}>{panel}</NavDrawerLayoutContext.Provider>\n </NavDrawerContext.Provider>\n </NavContext.Provider>\n );\n};\nNavDrawerRoot.displayName = 'NavDrawer';\n\n// ---------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------\n\n/**\n * The header row of a NavDrawer: a Hamburger, the app's name, … (no list: Nav items go in the\n * body or the footer). Its line underneath shows while the body is scrolled away from its top.\n */\nexport const NavDrawerHeader = ({ className, children, ref, ...rest }: NavDrawerHeaderProps) => {\n const { scrollState } = useNavDrawerLayout('NavDrawer.Header');\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n navDrawerHeaderClassNames.root,\n 'flex shrink-0 items-center gap-2 ps-2.5 pe-2 py-2',\n scrollSeparatorClasses.header,\n className,\n )}\n >\n {children}\n </div>\n );\n};\nNavDrawerHeader.displayName = 'NavDrawerHeader';\n\n/**\n * The scrolling list of a NavDrawer: the Nav parts (`Nav.Item`, `Nav.Category`, …) as the items of\n * its list. With `focusMode=\"arrow\"` it is one Tab stop and the arrow keys move through it.\n */\nexport const NavDrawerBody = ({\n focusMode = 'tab',\n className,\n onKeyDown,\n onFocus,\n children,\n ref,\n ...rest\n}: NavDrawerBodyProps) => {\n const { scrollState, registerBody } = useNavDrawerLayout('NavDrawer.Body');\n const nav = React.useContext(NavContext);\n const arrow = focusMode === 'arrow';\n\n // The closed category that holds the current page, reported by the categories of an arrow body\n // from their layout effects: it holds the first Tab stop while the current page is hidden.\n const [currentCategory, setCurrentCategory] = React.useState<string | null>(null);\n const reportCurrentCategory = React.useCallback((category: string, holdsCurrent: boolean) => {\n setCurrentCategory((previous) =>\n holdsCurrent ? category : previous === category ? null : previous,\n );\n }, []);\n const roving = React.useMemo<NavRovingContextValue>(\n () => ({ reportCurrentCategory }),\n [reportCurrentCategory],\n );\n const selected = nav?.value ?? '';\n const activeValue =\n currentCategory !== null ? `wave-nav-category:${currentCategory}` : selected || null;\n // Always called (C-HOOKS); the container attaches only in the arrow mode, and detaching it hands\n // every element its own tabindex back.\n const { containerProps } = useRovingTabIndex({\n itemSelector: TOOLBAR_ITEM_SELECTOR,\n manageTabIndex: true,\n tabStop: 'last-focused',\n orientation: 'both',\n loop: true,\n homeEndKeys: true,\n typeahead: false,\n activeValue,\n });\n\n const attachBody = React.useCallback(\n (element: HTMLDivElement | null) => (element ? registerBody(element) : undefined),\n [registerBody],\n );\n const mergedRef = useMergedRefs<HTMLDivElement>(\n ref,\n attachBody,\n arrow ? containerProps.ref : null,\n );\n // Development only: every child of the list is an <li> (`NavDrawer.Body:list-child`).\n const listRef = React.useRef<HTMLUListElement>(null);\n useNavListChildCheck(listRef, 'NavDrawer.Body', 'items');\n\n return (\n <div\n data-focus-mode={focusMode}\n data-scroll-state={scrollState}\n {...rest}\n ref={mergedRef}\n data-roving-container={arrow ? '' : undefined}\n onKeyDown={composeEventHandlers(onKeyDown, arrow ? containerProps.onKeyDown : undefined)}\n onFocus={composeEventHandlers(onFocus, arrow ? containerProps.onFocus : undefined, {\n checkDefaultPrevented: false,\n })}\n className={cn(navDrawerBodyClassNames.root, 'min-h-0 flex-1 overflow-y-auto py-2', className)}\n >\n <NavRovingContext.Provider value={arrow ? roving : null}>\n <ul ref={listRef} className={cn(navDrawerBodyClassNames.list, 'm-0 list-none p-0')}>\n {children}\n </ul>\n </NavRovingContext.Provider>\n </div>\n );\n};\nNavDrawerBody.displayName = 'NavDrawerBody';\n\n/**\n * The list pinned below a NavDrawer's body (Settings, Help): Nav parts as the items of its list,\n * each a Tab stop. Its line above shows while more of the body is below.\n */\nexport const NavDrawerFooter = ({ className, children, ref, ...rest }: NavDrawerFooterProps) => {\n const { scrollState } = useNavDrawerLayout('NavDrawer.Footer');\n // Development only: every child of the list is an <li> (`NavDrawer.Footer:list-child`).\n const listRef = React.useRef<HTMLUListElement>(null);\n useNavListChildCheck(listRef, 'NavDrawer.Footer', 'items');\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n navDrawerFooterClassNames.root,\n 'shrink-0 py-2',\n scrollSeparatorClasses.footer,\n className,\n )}\n >\n <ul ref={listRef} className={cn(navDrawerFooterClassNames.list, 'm-0 list-none p-0')}>\n {children}\n </ul>\n </div>\n );\n};\nNavDrawerFooter.displayName = 'NavDrawerFooter';\n\n// ---------------------------------------------------------------------------\n// Compound\n// ---------------------------------------------------------------------------\n\n/**\n * A navigation pane in a drawer: Nav's items, categories and selection in a `<nav>` landmark that\n * sits over the page (`type=\"overlay\"`) or in the page layout (`type=\"inline\"`). Fluent's\n * `NavDrawer`.\n *\n * - **Composition:** `NavDrawer.Header` (a row: a `Hamburger`, the app's name), `NavDrawer.Body`\n * (the scrolling list) and `NavDrawer.Footer` (a list pinned below it), rendered in the order\n * written. Nav parts (`Nav.Item`, `Nav.Category`, `Nav.SectionHeader`, `Nav.Divider`,\n * `Nav.AppItem`, …) go in the Body and the Footer, which render the lists; wrap anything else\n * there in an `<li>`.\n * - **Types:** `overlay` (default) is a panel over the page, in a portal, opened in the browser\n * only; `inline` is a panel in the page layout, also in the server HTML. Changing `type`\n * remounts the panel; the selection and the open categories are kept.\n * - **Opening and closing:** keep it controlled (`open`, `onOpenChange`): an uncontrolled drawer\n * that is closed cannot open again. A `Hamburger` inside it toggles it (reason `trigger`);\n * Escape and a backdrop press close an overlay (`escape`, `outside-press`). Closing an overlay\n * when an item is chosen is yours, in `onItemSelect`, which also fires when the current page is\n * activated again. A non-modal overlay (`modalType=\"non-modal\"`) covers the page, which keeps\n * its Tab order: keep the page's controls clear of it, or use `type=\"inline\"`.\n * - **Focus:** pass your page's Hamburger as `finalFocusRef`, so focus returns to it when a\n * Hamburger inside the drawer closes it. An overlay moves focus in when it opens; an inline\n * drawer does not.\n * - **Keyboard:** every item is a Tab stop; `NavDrawer.Body focusMode=\"arrow\"` makes the body one\n * Tab stop with arrow keys, Home and End.\n * - **Landmark:** one `<nav>`, named \"Navigation\" by default (`aria-label`, `aria-labelledby`);\n * an overlay is also a dialog with that name. Rename it when the page has another navigation\n * landmark.\n * - **Selection:** Nav's `value`/`onValueChange` (only on a change), `openCategories` and\n * `currentCategory`, and `onItemSelect` on every activation (Fluent's `selectedValue` and\n * `onNavItemSelect`).\n * - **Server Components:** the parts are also exported as `NavDrawerHeader`, `NavDrawerBody` and\n * `NavDrawerFooter`.\n *\n * @example\n * const [open, setOpen] = useState(false);\n * const hamburgerRef = useRef<HTMLButtonElement>(null);\n * <Hamburger\n * ref={hamburgerRef}\n * aria-expanded={open}\n * aria-controls={open ? 'main-nav' : undefined}\n * aria-haspopup=\"dialog\"\n * onClick={() => setOpen(!open)}\n * />\n * <NavDrawer\n * id=\"main-nav\"\n * open={open}\n * onOpenChange={setOpen}\n * onItemSelect={() => setOpen(false)}\n * finalFocusRef={hamburgerRef}\n * defaultValue=\"home\"\n * >\n * <NavDrawer.Header>\n * <Hamburger />\n * Contoso HR\n * </NavDrawer.Header>\n * <NavDrawer.Body>\n * <Nav.Item value=\"home\" href=\"/\">Home</Nav.Item>\n * </NavDrawer.Body>\n * </NavDrawer>\n */\nexport const NavDrawer = /* @__PURE__ */ Object.assign(NavDrawerRoot, {\n Header: NavDrawerHeader,\n Body: NavDrawerBody,\n Footer: NavDrawerFooter,\n});\n"],"mappings":"8qBAwNA,IAAM0C,EAA0B,wBAC1BC,EACJ,wPAEIC,EAA0B,wBAC1BC,EACJ,sMAGF,SAASC,EAAiB,EAA2B,CACnD,IAAK,IAAMC,KAAQ,MAAM,KAAKC,EAAI,iBAAiB,IAAI,CAAC,EAAG,CACzD,IAAMC,EAASF,EAAK,eAAe,UACnC,GAAIE,IAAW,MAAQA,IAAW,KAAM,MAAO,EACjD,CACA,MAAO,EACT,CAOA,IAAMC,EAA4C,CAChD,YAAa,OACb,qBAA0B,CAAC,CAC7B,EAGA,SAASC,EAAmB,EAAoD,CAI9E,OAHgBnD,EAAM,WAAWC,EAAAA,sBAC7B,IACJ0B,EAAA,qBAAqByB,EAAe,WAAW,EACxCF,EACT,CAGA,IAAMG,GAAiB,CACrB,OAAO,UACP,KAAMC,EACN,cACA,eACA,eACA,WAAW,QACX,OAAO,QACP,YAAY,GACZ,UAAWC,EAAgB,QAC3B,iBAAiB,GACjB,gBACA,WACA,QACA,eACA,gBACA,iBACA,wBACA,yBACA,kBACA,aAAcC,EACd,kBAAmBC,EACnB,mBAAoBC,EACpB,KACA,WACA,MACA,GAAGC,KACiB,CACpB,GAAM,CAACC,EAAWC,GAAe3D,EAAAA,kBAAkBoD,EAAUQ,EAAaC,CAAY,EAGhFC,EAAO7D,EAAAA,cAAc8D,EAAML,CAAS,EACpCM,EAAW9D,EAAAA,gBAAgB,CAC/B,cAAe,YACf,QACA,aAAc+D,GAAgB,GAC9B,gBACA,WAAYC,EACZ,iBACA,wBACA,yBACA,kBACA,UACF,CAAC,EAEKC,GAAuBd,IAAkB,YAAc,YAAc,QACrEe,GAAcjE,EAAAA,MAAM,iBAAiB,EACrCkE,EAAUC,GAAMF,GAGhB,CAACG,GAAMC,GAAW1E,EAAM,SAA6B,IAAI,EACzD2E,EAAe3E,EAAM,YAAa,IACtC0E,EAAS,GAAaE,GAAYC,CAAO,MAC5BH,EAAS,GAAcE,IAAaC,EAAU,KAAOD,CAAS,GAC1E,CAAC,CAAC,EACCE,EAAcxE,EAAAA,eAAemE,EAAI,EACjCM,GAAS/E,EAAM,aACZ,CAAE,cAAa,cAAa,GACnC,CAAC8E,EAAaH,CAAY,CAC5B,EACMK,GAAShF,EAAM,aACZ,CAAE,OAAM,cAAa,UAAS,MAAK,GAC1C,CAACgE,EAAMH,EAAaU,EAASN,CAAI,CACnC,EAGMgB,EAAc3B,IAAa,IAAA,IAAa,CAACM,EAC/CpB,EAAM,cAAgB,CAChByC,GAAatD,EAAA,SAASe,EAAyBC,CAAmB,CACxE,EAAG,CAACsC,CAAW,CAAC,EAGhB,IAAMC,EAASlF,EAAM,OAAoB,IAAI,EAC7CwC,EAAM,cAAgB,CACpB,GAAI,CAACjC,EAAAA,OAASC,EAAAA,UAAUoC,CAAuB,EAAG,OAClD,IAAMI,EAAMkC,EAAO,QACflC,GAAOF,EAAiBE,CAAG,GAAGrB,EAAA,SAASiB,EAAyBC,CAAmB,CACzF,CAAC,EAID,IAAMsC,EAAY,CAChB,aAAc3B,IAAcC,IAAmB,IAAA,GAAY,aAAe,IAAA,IAC1E,kBAAmBA,EACnB,mBAAoBC,CACtB,EACM0B,GAAiBnB,IAAS,UAAYkB,EAAY,IAAA,GAElDE,IACJ,EAAA5C,EAAA,IAAA,CAAChC,EAAAA,YAAD,CACE,cAAc,YACR,OACA,OACO,cACH,WACJ,OACK,YACA,aACK,iBAChB,SAAS,MACT,QAASC,EAAAA,kBACM,gBACf,cAAeC,EAAAA,GAAGC,EAAAA,iBAAiB,KAAMC,EAAAA,oBAAoB,IAAI,EACjE,kBAAmBF,EAAAA,GAAGC,EAAAA,iBAAiB,SAAUC,EAAAA,oBAAoB,QAAQ,EACnE,WACV,GAAI0D,EACJ,GAAIa,GACJ,GAAIzB,EACC,MAEL,UAAA,EAAAlB,EAAA,IAAA,CAAC,MAAD,CACE,IAAKyC,EACL,GAAIC,EACJ,UAAWxE,EAAAA,GAAGE,EAAAA,oBAAoB,IAAK,8BAA8B,EAEpE,UACE,CAAA,CACM,CAAA,EAKf,OAFAuB,EAAA,uBAAuB1B,EAAAA,kBAAmBsD,CAAI,GAG5C,EAAAvB,EAAA,IAAA,CAAC3B,EAAAA,WAAW,SAAZ,CAAqB,MAAOoD,EAC1B,UAAA,EAAAzB,EAAA,IAAA,CAAC1B,EAAAA,iBAAiB,SAAlB,CAA2B,MAAOiE,GAChC,UAAA,EAAAvC,EAAA,IAAA,CAACxC,EAAAA,uBAAuB,SAAxB,CAAiC,MAAO8E,GAAS,SAAAM,EAAuC,CAAA,CAC/D,CAAA,CACR,CAAA,CAEzB,EACA,EAAc,YAAc,YAU5B,IAAaC,GAAmB,CAAE,YAAW,WAAU,MAAK,GAAG3B,KAAiC,CAC9F,GAAM,CAAE,eAAgBR,EAAmB,kBAAkB,EAC7D,OACE,EAAAV,EAAA,IAAA,CAAC,MAAD,CACE,oBAAmBqC,EACnB,GAAInB,EACC,MACL,UAAWhD,EAAAA,GACTK,EAAAA,0BAA0B,KAC1B,oDACAC,EAAAA,uBAAuB,OACvBsE,CACF,EAEC,UACE,CAAA,CAET,EACA,EAAgB,YAAc,kBAM9B,IAAaC,GAAiB,CAC5B,YAAY,MACZ,YACA,YACA,UACA,WACA,MACA,GAAG7B,KACqB,CACxB,GAAM,CAAE,cAAa,gBAAiBR,EAAmB,gBAAgB,EACnEH,EAAMhD,EAAM,WAAWc,EAAAA,UAAU,EACjC2E,EAAQC,IAAc,QAItB,CAACC,EAAiBC,GAAsB5F,EAAM,SAAwB,IAAI,EAC1E6F,EAAwB7F,EAAM,aAAa,EAAkB,IAA0B,CAC3F4F,EAAoB,GAClBE,EAAeC,EAAWnB,IAAamB,EAAW,KAAOnB,CAC3D,CACF,EAAG,CAAC,CAAC,EACCoB,EAAShG,EAAM,aACZ,CAAE,uBAAsB,GAC/B,CAAC6F,CAAqB,CACxB,EACMI,EAAWjD,GAAK,OAAS,GACzBkD,EACJP,IAAoB,KAAgDM,GAAY,KAArD,qBAAqBN,IAG5C,CAAE,kBAAmBzE,EAAAA,kBAAkB,CAC3C,aAAcC,EAAAA,sBACd,eAAgB,GAChB,QAAS,eACT,YAAa,OACb,KAAM,GACN,YAAa,GACb,UAAW,GACX,aACF,CAAC,EAEKgF,EAAanG,EAAM,YACtB,GAAoC6E,EAAUF,EAAaE,CAAO,EAAI,IAAA,GACvE,CAACF,CAAY,CACf,EACMyB,EAAYhF,EAAAA,cAChBiF,EACAF,EACAV,EAAQa,EAAe,IAAM,IAC/B,EAEMC,EAAUvG,EAAM,OAAyB,IAAI,EAGnD,OAFAkC,EAAA,qBAAqBqE,EAAS,iBAAkB,OAAO,GAGrD,EAAA9D,EAAA,IAAA,CAAC,MAAD,CACE,kBAAiBiD,EACjB,oBAAmBZ,EACnB,GAAInB,EACJ,IAAKyC,EACL,wBAAuBX,EAAQ,GAAK,IAAA,GACpC,UAAWpE,EAAAA,qBAAqBmF,EAAWf,EAAQa,EAAe,UAAY,IAAA,EAAS,EACvF,QAASjF,EAAAA,qBAAqBoF,EAAShB,EAAQa,EAAe,QAAU,IAAA,GAAW,CACjF,sBAAuB,EACzB,CAAC,EACD,UAAW3F,EAAAA,GAAGW,EAAAA,wBAAwB,KAAM,sCAAuCiE,CAAS,EAE5F,UAAA,EAAA9C,EAAA,IAAA,CAAClB,EAAAA,iBAAiB,SAAlB,CAA2B,MAAOkE,EAAQO,EAAS,KACjD,UAAA,EAAAvD,EAAA,IAAA,CAAC,KAAD,CAAI,IAAK8D,EAAS,UAAW5F,EAAAA,GAAGW,EAAAA,wBAAwB,KAAM,mBAAmB,EAC9E,UACC,CAAA,CACqB,CAAA,CACxB,CAAA,CAET,EACA,EAAc,YAAc,gBAM5B,IAAaoF,GAAmB,CAAE,YAAW,WAAU,MAAK,GAAG/C,KAAiC,CAC9F,GAAM,CAAE,eAAgBR,EAAmB,kBAAkB,EAEvDoD,EAAUvG,EAAM,OAAyB,IAAI,EAEnD,OADAkC,EAAA,qBAAqBqE,EAAS,mBAAoB,OAAO,GAEvD,EAAA9D,EAAA,IAAA,CAAC,MAAD,CACE,oBAAmBqC,EACnB,GAAInB,EACC,MACL,UAAWhD,EAAAA,GACTa,EAAAA,0BAA0B,KAC1B,gBACAP,EAAAA,uBAAuB,OACvBsE,CACF,EAEA,UAAA,EAAA9C,EAAA,IAAA,CAAC,KAAD,CAAI,IAAK8D,EAAS,UAAW5F,EAAAA,GAAGa,EAAAA,0BAA0B,KAAM,mBAAmB,EAChF,UACC,CAAA,CACD,CAAA,CAET,EACA,EAAgB,YAAc,kBAkE9B,IAAamF,EAA4B,OAAO,OAAOtD,EAAe,CACpE,OAAQiC,EACR,KAAME,EACN,OAAQkB,CACV,CAAC"}
1
+ {"version":3,"file":"NavDrawer.cjs","names":["React","NavDrawerLayoutContext","useModalOpenState","useDrawerOpen","useNavRootState","useId","useScrollState","isDev","hasWarned","DrawerPanel","inertModalTrigger","cn","drawerClassNames","navDrawerClassNames","NavContext","NavDrawerContext","navDrawerHeaderClassNames","scrollSeparatorClasses","useRovingTabIndex","TOOLBAR_ITEM_SELECTOR","useMergedRefs","composeEventHandlers","navDrawerBodyClassNames","NavRovingContext","navDrawerFooterClassNames","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useId","require_useRovingTabIndex","require_useMergedRefs","require_Toolbar_navigation","require_Nav_context","require_Nav_root","require_Dialog_shared","require_Drawer_panel","require_Drawer_scroll","require_NavDrawer_context","react","react_jsx_runtime","UNREACHABLE_WARNING_KEY","UNREACHABLE_WARNING","LOOSE_ITEMS_WARNING_KEY","LOOSE_ITEMS_WARNING","hasLooseListItem","item","nav","parent","INERT_LAYOUT","useNavDrawerLayout","componentName","NavDrawerRoot","openProp","modalTypeProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","rest","openState","requestOpen","defaultOpen","onOpenChange","open","type","navState","defaultValue","onItemSelect","modalType","generatedId","panelId","id","body","setBody","registerBody","previous","element","scrollState","layout","drawer","unreachable","navRef","nameProps","panelNameProps","panel","NavDrawerHeader","className","NavDrawerBody","arrow","focusMode","currentCategory","setCurrentCategory","reportCurrentCategory","holdsCurrent","category","roving","selected","activeValue","attachBody","mergedRef","ref","containerProps","listRef","onKeyDown","onFocus","NavDrawerFooter","NavDrawer"],"sources":["../../../src/components/navigation/NavDrawer.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n drawerClassNames,\n navDrawerBodyClassNames,\n navDrawerClassNames,\n navDrawerFooterClassNames,\n navDrawerHeaderClassNames,\n} from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { hasWarned, isDev, reportMissingContext, warnOnce } from '../../lib/dev';\nimport type { Slot, SlotObject } from '../../lib/slot';\nimport type { BackdropAppearance, FocusMode, ModalType, MotionSlot } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { TOOLBAR_ITEM_SELECTOR } from '../button/Toolbar.navigation';\nimport {\n inertModalTrigger,\n useModalOpenState,\n useModalTriggerSession,\n} from '../overlays/Dialog.shared';\nimport type {\n DrawerOpenChangeDetails,\n DrawerPosition,\n DrawerSize,\n DrawerType,\n} from '../overlays/Drawer.context';\nimport { DrawerPanel, useDrawerOpen } from '../overlays/Drawer.panel';\nimport { scrollSeparatorClasses, useScrollState } from '../overlays/Drawer.scroll';\nimport {\n NavContext,\n NavRovingContext,\n useNavListChildCheck,\n type NavRovingContextValue,\n} from './Nav.context';\nimport { useNavRootState, type NavProps } from './Nav.root';\nimport {\n NavDrawerContext,\n NavDrawerLayoutContext,\n type NavDrawerContextValue,\n type NavDrawerLayoutContextValue,\n} from './NavDrawer.context';\n\n/*\n * NavDrawer: Nav's state (`useNavRootState`) and a navigation landmark in the drawer panel shell\n * (`DrawerPanel`), with its Header, Body and Footer parts. Imports the Nav root and context modules\n * (never `Nav.tsx`) and the shell's modules (never Drawer's root or compound); Nav never imports\n * it, and `Hamburger.tsx` reads only `NavDrawer.context.ts`.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Properties for the NavDrawer component. */\nexport interface NavDrawerProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'>,\n Pick<\n NavProps,\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'openCategories'\n | 'defaultOpenCategories'\n | 'onOpenCategoriesChange'\n | 'currentCategory'\n > {\n /**\n * How the drawer sits on the page (Fluent's `type`).\n * - `overlay`: a panel over the page, rendered in a portal while open (in the browser only: an\n * open overlay is closed in the server HTML and opens once hydrated). Modal by default: focus\n * moves in and stays there, the rest of the page is `inert` and does not scroll, and Escape\n * and a backdrop press close it. It is a dialog with the navigation's name.\n * - `inline`: a panel in the page layout, rendered where the NavDrawer is (also in the server\n * HTML). The page stays usable around it; Escape and presses outside do nothing; opening it\n * moves no focus, and closing it while focus is inside returns focus to `finalFocusRef`, else\n * to the element that opened it.\n *\n * Changing `type` remounts the panel; the selection and the open categories are kept. Rendered\n * as `data-type`.\n * @default 'overlay'\n */\n type?: DrawerType;\n /** Controlled open state. */\n open?: boolean;\n /**\n * Open state for uncontrolled usage. Keep the drawer controlled instead: a closed uncontrolled\n * NavDrawer cannot be opened again (a Hamburger inside it is not shown while it is closed).\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the new open state when it changes, with `details.reason`: `trigger` (a Hamburger\n * inside the drawer), `escape` and `outside-press` (the backdrop; overlay only). `details` is\n * typed optional until 1.0. A controlled drawer stays as it is until you update `open`.\n */\n onOpenChange?: (open: boolean, details?: DrawerOpenChangeDetails) => void;\n /**\n * Called with an item's value every time an item is activated, also when the current page is\n * activated again (a disabled item, a link opened in another tab or window, and a button item\n * whose `onClick` calls `preventDefault()` are not activations). Close an overlay drawer here:\n * `onValueChange` fires only when the value changes. Fluent's `onNavItemSelect`.\n */\n onItemSelect?: (value: string) => void;\n /**\n * The edge the panel is attached to: an overlay's screen edge; an inline panel's inner edge is\n * the opposite one. `start`/`end` follow the text direction; `left`/`right` are physical sides;\n * `bottom` runs along the bottom edge. Unlike Drawer's (`'end'`), the default is the start edge,\n * where navigation sits (Fluent's). Rendered as `data-position`.\n * @default 'start'\n */\n position?: DrawerPosition;\n /**\n * The panel's width at a side (its height at the bottom), on Drawer's scale: `small` 320px,\n * `medium` 592px, `large` 940px, `full` the viewport (inline: the container). A width class in\n * `className` replaces it (Fluent's navigation pane is 260px wide: the width class of 65\n * spacing steps). It also times the motion, an overlay's slide and an inline drawer's collapse\n * alike: 250 ms small, 300 ms medium, 400 ms large, 500 ms full (an inline drawer at `full` has\n * no motion; see `motion`), so a drawer without `size` takes 250 ms whatever width a class gives\n * it. Rendered as `data-size`. Drawer's default too.\n * @default 'small'\n */\n size?: DrawerSize;\n /**\n * Inline drawers: draws a line on the panel's inner edge (`data-separator`), as Nav does\n * (Drawer's `separator` defaults to `false`). An overlay always draws that edge; forced colours\n * always draw it.\n * @default true\n */\n separator?: boolean;\n /**\n * Overlay drawers: `modal` (backdrop, focus trapped, page inert and not scrolling) or\n * `non-modal` (no backdrop, no trap, nothing inert; Escape closes it while focus is inside, and\n * its Tab place follows the element that opened it). A non-modal overlay covers the page under\n * it while the page keeps its Tab order: keep the page's controls clear of it (reserve its width,\n * or its height at the bottom, in your layout while it is open) or use `type=\"inline\"`; with\n * `size=\"full\"` it hides the whole page and warns. Ignored by inline drawers. Rendered as\n * `data-modal-type` on an overlay's panel. Fluent's `modalType` (without `alert`: a navigation\n * pane is never an alert, so an `'alert'` is treated as `'modal'`). Drawer's default too.\n * @default 'modal'\n */\n modalType?: Extract<ModalType, 'modal' | 'non-modal'>;\n /**\n * Removes the panel when the drawer closes, once its exit motion has ended. `false` keeps it\n * mounted while closed, out of view and `inert`, so the state of what is inside survives, and a\n * Hamburger outside can point `aria-controls` at it at all times: always for an inline drawer,\n * and once the page has hydrated for an overlay (whose panel is not in the server HTML).\n * Fluent's `unmountOnClose`. Drawer's default too.\n * @default true\n */\n unmountOnClose?: boolean;\n /**\n * Where focus goes when the drawer closes with focus inside it (a modal overlay: whenever it\n * closes). Pass your page's Hamburger, so a Hamburger inside the drawer that closes it hands\n * focus to the one that opens it again.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * The backdrop of a modal overlay (Drawer's `backdrop` slot: `null` renders none, a slot\n * object's `appearance` picks the fill). Ignored, with a development warning, by a non-modal or\n * inline drawer.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /**\n * The drawer's motion, as Drawer's. By default an overlay panel slides in from beyond its edge\n * and fades in with a decelerating curve, and slides back out and fades out with an accelerating\n * curve; the `start` and `end` edges follow the text direction, `left` and `right` do not\n * mirror, and a `bottom` panel rises from below. An inline drawer by default opens the space it\n * takes in your layout from nothing (its width at a side, its height at the bottom) while its\n * panel fades in, held at its size against its inner edge, so it reads as sliding out from that\n * edge, with a decelerating curve; closing runs the same backwards with an accelerating curve.\n * Both take a duration that follows `size` both ways: 250 ms small (also without `size`), 300 ms\n * medium, 400 ms large, 500 ms full. An inline drawer at `full` has no motion, as its size is\n * its container's (a value here does not apply to it either), and an inline drawer whose width\n * (height at the bottom) in `className` is a percentage resizes oddly during the motion,\n * correctly once open: give it a length, or pass `null`. Under reduced motion the drawer appears\n * and disappears at once. `null` turns the motion off (the drawer 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. They go on the overlay panel, or on\n * the element around an inline drawer's panel (`wave-nav-drawer__collapse`), whose phases the\n * drawer waits for. A `className` that holds `data-[presence=…]` classes while `motion` is unset\n * keeps 0.14's behaviour: no default motion, your classes animate the panel, and the drawer\n * waits for the panel's motion (inline too, not the element around it). Fluent's\n * `OverlayDrawer` and `InlineDrawer` `surfaceMotion`.\n * @default the slide (overlay) or the collapse (inline) above\n */\n motion?: MotionSlot | null;\n /**\n * The backdrop's motion (a modal overlay), as Drawer's. By default it fades in and out with a\n * linear curve over the panel's duration (250 to 500 ms, by `size`), so it ends with the panel;\n * under reduced motion it appears and disappears at once. `null` turns the motion off; a class\n * string or `{ className }` replaces the default classes with yours (see `MotionSlot`), also\n * under a `WaveProvider` with `motion=\"none\"`, which otherwise turns the default off. The\n * panel's motion decides when the drawer unmounts or hides: a replacement longer than the\n * panel's exit is cut off there. Ignored, with a development warning, by a non-modal or inline\n * drawer. Fluent's `OverlayDrawer` `backdropMotion`.\n * @default the fade above\n */\n backdropMotion?: MotionSlot | null;\n /**\n * Name of the navigation landmark (and of an overlay's dialog). Localize it; rename it when the\n * page has another navigation landmark (two with one name are ambiguous). An `aria-labelledby`\n * replaces the default.\n * @default 'Navigation'\n */\n 'aria-label'?: string;\n /** `NavDrawer.Header`, `NavDrawer.Body` and `NavDrawer.Footer`, rendered in the order written. */\n children?: React.ReactNode;\n /** Ref to the panel: the `role=\"dialog\"` element of an overlay drawer, the panel element of an inline one. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the NavDrawerHeader sub-component. */\nexport interface NavDrawerHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** A Hamburger, the app's name, …: any content (Nav items go in the body or the footer). */\n children?: React.ReactNode;\n /** Ref to the header element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the NavDrawerBody sub-component. */\nexport interface NavDrawerBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * How the keyboard reaches the items. `'tab'`: every item is a Tab stop and the arrow keys do\n * nothing (Nav's model). `'arrow'`: the body is one Tab stop, the last focused element (at first\n * the current page, or the closed category that holds it, else the first item); Down and Right\n * move to the next element and Up and Left to the previous one (Left and Right swap in a\n * right-to-left layout), wrapping, and Home and End go to the ends. Every focusable element in\n * the body joins the order, item actions included. Screen readers do not announce arrow keys in\n * a navigation landmark: prefer `'tab'` unless your users expect an app pane. Rendered as\n * `data-focus-mode`. Fluent's NavDrawer uses arrow keys by default (its `tabbable` adds Tab\n * stops).\n * @default 'tab'\n */\n focusMode?: FocusMode;\n /** Nav parts: `Nav.Item`, `Nav.Category`, `Nav.SectionHeader`, … (each renders its own list item). */\n children?: React.ReactNode;\n /** Ref to the scrolling body element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the NavDrawerFooter sub-component. */\nexport interface NavDrawerFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Nav parts pinned below the body (Settings, Help); wrap other content in an `<li>`. */\n children?: React.ReactNode;\n /** Ref to the footer element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// Development checks\n// ---------------------------------------------------------------------------\n\nconst UNREACHABLE_WARNING_KEY = 'NavDrawer:unreachable';\nconst UNREACHABLE_WARNING =\n 'NavDrawer is closed and nothing can open it: it is uncontrolled (no `open` prop), and a Hamburger inside it cannot be reached while it is closed. Control it with `open` and `onOpenChange`, and open it from a Hamburger (or any button) outside it.';\n\nconst LOOSE_ITEMS_WARNING_KEY = 'NavDrawer:loose-items';\nconst LOOSE_ITEMS_WARNING =\n 'NavDrawer: a list item sits outside NavDrawer.Body and NavDrawer.Footer, the parts that render a list. Move Nav.Item, Nav.Category and the other Nav parts into NavDrawer.Body or NavDrawer.Footer.';\n\n/** Whether `nav` holds an `<li>` whose parent is not a `<ul>` or `<ol>`. */\nfunction hasLooseListItem(nav: HTMLElement): boolean {\n for (const item of Array.from(nav.querySelectorAll('li'))) {\n const parent = item.parentElement?.localName;\n if (parent !== 'ul' && parent !== 'ol') return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Root\n// ---------------------------------------------------------------------------\n\n/** The scroll state and body registry the parts read outside a NavDrawer in production. */\nconst INERT_LAYOUT: NavDrawerLayoutContextValue = {\n scrollState: 'none',\n registerBody: () => () => {},\n};\n\n/** C-CONTEXT: the enclosing NavDrawer's layout for the part `componentName`. */\nfunction useNavDrawerLayout(componentName: string): NavDrawerLayoutContextValue {\n const context = React.useContext(NavDrawerLayoutContext);\n if (context) return context;\n reportMissingContext(componentName, 'NavDrawer');\n return INERT_LAYOUT;\n}\n\n// The root of `NavDrawer` (documented on the export below).\nconst NavDrawerRoot = ({\n type = 'overlay',\n open: openProp,\n defaultOpen,\n onOpenChange,\n onItemSelect,\n position = 'start',\n size = 'small',\n separator = true,\n modalType: modalTypeProp = 'modal',\n unmountOnClose = true,\n finalFocusRef,\n backdrop,\n motion,\n backdropMotion,\n value,\n defaultValue,\n onValueChange,\n openCategories,\n defaultOpenCategories,\n onOpenCategoriesChange,\n currentCategory,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n id,\n children,\n ref,\n ...rest\n}: NavDrawerProps) => {\n const [openState, requestOpen] = useModalOpenState(openProp, defaultOpen, onOpenChange);\n // An overlay reports itself closed until the page has hydrated (its portal renders only in the\n // browser), so a Hamburger's aria-controls never names a panel that is not there.\n const open = useDrawerOpen(type, openState);\n const navState = useNavRootState({\n componentName: 'NavDrawer',\n value,\n defaultValue: defaultValue ?? '',\n onValueChange,\n onActivate: onItemSelect,\n openCategories,\n defaultOpenCategories,\n onOpenCategoriesChange,\n currentCategory,\n children,\n });\n // A navigation pane is never an alert: an 'alert' passed at run time is a modal one.\n const modalType: ModalType = modalTypeProp === 'non-modal' ? 'non-modal' : 'modal';\n const generatedId = useId('wave-nav-drawer');\n const panelId = id ?? generatedId;\n\n // The first mounted body, measured for the scroll-state separators of the parts.\n const [body, setBody] = React.useState<HTMLElement | null>(null);\n const registerBody = React.useCallback((element: HTMLElement) => {\n setBody((previous) => previous ?? element);\n return () => setBody((previous) => (previous === element ? null : previous));\n }, []);\n const scrollState = useScrollState(body);\n const layout = React.useMemo<NavDrawerLayoutContextValue>(\n () => ({ scrollState, registerBody }),\n [scrollState, registerBody],\n );\n const drawer = React.useMemo<NavDrawerContextValue>(\n () => ({ open, requestOpen, panelId, type }),\n [open, requestOpen, panelId, type],\n );\n\n // An uncontrolled drawer that is closed has no way back: its Hamburgers are inside it.\n const unreachable = openProp === undefined && !openState;\n React.useEffect(() => {\n if (unreachable) warnOnce(UNREACHABLE_WARNING_KEY, UNREACHABLE_WARNING);\n }, [unreachable]);\n\n // Development only: after every commit, a list item outside the Body's and Footer's lists.\n const navRef = React.useRef<HTMLElement>(null);\n React.useEffect(() => {\n if (!isDev || hasWarned(LOOSE_ITEMS_WARNING_KEY)) return;\n const nav = navRef.current;\n if (nav && hasLooseListItem(nav)) warnOnce(LOOSE_ITEMS_WARNING_KEY, LOOSE_ITEMS_WARNING);\n });\n\n // The name goes to the <nav> in both types and, in an overlay, also to its dialog panel. An\n // aria-labelledby without aria-label drops the default.\n const nameProps = {\n 'aria-label': ariaLabel ?? (ariaLabelledBy === undefined ? 'Navigation' : undefined),\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n };\n const panelNameProps = type === 'overlay' ? nameProps : undefined;\n\n const panel = (\n <DrawerPanel\n componentName=\"NavDrawer\"\n type={type}\n open={open}\n requestOpen={requestOpen}\n position={position}\n size={size}\n separator={separator}\n modalType={modalType}\n unmountOnClose={unmountOnClose}\n inlineAs=\"div\"\n trigger={inertModalTrigger}\n finalFocusRef={finalFocusRef}\n rootClassName={cn(drawerClassNames.root, navDrawerClassNames.root)}\n backdropClassName={cn(drawerClassNames.backdrop, navDrawerClassNames.backdrop)}\n collapseClassName={cn(drawerClassNames.collapse, navDrawerClassNames.collapse)}\n backdrop={backdrop}\n motion={motion}\n backdropMotion={backdropMotion}\n id={panelId}\n {...panelNameProps}\n {...rest}\n ref={ref as React.Ref<HTMLElement> | undefined}\n >\n <nav\n ref={navRef}\n {...nameProps}\n className={cn(navDrawerClassNames.nav, 'flex min-h-0 flex-1 flex-col')}\n >\n {children}\n </nav>\n </DrawerPanel>\n );\n // After the shell's effects (focus restore), as the shell's contract asks.\n useModalTriggerSession(inertModalTrigger, open);\n\n return (\n <NavContext.Provider value={navState}>\n <NavDrawerContext.Provider value={drawer}>\n <NavDrawerLayoutContext.Provider value={layout}>{panel}</NavDrawerLayoutContext.Provider>\n </NavDrawerContext.Provider>\n </NavContext.Provider>\n );\n};\nNavDrawerRoot.displayName = 'NavDrawer';\n\n// ---------------------------------------------------------------------------\n// Parts\n// ---------------------------------------------------------------------------\n\n/**\n * The header row of a NavDrawer: a Hamburger, the app's name, … (no list: Nav items go in the\n * body or the footer). Its line underneath shows while the body is scrolled away from its top.\n */\nexport const NavDrawerHeader = ({ className, children, ref, ...rest }: NavDrawerHeaderProps) => {\n const { scrollState } = useNavDrawerLayout('NavDrawer.Header');\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n navDrawerHeaderClassNames.root,\n 'flex shrink-0 items-center gap-2 ps-2.5 pe-2 py-2',\n scrollSeparatorClasses.header,\n className,\n )}\n >\n {children}\n </div>\n );\n};\nNavDrawerHeader.displayName = 'NavDrawerHeader';\n\n/**\n * The scrolling list of a NavDrawer: the Nav parts (`Nav.Item`, `Nav.Category`, …) as the items of\n * its list. With `focusMode=\"arrow\"` it is one Tab stop and the arrow keys move through it.\n */\nexport const NavDrawerBody = ({\n focusMode = 'tab',\n className,\n onKeyDown,\n onFocus,\n children,\n ref,\n ...rest\n}: NavDrawerBodyProps) => {\n const { scrollState, registerBody } = useNavDrawerLayout('NavDrawer.Body');\n const nav = React.useContext(NavContext);\n const arrow = focusMode === 'arrow';\n\n // The closed category that holds the current page, reported by the categories of an arrow body\n // from their layout effects: it holds the first Tab stop while the current page is hidden.\n const [currentCategory, setCurrentCategory] = React.useState<string | null>(null);\n const reportCurrentCategory = React.useCallback((category: string, holdsCurrent: boolean) => {\n setCurrentCategory((previous) =>\n holdsCurrent ? category : previous === category ? null : previous,\n );\n }, []);\n const roving = React.useMemo<NavRovingContextValue>(\n () => ({ reportCurrentCategory }),\n [reportCurrentCategory],\n );\n const selected = nav?.value ?? '';\n const activeValue =\n currentCategory !== null ? `wave-nav-category:${currentCategory}` : selected || null;\n // Always called (C-HOOKS); the container attaches only in the arrow mode, and detaching it hands\n // every element its own tabindex back.\n const { containerProps } = useRovingTabIndex({\n itemSelector: TOOLBAR_ITEM_SELECTOR,\n manageTabIndex: true,\n tabStop: 'last-focused',\n orientation: 'both',\n loop: true,\n homeEndKeys: true,\n typeahead: false,\n activeValue,\n });\n\n const attachBody = React.useCallback(\n (element: HTMLDivElement | null) => (element ? registerBody(element) : undefined),\n [registerBody],\n );\n const mergedRef = useMergedRefs<HTMLDivElement>(\n ref,\n attachBody,\n arrow ? containerProps.ref : null,\n );\n // Development only: every child of the list is an <li> (`NavDrawer.Body:list-child`).\n const listRef = React.useRef<HTMLUListElement>(null);\n useNavListChildCheck(listRef, 'NavDrawer.Body', 'items');\n\n return (\n <div\n data-focus-mode={focusMode}\n data-scroll-state={scrollState}\n {...rest}\n ref={mergedRef}\n data-roving-container={arrow ? '' : undefined}\n onKeyDown={composeEventHandlers(onKeyDown, arrow ? containerProps.onKeyDown : undefined)}\n onFocus={composeEventHandlers(onFocus, arrow ? containerProps.onFocus : undefined, {\n checkDefaultPrevented: false,\n })}\n className={cn(navDrawerBodyClassNames.root, 'min-h-0 flex-1 overflow-y-auto py-2', className)}\n >\n <NavRovingContext.Provider value={arrow ? roving : null}>\n <ul ref={listRef} className={cn(navDrawerBodyClassNames.list, 'm-0 list-none p-0')}>\n {children}\n </ul>\n </NavRovingContext.Provider>\n </div>\n );\n};\nNavDrawerBody.displayName = 'NavDrawerBody';\n\n/**\n * The list pinned below a NavDrawer's body (Settings, Help): Nav parts as the items of its list,\n * each a Tab stop. Its line above shows while more of the body is below.\n */\nexport const NavDrawerFooter = ({ className, children, ref, ...rest }: NavDrawerFooterProps) => {\n const { scrollState } = useNavDrawerLayout('NavDrawer.Footer');\n // Development only: every child of the list is an <li> (`NavDrawer.Footer:list-child`).\n const listRef = React.useRef<HTMLUListElement>(null);\n useNavListChildCheck(listRef, 'NavDrawer.Footer', 'items');\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n navDrawerFooterClassNames.root,\n 'shrink-0 py-2',\n scrollSeparatorClasses.footer,\n className,\n )}\n >\n <ul ref={listRef} className={cn(navDrawerFooterClassNames.list, 'm-0 list-none p-0')}>\n {children}\n </ul>\n </div>\n );\n};\nNavDrawerFooter.displayName = 'NavDrawerFooter';\n\n// ---------------------------------------------------------------------------\n// Compound\n// ---------------------------------------------------------------------------\n\n/**\n * A navigation pane in a drawer: Nav's items, categories and selection in a `<nav>` landmark that\n * sits over the page (`type=\"overlay\"`) or in the page layout (`type=\"inline\"`). Fluent's\n * `NavDrawer`.\n *\n * - **Composition:** `NavDrawer.Header` (a row: a `Hamburger`, the app's name), `NavDrawer.Body`\n * (the scrolling list) and `NavDrawer.Footer` (a list pinned below it), rendered in the order\n * written. Nav parts (`Nav.Item`, `Nav.Category`, `Nav.SectionHeader`, `Nav.Divider`,\n * `Nav.AppItem`, …) go in the Body and the Footer, which render the lists; wrap anything else\n * there in an `<li>`.\n * - **Types:** `overlay` (default) is a panel over the page, in a portal, opened in the browser\n * only; `inline` is a panel in the page layout, also in the server HTML. Changing `type`\n * remounts the panel; the selection and the open categories are kept.\n * - **Opening and closing:** keep it controlled (`open`, `onOpenChange`): an uncontrolled drawer\n * that is closed cannot open again. A `Hamburger` inside it toggles it (reason `trigger`);\n * Escape and a backdrop press close an overlay (`escape`, `outside-press`). Closing an overlay\n * when an item is chosen is yours, in `onItemSelect`, which also fires when the current page is\n * activated again. A non-modal overlay (`modalType=\"non-modal\"`) covers the page, which keeps\n * its Tab order: keep the page's controls clear of it, or use `type=\"inline\"`.\n * - **Motion:** an overlay slides in from its edge and fades in, and slides back and fades out,\n * over 250 ms (`small`, the default), 300 ms (`medium`), 400 ms (`large`) or 500 ms (`full`),\n * with its backdrop fading along; one open by default animates in when it mounts in the browser.\n * An inline drawer opens and closes the space it takes in the layout over the same durations,\n * in an element of its own around the panel (`wave-nav-drawer__collapse`, which has no box\n * while open); one open by default does not animate in, and one at `full` has no motion. Under\n * reduced motion every drawer appears and disappears at once. `motion` and `backdropMotion`\n * turn each off (`null`) or replace it, and `WaveProvider motion=\"none\"` turns both defaults\n * off. While it exits the panel stays on screen, `inert`, and focus, the trap and the scroll\n * lock are already released.\n * - **Focus:** pass your page's Hamburger as `finalFocusRef`, so focus returns to it when a\n * Hamburger inside the drawer closes it. An overlay moves focus in when it opens; an inline\n * drawer does not.\n * - **Keyboard:** every item is a Tab stop; `NavDrawer.Body focusMode=\"arrow\"` makes the body one\n * Tab stop with arrow keys, Home and End.\n * - **Landmark:** one `<nav>`, named \"Navigation\" by default (`aria-label`, `aria-labelledby`);\n * an overlay is also a dialog with that name. Rename it when the page has another navigation\n * landmark.\n * - **Selection:** Nav's `value`/`onValueChange` (only on a change), `openCategories` and\n * `currentCategory`, and `onItemSelect` on every activation (Fluent's `selectedValue` and\n * `onNavItemSelect`).\n * - **Server Components:** the parts are also exported as `NavDrawerHeader`, `NavDrawerBody` and\n * `NavDrawerFooter`.\n *\n * @example\n * const [open, setOpen] = useState(false);\n * const hamburgerRef = useRef<HTMLButtonElement>(null);\n * <Hamburger\n * ref={hamburgerRef}\n * aria-expanded={open}\n * aria-controls={open ? 'main-nav' : undefined}\n * aria-haspopup=\"dialog\"\n * onClick={() => setOpen(!open)}\n * />\n * <NavDrawer\n * id=\"main-nav\"\n * open={open}\n * onOpenChange={setOpen}\n * onItemSelect={() => setOpen(false)}\n * finalFocusRef={hamburgerRef}\n * defaultValue=\"home\"\n * >\n * <NavDrawer.Header>\n * <Hamburger />\n * Contoso HR\n * </NavDrawer.Header>\n * <NavDrawer.Body>\n * <Nav.Item value=\"home\" href=\"/\">Home</Nav.Item>\n * </NavDrawer.Body>\n * </NavDrawer>\n */\nexport const NavDrawer = /* @__PURE__ */ Object.assign(NavDrawerRoot, {\n Header: NavDrawerHeader,\n Body: NavDrawerBody,\n Footer: NavDrawerFooter,\n});\n"],"mappings":"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"}
@@ -17,44 +17,44 @@ import * as O from "react";
17
17
  import { jsx as k } from "react/jsx-runtime";
18
18
  //#region src/components/navigation/NavDrawer.tsx
19
19
  var A = "NavDrawer:unreachable", j = "NavDrawer is closed and nothing can open it: it is uncontrolled (no `open` prop), and a Hamburger inside it cannot be reached while it is closed. Control it with `open` and `onOpenChange`, and open it from a Hamburger (or any button) outside it.", M = "NavDrawer:loose-items", ee = "NavDrawer: a list item sits outside NavDrawer.Body and NavDrawer.Footer, the parts that render a list. Move Nav.Item, Nav.Category and the other Nav parts into NavDrawer.Body or NavDrawer.Footer.";
20
- function N(e) {
20
+ function te(e) {
21
21
  for (let t of Array.from(e.querySelectorAll("li"))) {
22
22
  let e = t.parentElement?.localName;
23
23
  if (e !== "ul" && e !== "ol") return !0;
24
24
  }
25
25
  return !1;
26
26
  }
27
- var P = {
27
+ var N = {
28
28
  scrollState: "none",
29
29
  registerBody: () => () => {}
30
30
  };
31
- function F(e) {
32
- return O.useContext(D) || (r(e, "NavDrawer"), P);
31
+ function P(e) {
32
+ return O.useContext(D) || (r(e, "NavDrawer"), N);
33
33
  }
34
- var I = ({ type: r = "overlay", open: a, defaultOpen: s, onOpenChange: l, onItemSelect: u, position: f = "start", size: p = "small", separator: m = !0, modalType: g = "modal", unmountOnClose: _ = !0, finalFocusRef: w, backdrop: P, value: F, defaultValue: I, onValueChange: L, openCategories: R, defaultOpenCategories: z, onOpenCategoriesChange: B, currentCategory: te, "aria-label": ne, "aria-labelledby": V, "aria-describedby": re, id: ie, children: H, ref: ae, ...oe }) => {
35
- let [U, W] = b(a, s, l), G = C(r, U), K = v({
34
+ var F = ({ type: r = "overlay", open: a, defaultOpen: s, onOpenChange: l, onItemSelect: u, position: f = "start", size: p = "small", separator: m = !0, modalType: g = "modal", unmountOnClose: _ = !0, finalFocusRef: w, backdrop: N, motion: P, backdropMotion: F, value: I, defaultValue: L, onValueChange: R, openCategories: z, defaultOpenCategories: ne, onOpenCategoriesChange: B, currentCategory: re, "aria-label": ie, "aria-labelledby": V, "aria-describedby": ae, id: oe, children: H, ref: se, ...ce }) => {
35
+ let [U, W] = b(a, s, l), G = C(r, U), le = v({
36
36
  componentName: "NavDrawer",
37
- value: F,
38
- defaultValue: I ?? "",
39
- onValueChange: L,
37
+ value: I,
38
+ defaultValue: L ?? "",
39
+ onValueChange: R,
40
40
  onActivate: u,
41
- openCategories: R,
42
- defaultOpenCategories: z,
41
+ openCategories: z,
42
+ defaultOpenCategories: ne,
43
43
  onOpenCategoriesChange: B,
44
- currentCategory: te,
44
+ currentCategory: re,
45
45
  children: H
46
- }), se = g === "non-modal" ? "non-modal" : "modal", ce = d("wave-nav-drawer"), q = ie ?? ce, [le, J] = O.useState(null), Y = O.useCallback((e) => (J((t) => t ?? e), () => J((t) => t === e ? null : t)), []), X = T(le), ue = O.useMemo(() => ({
46
+ }), ue = g === "non-modal" ? "non-modal" : "modal", de = d("wave-nav-drawer"), K = oe ?? de, [q, J] = O.useState(null), Y = O.useCallback((e) => (J((t) => t ?? e), () => J((t) => t === e ? null : t)), []), X = T(q), fe = O.useMemo(() => ({
47
47
  scrollState: X,
48
48
  registerBody: Y
49
- }), [X, Y]), de = O.useMemo(() => ({
49
+ }), [X, Y]), pe = O.useMemo(() => ({
50
50
  open: G,
51
51
  requestOpen: W,
52
- panelId: q,
52
+ panelId: K,
53
53
  type: r
54
54
  }), [
55
55
  G,
56
56
  W,
57
- q,
57
+ K,
58
58
  r
59
59
  ]), Z = a === void 0 && !U;
60
60
  O.useEffect(() => {
@@ -64,13 +64,13 @@ var I = ({ type: r = "overlay", open: a, defaultOpen: s, onOpenChange: l, onItem
64
64
  O.useEffect(() => {
65
65
  if (!n || t(M)) return;
66
66
  let e = Q.current;
67
- e && N(e) && i(M, ee);
67
+ e && te(e) && i(M, ee);
68
68
  });
69
69
  let $ = {
70
- "aria-label": ne ?? (V === void 0 ? "Navigation" : void 0),
70
+ "aria-label": ie ?? (V === void 0 ? "Navigation" : void 0),
71
71
  "aria-labelledby": V,
72
- "aria-describedby": re
73
- }, fe = r === "overlay" ? $ : void 0, pe = /* @__PURE__ */ k(S, {
72
+ "aria-describedby": ae
73
+ }, me = r === "overlay" ? $ : void 0, he = /* @__PURE__ */ k(S, {
74
74
  componentName: "NavDrawer",
75
75
  type: r,
76
76
  open: G,
@@ -78,18 +78,21 @@ var I = ({ type: r = "overlay", open: a, defaultOpen: s, onOpenChange: l, onItem
78
78
  position: f,
79
79
  size: p,
80
80
  separator: m,
81
- modalType: se,
81
+ modalType: ue,
82
82
  unmountOnClose: _,
83
83
  inlineAs: "div",
84
84
  trigger: y,
85
85
  finalFocusRef: w,
86
86
  rootClassName: e(o.root, c.root),
87
87
  backdropClassName: e(o.backdrop, c.backdrop),
88
- backdrop: P,
89
- id: q,
90
- ...fe,
91
- ...oe,
92
- ref: ae,
88
+ collapseClassName: e(o.collapse, c.collapse),
89
+ backdrop: N,
90
+ motion: P,
91
+ backdropMotion: F,
92
+ id: K,
93
+ ...me,
94
+ ...ce,
95
+ ref: se,
93
96
  children: /* @__PURE__ */ k("nav", {
94
97
  ref: Q,
95
98
  ...$,
@@ -98,19 +101,19 @@ var I = ({ type: r = "overlay", open: a, defaultOpen: s, onOpenChange: l, onItem
98
101
  })
99
102
  });
100
103
  return x(y, G), /* @__PURE__ */ k(h.Provider, {
101
- value: K,
104
+ value: le,
102
105
  children: /* @__PURE__ */ k(E.Provider, {
103
- value: de,
106
+ value: pe,
104
107
  children: /* @__PURE__ */ k(D.Provider, {
105
- value: ue,
106
- children: pe
108
+ value: fe,
109
+ children: he
107
110
  })
108
111
  })
109
112
  });
110
113
  };
111
- I.displayName = "NavDrawer";
112
- var L = ({ className: t, children: n, ref: r, ...i }) => {
113
- let { scrollState: a } = F("NavDrawer.Header");
114
+ F.displayName = "NavDrawer";
115
+ var I = ({ className: t, children: n, ref: r, ...i }) => {
116
+ let { scrollState: a } = P("NavDrawer.Header");
114
117
  return /* @__PURE__ */ k("div", {
115
118
  "data-scroll-state": a,
116
119
  ...i,
@@ -119,9 +122,9 @@ var L = ({ className: t, children: n, ref: r, ...i }) => {
119
122
  children: n
120
123
  });
121
124
  };
122
- L.displayName = "NavDrawerHeader";
123
- var R = ({ focusMode: t = "tab", className: n, onKeyDown: r, onFocus: i, children: o, ref: c, ...l }) => {
124
- let { scrollState: u, registerBody: d } = F("NavDrawer.Body"), v = O.useContext(h), y = t === "arrow", [b, x] = O.useState(null), S = O.useCallback((e, t) => {
125
+ I.displayName = "NavDrawerHeader";
126
+ var L = ({ focusMode: t = "tab", className: n, onKeyDown: r, onFocus: i, children: o, ref: c, ...l }) => {
127
+ let { scrollState: u, registerBody: d } = P("NavDrawer.Body"), v = O.useContext(h), y = t === "arrow", [b, x] = O.useState(null), S = O.useCallback((e, t) => {
125
128
  x((n) => t ? e : n === e ? null : n);
126
129
  }, []), C = O.useMemo(() => ({ reportCurrentCategory: S }), [S]), w = v?.value ?? "", T = b === null ? w || null : `wave-nav-category:${b}`, { containerProps: E } = f({
127
130
  itemSelector: m,
@@ -152,9 +155,9 @@ var R = ({ focusMode: t = "tab", className: n, onKeyDown: r, onFocus: i, childre
152
155
  })
153
156
  });
154
157
  };
155
- R.displayName = "NavDrawerBody";
156
- var z = ({ className: t, children: n, ref: r, ...i }) => {
157
- let { scrollState: a } = F("NavDrawer.Footer"), o = O.useRef(null);
158
+ L.displayName = "NavDrawerBody";
159
+ var R = ({ className: t, children: n, ref: r, ...i }) => {
160
+ let { scrollState: a } = P("NavDrawer.Footer"), o = O.useRef(null);
158
161
  return _(o, "NavDrawer.Footer", "items"), /* @__PURE__ */ k("div", {
159
162
  "data-scroll-state": a,
160
163
  ...i,
@@ -167,13 +170,13 @@ var z = ({ className: t, children: n, ref: r, ...i }) => {
167
170
  })
168
171
  });
169
172
  };
170
- z.displayName = "NavDrawerFooter";
171
- var B = /* @__PURE__ */ Object.assign(I, {
172
- Header: L,
173
- Body: R,
174
- Footer: z
173
+ R.displayName = "NavDrawerFooter";
174
+ var z = /* @__PURE__ */ Object.assign(F, {
175
+ Header: I,
176
+ Body: L,
177
+ Footer: R
175
178
  });
176
179
  //#endregion
177
- export { B as NavDrawer, R as NavDrawerBody, z as NavDrawerFooter, L as NavDrawerHeader };
180
+ export { z as NavDrawer, L as NavDrawerBody, R as NavDrawerFooter, I as NavDrawerHeader };
178
181
 
179
182
  //# sourceMappingURL=NavDrawer.mjs.map