@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlatTree.item.mjs","names":["useId","useId$1","React","isCheckboxClick","event","FlatTreeItem","row","rest","ctx","useFlatTreeContext","item","disabled","labelId","itemRef","mergedRef","useMergedRefs","ref","checkState","isSelected","value","isCurrent","handleClick","isOwnEvent","onClick","keepFocusOnItem","handleCheckboxClick","chevron","isBranch","ChevronRightIcon","cn","flatTreeItemClassNames","expanded","checkbox","forcedColors","SubtractIcon","CheckIcon","radio","itemStyle","style","level","disabledStyles","className","setSize","position","index"],"sources":["../../../src/components/layout/FlatTree.item.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flatTreeItemClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { isOwnEvent } from '../../lib/events';\nimport type { VisibleFlatItem } from '../../lib/flatTree';\nimport { CheckIcon, ChevronRightIcon, SubtractIcon } from '../../lib/icons';\nimport { disabledStyles, forcedColors } from '../../lib/styles';\nimport type { CheckState } from '../../lib/treeCascade';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useFlatTreeContext } from './FlatTree.context';\n\n/** Properties for the FlatTreeItem sub-component. */\nexport interface FlatTreeItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** The row the item shows: a visible item of the tree's model (`model.visibleItems`). */\n item: VisibleFlatItem & { checked?: CheckState };\n /** The item's content: what the tree's `renderItem` returns, else the item's label. */\n children?: React.ReactNode;\n /** Ref to the `role=\"treeitem\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Whether a click landed on the item's checkbox, which has a click of its own. */\nfunction isCheckboxClick(event: React.MouseEvent<HTMLElement>): boolean {\n const target = event.target as Element | null;\n return target?.closest?.('[data-flat-tree-checkbox]') != null;\n}\n\n/**\n * One row of a FlatTree, rendered by the tree for each visible item of its model (it is not\n * written by hand): a `role=\"treeitem\"` element with the item's level, set size and position,\n * `aria-expanded` on a branch, and the expand chevron, the checkbox (multiple mode) or the radio\n * (single mode) of the nested `Tree`'s items, before the content. Levels are drawn by indenting\n * the row, since the items are siblings. In a windowed tree it is exactly the window's `itemSize`\n * tall.\n *\n * `ref`, `className` and the other props land on the treeitem element; its `onClick` receives the\n * clicks on the row, not those on the checkbox, and runs before the built-in activation (call\n * `event.preventDefault()` to skip it).\n */\nexport const FlatTreeItem = ({\n item: row,\n children,\n className,\n style,\n onClick,\n ref,\n ...rest\n}: FlatTreeItemProps) => {\n const ctx = useFlatTreeContext('FlatTree.Item');\n const { item, level, position, setSize, isBranch, expanded, index } = row;\n const { value } = item;\n const disabled = item.disabled === true;\n const labelId = useId('flat-tree-item-label');\n const itemRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, itemRef);\n\n const checkState: CheckState | undefined =\n ctx.selectionMode === 'multiple' ? (row.checked ?? 'unchecked') : undefined;\n const isSelected = ctx.selected !== undefined ? ctx.selected === value : undefined;\n const isCurrent = ctx.current !== undefined && ctx.current !== null && ctx.current === value;\n\n const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {\n // A click from a portal opened in the content, or on the checkbox, is not the row's.\n if (!isOwnEvent(event) || isCheckboxClick(event)) return;\n onClick?.(event);\n if (!event.defaultPrevented) ctx.activate(row);\n };\n\n // The checkbox never takes focus (APG: focus stays on tree items): a press on it focuses its\n // item instead, and its click toggles the check without activating the item.\n const keepFocusOnItem = (event: React.MouseEvent<HTMLSpanElement>) => {\n event.preventDefault();\n itemRef.current?.focus({ preventScroll: true });\n };\n const handleCheckboxClick = (event: React.MouseEvent<HTMLSpanElement>) => {\n ctx.toggleChecked(row, event.nativeEvent);\n };\n\n const chevron = isBranch ? (\n <ChevronRightIcon\n className={cn(\n flatTreeItemClassNames.expandIcon,\n 'shrink-0 transition-transform motion-reduce:transition-none',\n expanded ? 'rotate-90' : 'wave-rtl:-scale-x-100',\n )}\n />\n ) : (\n <span className=\"w-3 shrink-0\" aria-hidden=\"true\" />\n );\n\n const checkbox =\n checkState === undefined ? null : (\n <span\n role=\"checkbox\"\n aria-checked={checkState === 'mixed' ? 'mixed' : checkState === 'checked'}\n aria-labelledby={labelId}\n aria-disabled={disabled ? true : undefined}\n tabIndex={-1}\n data-flat-tree-checkbox=\"\"\n onMouseDown={keepFocusOnItem}\n onClick={handleCheckboxClick}\n className={cn(\n flatTreeItemClassNames.indicator,\n // Checkbox's box: 16px inside a 24px target (the pseudo-element), WCAG 2.5.8.\n 'relative inline-flex size-4 shrink-0 items-center justify-center rounded-xs border transition-colors motion-reduce:transition-none',\n 'before:absolute before:-inset-1',\n checkState === 'unchecked'\n ? cn('border-stroke-accessible bg-transparent', forcedColors.control)\n : 'border-primary bg-primary text-primary-foreground forced-colors:border-[Highlight] forced-colors:bg-[Highlight]',\n )}\n >\n {checkState === 'mixed' ? (\n <SubtractIcon size={12} className={forcedColors.selectedLeaf} />\n ) : checkState === 'checked' ? (\n <CheckIcon size={12} className={forcedColors.selectedLeaf} />\n ) : null}\n </span>\n );\n\n // Single mode: a decorative radio (the treeitem's aria-selected carries the state). A click on\n // it is a click on the row, so it activates the item.\n const radio =\n ctx.selectionMode === 'single' ? (\n <span\n aria-hidden=\"true\"\n className={cn(\n flatTreeItemClassNames.indicator,\n 'inline-flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors motion-reduce:transition-none',\n isSelected\n ? 'border-2 border-primary forced-colors:border-[Highlight]'\n : cn('border-stroke-accessible', forcedColors.control),\n )}\n >\n {isSelected && (\n <span className={cn('block size-2 rounded-full bg-primary', forcedColors.selectedLeaf)} />\n )}\n </span>\n ) : null;\n\n // The level is drawn as indentation (one step per level, as a nested group's), and a windowed\n // item is exactly the window's item height: the window's arithmetic counts on it.\n const itemStyle: React.CSSProperties = { ...style };\n if (level > 1) itemStyle.paddingInlineStart = `${level - 1}rem`;\n if (ctx.itemSize !== undefined) itemStyle.height = ctx.itemSize;\n\n return (\n <div\n role=\"treeitem\"\n aria-selected={isSelected}\n aria-current={isCurrent ? true : undefined}\n aria-disabled={disabled ? true : undefined}\n data-selected={isSelected ? '' : undefined}\n data-current={isCurrent ? '' : undefined}\n data-checked={checkState === 'checked' ? '' : undefined}\n data-mixed={checkState === 'mixed' ? '' : undefined}\n data-disabled={disabled ? '' : undefined}\n className={cn(\n flatTreeItemClassNames.root,\n // The focus ring is drawn on the row, inside the item's box.\n 'box-border block outline-none',\n '[&:focus-visible>[data-flat-tree-row]]:outline-2 [&:focus-visible>[data-flat-tree-row]]:-outline-offset-2 [&:focus-visible>[data-flat-tree-row]]:outline-ring',\n disabledStyles,\n className,\n )}\n {...rest}\n // Named by its content only: the treeitem also holds the chevron and the checkbox. A consumer\n // aria-labelledby or aria-label replaces it.\n aria-labelledby={\n rest['aria-labelledby'] ?? (rest['aria-label'] === undefined ? labelId : undefined)\n }\n // From the model, after the rest props: the positions and states are the data's.\n aria-level={level}\n aria-setsize={setSize}\n aria-posinset={position}\n aria-expanded={isBranch ? expanded : undefined}\n aria-checked={\n checkState === undefined\n ? undefined\n : checkState === 'mixed'\n ? 'mixed'\n : checkState === 'checked'\n }\n data-index={index}\n tabIndex={ctx.tabStop === value ? 0 : -1}\n style={itemStyle}\n onClick={handleClick}\n ref={mergedRef}\n >\n <div\n data-flat-tree-row=\"\"\n className={cn(\n flatTreeItemClassNames.row,\n 'box-border flex items-center gap-1.5 rounded px-2 py-1',\n ctx.itemSize !== undefined && 'h-full',\n disabled ? 'cursor-not-allowed' : 'cursor-pointer hover:bg-subtle-hover',\n isSelected && cn('bg-subtle-selected font-semibold', forcedColors.selectedContainer),\n )}\n >\n {chevron}\n {checkbox ?? radio}\n <span id={labelId} className={cn(flatTreeItemClassNames.label, 'min-w-0 truncate')}>\n {children}\n </span>\n </div>\n </div>\n );\n};\nFlatTreeItem.displayName = 'FlatTreeItem';\n"],"mappings":"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"}
@@ -0,0 +1,276 @@
1
+ "use client";
2
+ import { cn as e } from "../../lib/cn.mjs";
3
+ import { warnOnce as t } from "../../lib/dev.mjs";
4
+ import { composeEventHandlers as n } from "../../lib/composeEventHandlers.mjs";
5
+ import { flatTreeClassNames as r } from "../../lib/classNames.mjs";
6
+ import { useEventCallback as i } from "../../hooks/useEventCallback.mjs";
7
+ import { getArrowIntent as a, getDirection as o } from "../../lib/direction.mjs";
8
+ import { useTypeahead as s } from "../../hooks/useTypeahead.mjs";
9
+ import { useMergedRefs as c } from "../../hooks/useMergedRefs.mjs";
10
+ import { isEditableTarget as l, isOwnEvent as u } from "../../lib/events.mjs";
11
+ import { FlatTreeContext as d } from "./FlatTree.context.mjs";
12
+ import { FlatTreeItem as f } from "./FlatTree.item.mjs";
13
+ import * as p from "react";
14
+ import { jsx as m } from "react/jsx-runtime";
15
+ //#region src/components/layout/FlatTree.tsx
16
+ var h = {
17
+ focused: null,
18
+ pending: null
19
+ }, ee = class {
20
+ state = h;
21
+ listeners = /* @__PURE__ */ new Set();
22
+ subscribe = (e) => (this.listeners.add(e), () => {
23
+ this.listeners.delete(e);
24
+ });
25
+ getSnapshot = () => this.state;
26
+ getServerSnapshot = () => h;
27
+ update(e) {
28
+ let t = {
29
+ ...this.state,
30
+ ...e
31
+ };
32
+ if (t.focused !== this.state.focused || t.pending !== this.state.pending) {
33
+ this.state = t;
34
+ for (let e of this.listeners) e();
35
+ }
36
+ }
37
+ };
38
+ function g({ size: e }) {
39
+ return /* @__PURE__ */ m("div", {
40
+ role: "none",
41
+ "aria-hidden": "true",
42
+ "data-virtual-spacer": "",
43
+ className: r.spacer,
44
+ style: { height: e }
45
+ });
46
+ }
47
+ g.displayName = "FlatTreeSpacer";
48
+ function _(e, t) {
49
+ let n = t instanceof Element ? t : null;
50
+ for (; n && n.parentElement !== e;) n = n.parentElement;
51
+ return n instanceof HTMLElement && n.getAttribute("role") === "treeitem" ? n : null;
52
+ }
53
+ function v(e) {
54
+ let t = e.getAttribute("data-index");
55
+ return t !== null && /^\d+$/.test(t) ? Number(t) : null;
56
+ }
57
+ function y(e, t) {
58
+ return e.querySelector(`:scope > [data-index="${t}"]`);
59
+ }
60
+ function b(e, t, n) {
61
+ for (let r = t + n; r >= 0 && r < e.length; r += n) if (!e[r].item.disabled) return r;
62
+ }
63
+ function te(e, t) {
64
+ let { level: n } = e[t];
65
+ for (let r = t + 1; r < e.length && e[r].level > n; r += 1) if (e[r].level === n + 1 && !e[r].item.disabled) return r;
66
+ }
67
+ var ne = "FlatTree: a tree needs an accessible name. Pass `aria-label` or `aria-labelledby`.", re = "FlatTree: selectionMode=\"multiple\" needs a model that holds the check states: pass `selectionMode: 'multiple'` to `useFlatTree` as well; until then every item shows unchecked.", ie = "FlatTree: `selected` has no effect with selectionMode=\"multiple\"; use the model's `checkedItems`, and `current` for the item the user is on.", ae = "FlatTree: selectionMode=\"single\" draws a radio on every item for `selected`; pass `selected` (null while nothing is selected) and update it from `onItemSelect`.", x = ({ model: h, virtualWindow: x, renderItem: S, selectionMode: oe, selected: C, current: w, onItemSelect: se, className: T, onKeyDown: ce, onFocus: le, onBlur: ue, onPointerDownCapture: de, ref: fe, ...E }) => {
68
+ let D = h.getTreeProps().selectionMode, O = oe ?? D, k = h.visibleItems, A = k.length, j = x !== void 0, M = O === "multiple" ? void 0 : O === "single" ? C ?? null : C, [N] = p.useState(() => new ee()), { focused: P, pending: F } = p.useSyncExternalStore(N.subscribe, N.getSnapshot, N.getServerSnapshot), pe = p.useMemo(() => k.find((e) => !e.item.disabled), [k]), I = P === null ? void 0 : h.getItem(P), L = M == null ? void 0 : h.getItem(M), R = I ?? (L && !L.item.disabled ? L : pe), z = R?.index, B = F === null ? void 0 : h.getItem(F)?.index, me = p.useMemo(() => [z, B].filter((e) => e !== void 0), [z, B]), V = i((e) => {
69
+ e.item.disabled || (e.isBranch && h.toggle(e.item.value), se?.(e.item.value));
70
+ }), H = i((e, t) => {
71
+ e.item.disabled || h.setChecked(e.item.value, e.checked !== "checked", t);
72
+ }), U = x?.itemSize, W = R?.item.value ?? null, he = p.useMemo(() => ({
73
+ selectionMode: O,
74
+ selected: M,
75
+ current: w,
76
+ tabStop: W,
77
+ itemSize: U,
78
+ activate: V,
79
+ toggleChecked: H
80
+ }), [
81
+ O,
82
+ M,
83
+ w,
84
+ W,
85
+ U,
86
+ V,
87
+ H
88
+ ]), G = p.useRef(null), ge = c(fe, G, x?.scrollRef), K = (e, t) => {
89
+ let n = k[t];
90
+ if (!n) return;
91
+ x?.scrollToIndex(t, { align: "auto" });
92
+ let r = y(e, t);
93
+ r ? (N.update({ pending: null }), r.focus()) : N.update({ pending: n.item.value });
94
+ }, { onTypeahead: _e, isSearching: ve } = s({
95
+ getItems: () => k.map((e) => ({
96
+ value: e.item.value,
97
+ text: e.item.label ?? e.item.value,
98
+ disabled: e.item.disabled
99
+ })),
100
+ onMatch: (e) => {
101
+ let t = G.current, n = h.getItem(e);
102
+ t && n && K(t, n.index);
103
+ }
104
+ }), q = p.useRef(null), J = p.useRef(!1), ye = i((e) => {
105
+ j && u(e) && (J.current = !0);
106
+ });
107
+ p.useEffect(() => {
108
+ let e = G.current?.ownerDocument;
109
+ if (!j || !e) return;
110
+ let t = () => {
111
+ J.current = !1;
112
+ };
113
+ return e.addEventListener("keydown", t, !0), () => e.removeEventListener("keydown", t, !0);
114
+ }, [j]);
115
+ let Y = p.useRef(!1), be = i((e) => {
116
+ let t = J.current;
117
+ J.current = !1, Y.current = !e.currentTarget.contains(e.target);
118
+ let n = _(e.currentTarget, e.target), r = n ? v(n) : null, i = r === null ? void 0 : k[r];
119
+ if (!i || r === null) return;
120
+ N.update({
121
+ focused: i.item.value,
122
+ pending: null
123
+ });
124
+ let a = [];
125
+ for (let e = i.parentValue; e !== void 0;) a.push(e), e = h.getItem(e)?.parentValue;
126
+ q.current = {
127
+ path: a,
128
+ index: r
129
+ }, x && !t && x.scrollToIndex(r, { align: "auto" });
130
+ }), xe = i((e) => {
131
+ let t = e.currentTarget, n = e.relatedTarget;
132
+ if (n && t.contains(n)) return;
133
+ Y.current = !1;
134
+ let r = e.target;
135
+ queueMicrotask(() => {
136
+ if (!t.isConnected || Y.current) return;
137
+ let e = t.ownerDocument.activeElement;
138
+ e && t.contains(e) || r.isConnected && N.update({ focused: null });
139
+ });
140
+ }), Se = i((e) => {
141
+ let t = e.currentTarget, n = _(t, e.target), r = n ? v(n) : null;
142
+ if (r === null || r >= A || l(e.target)) return;
143
+ let i = k[r], s = N.getSnapshot().pending, c = (s === null ? void 0 : h.getItem(s)?.index) ?? r;
144
+ if (e.key.length === 1 && (e.key !== "*" || ve()) && _e(e, k[c].item.value)) {
145
+ e.preventDefault();
146
+ return;
147
+ }
148
+ if (e.altKey || e.ctrlKey || e.metaKey) return;
149
+ let u;
150
+ switch (e.key) {
151
+ case "ArrowDown":
152
+ u = b(k, c, 1);
153
+ break;
154
+ case "ArrowUp":
155
+ u = b(k, c, -1);
156
+ break;
157
+ case "Home":
158
+ u = b(k, -1, 1);
159
+ break;
160
+ case "End":
161
+ u = b(k, A, -1);
162
+ break;
163
+ case "Enter":
164
+ e.preventDefault(), V(i);
165
+ return;
166
+ case " ":
167
+ e.preventDefault(), O === "multiple" ? H(i, e.nativeEvent) : V(i);
168
+ return;
169
+ case "*": {
170
+ e.preventDefault();
171
+ let t = k.filter((e) => e.parentValue === i.parentValue && e.isBranch && !e.expanded && !e.item.disabled).map((e) => e.item.value);
172
+ t.length > 0 && h.expand(t);
173
+ return;
174
+ }
175
+ default: {
176
+ let n = a(e.key, {
177
+ orientation: "horizontal",
178
+ dir: o(t)
179
+ });
180
+ if (n === null) return;
181
+ if (n === "next") {
182
+ if (i.isBranch && !i.expanded) {
183
+ e.preventDefault(), i.item.disabled || h.expand(i.item.value);
184
+ return;
185
+ }
186
+ i.expanded && (u = te(k, r));
187
+ } else {
188
+ if (i.isBranch && i.expanded && !i.item.disabled) {
189
+ e.preventDefault(), h.collapse(i.item.value);
190
+ return;
191
+ }
192
+ for (let e = i.parentValue; e !== void 0 && u === void 0;) {
193
+ let t = h.getItem(e);
194
+ if (!t) break;
195
+ t.item.disabled || (u = t.index), e = t.parentValue;
196
+ }
197
+ }
198
+ if (u === void 0) {
199
+ e.preventDefault();
200
+ return;
201
+ }
202
+ }
203
+ }
204
+ e.preventDefault();
205
+ let d = u ?? c;
206
+ if (d === r) {
207
+ N.update({ pending: null }), x?.scrollToIndex(d, { align: "auto" });
208
+ return;
209
+ }
210
+ K(t, d);
211
+ }), X = p.useRef(null);
212
+ p.useLayoutEffect(() => {
213
+ let e = G.current, t = N.getSnapshot().focused, n = t === null ? void 0 : h.getItem(t)?.index, r = X.current;
214
+ if (X.current = null, !x || !e || t === null || n === void 0) return;
215
+ let i = x.itemSize, a = e.scrollTop;
216
+ if (r?.value === t && n !== r.index && e.contains(e.ownerDocument.activeElement)) {
217
+ let t = Math.floor(a / i) === Math.floor(r.top / i) ? a : r.top, o = r.index * i;
218
+ o + i > t && o < t + e.clientHeight && (e.scrollTop = t + (n - r.index) * i, x.scrollToIndex(n, { align: "auto" }), a = e.scrollTop);
219
+ }
220
+ X.current = {
221
+ value: t,
222
+ index: n,
223
+ top: a
224
+ };
225
+ }), p.useLayoutEffect(() => {
226
+ let e = G.current;
227
+ if (!e) return;
228
+ let t = e.ownerDocument, n = t.activeElement, r = !n || n === t.body || !n.isConnected, i = N.getSnapshot();
229
+ if (i.pending !== null) {
230
+ N.update({ pending: null });
231
+ let t = h.getItem(i.pending), a = t ? y(e, t.index) : null;
232
+ a && (r || e.contains(n)) && a.focus();
233
+ return;
234
+ }
235
+ if (i.focused === null || h.getItem(i.focused) || (N.update({ focused: null }), !r || A === 0)) return;
236
+ let a = q.current, o = a?.path.map((e) => h.getItem(e)).find((e) => e)?.index;
237
+ o ??= Math.min(a?.index ?? 0, A - 1), K(e, o);
238
+ });
239
+ let Z = !E["aria-label"] && !E["aria-labelledby"];
240
+ p.useEffect(() => {
241
+ Z && t("FlatTree:name", ne);
242
+ }, [Z]);
243
+ let Q = O === "multiple" && D !== "multiple";
244
+ p.useEffect(() => {
245
+ Q && t("FlatTree:selection-mode", re);
246
+ }, [Q]), p.useEffect(() => {
247
+ O === "multiple" && C !== void 0 && t("FlatTree:selected-with-multiple", ie), O === "single" && C === void 0 && t("FlatTree:single-without-selected", ae);
248
+ }, [O, C]);
249
+ let $ = (e) => /* @__PURE__ */ m(f, {
250
+ item: e,
251
+ children: S ? S(e) : e.item.label ?? e.item.value
252
+ }, `item:${e.item.value}`), Ce = x ? x.layout(A, { keep: me }).map((e) => e.kind === "item" ? $(k[e.index]) : /* @__PURE__ */ m(g, { size: e.size }, `spacer:${e.key}`)) : k.map($);
253
+ return /* @__PURE__ */ m(d.Provider, {
254
+ value: he,
255
+ children: /* @__PURE__ */ m("div", {
256
+ role: "tree",
257
+ "aria-multiselectable": O === "multiple" || void 0,
258
+ "data-selection-mode": O,
259
+ tabIndex: j && W !== null ? -1 : void 0,
260
+ className: e(r.root, "text-body-1", j && "overflow-y-auto [overflow-anchor:none]", T),
261
+ ...E,
262
+ onKeyDown: n(ce, Se),
263
+ onFocus: n(le, be, { checkDefaultPrevented: !1 }),
264
+ onBlur: n(ue, xe, { checkDefaultPrevented: !1 }),
265
+ onPointerDownCapture: n(de, ye),
266
+ ref: ge,
267
+ children: Ce
268
+ })
269
+ });
270
+ };
271
+ x.displayName = "FlatTree";
272
+ var S = /* @__PURE__ */ Object.assign(x, { Item: f });
273
+ //#endregion
274
+ export { S as FlatTree, f as FlatTreeItem };
275
+
276
+ //# sourceMappingURL=FlatTree.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlatTree.mjs","names":["React","NO_FOCUS","FlatTreeFocusStore","listener","state","next","FlatTreeSpacer","flatTreeClassNames","size","getOwnItem","el","target","root","getIndex","value","getRenderedItem","index","nextEnabled","at","from","step","rows","firstEnabledChild","level","NAME_MESSAGE","SELECTION_MODE_MESSAGE","SELECTED_WITH_MULTIPLE_MESSAGE","SINGLE_WITHOUT_SELECTED_MESSAGE","FlatTreeRoot","selectionModeProp","rest","modelMode","model","selectionMode","count","windowed","virtualWindow","effectiveSelected","selected","focusStore","firstEnabled","row","focusedRow","focused","selectedRow","tabStopRow","tabStopIndex","pendingIndex","pending","keep","activate","useEventCallback","onItemSelect","toggleChecked","event","itemSize","tabStop","context","current","rootRef","mergedRef","useMergedRefs","ref","moveTo","useTypeahead","focusPathRef","pointerPressRef","handlePointerDownCapture","isOwnEvent","doc","clear","focusInPopupRef","handleFocus","pointerFocus","path","parent","handleBlur","blurred","active","handleKeyDown","isEditableTarget","awaited","isSearching","onTypeahead","siblings","other","intent","getArrowIntent","getDirection","parentRow","goal","focusPlaceRef","last","top","before","lastTop","lost","snapshot","record","unnamed","warnOnce","missingChecks","renderRow","FlatTreeItem","renderItem","content","entry","FlatTreeContext","cn","className","composeEventHandlers","onKeyDown","onFocus","onBlur","onPointerDownCapture","FlatTree"],"sources":["../../../src/components/layout/FlatTree.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flatTreeClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isEditableTarget, isOwnEvent } from '../../lib/events';\nimport type { VisibleFlatItem } from '../../lib/flatTree';\nimport type { CheckState } from '../../lib/treeCascade';\nimport type { SelectionMode } from '../../lib/types';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useTypeahead } from '../../hooks/useTypeahead';\nimport type { VirtualWindow } from '../../hooks/useVirtualWindow';\nimport { FlatTreeContext, type FlatTreeContextValue, type FlatTreeRow } from './FlatTree.context';\nimport { FlatTreeItem } from './FlatTree.item';\nimport type { FlatTreeModel } from './useFlatTree';\n\nexport type { FlatTreeItemProps } from './FlatTree.item';\n\n/** Properties for the FlatTree component. */\nexport interface FlatTreeProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children' | 'onSelect'\n> {\n /** The tree's model, from `useFlatTree`: the visible rows, the expanded and the checked state. */\n model: FlatTreeModel;\n /**\n * Renders only the items in view (and a few beyond), from `useVirtualWindow({ itemSize })`. The\n * tree is then the scrolling element: give it a bounded height (a class or a style). Every item\n * is exactly `itemSize` pixels tall, so its content must fit in one row. Without it every visible\n * item is rendered.\n *\n * The tree element is then no tab stop of its own while an item is (`tabIndex` -1, as Firefox\n * would stop on a scroller; a `tabIndex` you pass wins), and the browser's scroll anchoring is\n * off on it (the window lays the items out): when rows are inserted or removed above the focused\n * item while it is in view (`*`, or a change of the model from code), the tree moves the view\n * with it, so it stays where it was.\n */\n virtualWindow?: VirtualWindow;\n /**\n * The content of an item, from its row: the item data with its level, position, set size,\n * expanded state and, in multiple mode, its check state. Called for the rendered items only.\n * @default the item's `label`, else its `value`\n */\n renderItem?: (item: VisibleFlatItem & { checked?: CheckState }) => React.ReactNode;\n /**\n * How items are selected, as the nested `Tree`'s `selectionMode`. `'multiple'` draws a checkbox\n * on every item, bound to the model's checked items (create the model with\n * `selectionMode: 'multiple'`); `'single'` draws a radio for `selected`. Spread\n * `model.getTreeProps()` on the tree to pass the model's mode.\n * @default the model's mode (`model.getTreeProps().selectionMode`)\n */\n selectionMode?: 'none' | SelectionMode;\n /**\n * Value of the selected item. When set (also to `null`), every item carries `aria-selected`, and\n * the selected item is where keyboard focus enters the tree while it is visible. It has no effect\n * with `selectionMode=\"multiple\"` (a development warning). With `selectionMode=\"single\"` every\n * item carries `aria-selected` even while it is not set (a development warning: the radios need\n * it).\n */\n selected?: string | null;\n /** Value of the current item (for example the open page): it gets `aria-current=\"true\"`. */\n current?: string | null;\n /**\n * Called with an item's value every time it is activated (a click on its row, Enter, or Space\n * unless the tree has checkboxes), also when the same item is activated again.\n */\n onItemSelect?: (value: string) => void;\n /** Ref to the `role=\"tree\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** The focused and the awaited item of a FlatTree, by value (see {@link FlatTreeFocusStore}). */\ninterface FlatTreeFocus {\n /** The item that has focus while focus is inside the tree: kept rendered, and the tab stop. */\n focused: string | null;\n /** The item a key moved to that was not rendered: kept rendered, focused after the commit. */\n pending: string | null;\n}\n\nconst NO_FOCUS: FlatTreeFocus = { focused: null, pending: null };\n\n/**\n * The focused and the awaited item of a FlatTree, read during render through\n * `useSyncExternalStore` and written by the tree's handlers and layout effect (C-HOOKS: no state\n * set in an effect, no ref read during render).\n */\nclass FlatTreeFocusStore {\n private state: FlatTreeFocus = NO_FOCUS;\n private readonly listeners = new Set<() => void>();\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): FlatTreeFocus => this.state;\n\n getServerSnapshot = (): FlatTreeFocus => NO_FOCUS;\n\n /** Changes the given fields; notifies only when one of them changed. */\n update(next: Partial<FlatTreeFocus>): void {\n const state = { ...this.state, ...next };\n if (state.focused === this.state.focused && state.pending === this.state.pending) return;\n this.state = state;\n for (const listener of this.listeners) listener();\n }\n}\n\n/** The element that stands in for the items of a windowed tree that are not rendered. */\nfunction FlatTreeSpacer({ size }: { size: number }) {\n return (\n <div\n role=\"none\"\n aria-hidden=\"true\"\n data-virtual-spacer=\"\"\n className={flatTreeClassNames.spacer}\n style={{ height: size }}\n />\n );\n}\nFlatTreeSpacer.displayName = 'FlatTreeSpacer';\n\n/** The item element (a treeitem child of `root`) that holds `target`; `null` for a portal's. */\nfunction getOwnItem(root: Element, target: EventTarget | null): HTMLElement | null {\n let el = target instanceof Element ? target : null;\n while (el && el.parentElement !== root) el = el.parentElement;\n return el instanceof HTMLElement && el.getAttribute('role') === 'treeitem' ? el : null;\n}\n\n/** The place of an item element in the visible rows (`data-index`). */\nfunction getIndex(el: Element): number | null {\n const value = el.getAttribute('data-index');\n return value !== null && /^\\d+$/.test(value) ? Number(value) : null;\n}\n\n/** The rendered item at `index` of the visible rows, or `null` while it is not rendered. */\nfunction getRenderedItem(root: Element, index: number): HTMLElement | null {\n return root.querySelector<HTMLElement>(`:scope > [data-index=\"${index}\"]`);\n}\n\n/** The next enabled row from `from` (exclusive) in the direction of `step`, or `undefined`. */\nfunction nextEnabled(rows: readonly FlatTreeRow[], from: number, step: 1 | -1): number | undefined {\n for (let at = from + step; at >= 0 && at < rows.length; at += step) {\n if (!rows[at].item.disabled) return at;\n }\n return undefined;\n}\n\n/** The first enabled child row of the expanded row at `index`, or `undefined`. */\nfunction firstEnabledChild(rows: readonly FlatTreeRow[], index: number): number | undefined {\n const { level } = rows[index];\n for (let at = index + 1; at < rows.length && rows[at].level > level; at += 1) {\n if (rows[at].level === level + 1 && !rows[at].item.disabled) return at;\n }\n return undefined;\n}\n\nconst NAME_MESSAGE =\n 'FlatTree: a tree needs an accessible name. Pass `aria-label` or `aria-labelledby`.';\n\nconst SELECTION_MODE_MESSAGE =\n 'FlatTree: selectionMode=\"multiple\" needs a model that holds the check states: pass ' +\n \"`selectionMode: 'multiple'` to `useFlatTree` as well; until then every item shows unchecked.\";\n\nconst SELECTED_WITH_MULTIPLE_MESSAGE =\n 'FlatTree: `selected` has no effect with selectionMode=\"multiple\"; use the model\\'s ' +\n '`checkedItems`, and `current` for the item the user is on.';\n\nconst SINGLE_WITHOUT_SELECTED_MESSAGE =\n 'FlatTree: selectionMode=\"single\" draws a radio on every item for `selected`; pass `selected` ' +\n '(null while nothing is selected) and update it from `onItemSelect`.';\n\n// The FlatTree root, documented on the exported `FlatTree` const.\nconst FlatTreeRoot = ({\n model,\n virtualWindow,\n renderItem,\n selectionMode: selectionModeProp,\n selected,\n current,\n onItemSelect,\n className,\n onKeyDown,\n onFocus,\n onBlur,\n onPointerDownCapture,\n ref,\n ...rest\n}: FlatTreeProps) => {\n const modelMode = model.getTreeProps().selectionMode;\n const selectionMode = selectionModeProp ?? modelMode;\n const rows = model.visibleItems;\n const count = rows.length;\n const windowed = virtualWindow !== undefined;\n\n // An item carries aria-checked or aria-selected, never both (APG); in single mode every item\n // carries aria-selected from the first render, so the radios and the state agree.\n const effectiveSelected =\n selectionMode === 'multiple'\n ? undefined\n : selectionMode === 'single'\n ? (selected ?? null)\n : selected;\n\n const [focusStore] = React.useState(() => new FlatTreeFocusStore());\n const { focused, pending } = React.useSyncExternalStore(\n focusStore.subscribe,\n focusStore.getSnapshot,\n focusStore.getServerSnapshot,\n );\n\n // The tab stop follows the model, not the DOM (most items are not rendered): the focused item,\n // else the selected item while it is visible and enabled, else the first enabled item.\n const firstEnabled = React.useMemo(() => rows.find((row) => !row.item.disabled), [rows]);\n const focusedRow = focused === null ? undefined : model.getItem(focused);\n const selectedRow =\n effectiveSelected === undefined || effectiveSelected === null\n ? undefined\n : model.getItem(effectiveSelected);\n const tabStopRow =\n focusedRow ?? (selectedRow && !selectedRow.item.disabled ? selectedRow : firstEnabled);\n const tabStopIndex = tabStopRow?.index;\n const pendingIndex = pending === null ? undefined : model.getItem(pending)?.index;\n // The tab stop and the awaited item stay rendered outside the window (a focused item scrolled\n // away keeps focus and its tab stop).\n const keep = React.useMemo(\n () => [tabStopIndex, pendingIndex].filter((index): index is number => index !== undefined),\n [tabStopIndex, pendingIndex],\n );\n\n const activate = useEventCallback((row: FlatTreeRow) => {\n if (row.item.disabled) return;\n if (row.isBranch) model.toggle(row.item.value);\n onItemSelect?.(row.item.value);\n });\n const toggleChecked = useEventCallback((row: FlatTreeRow, event: Event) => {\n if (row.item.disabled) return;\n model.setChecked(row.item.value, row.checked !== 'checked', event);\n });\n\n const itemSize = virtualWindow?.itemSize;\n const tabStop = tabStopRow?.item.value ?? null;\n const context = React.useMemo<FlatTreeContextValue>(\n () => ({\n selectionMode,\n selected: effectiveSelected,\n current,\n tabStop,\n itemSize,\n activate,\n toggleChecked,\n }),\n [selectionMode, effectiveSelected, current, tabStop, itemSize, activate, toggleChecked],\n );\n\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n // The tree is the window's scroller.\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, rootRef, virtualWindow?.scrollRef);\n\n /**\n * Focuses the row at `index`, moving the window to it first (in the same update, so no frame\n * shows the spacer); a row that is not rendered is awaited and focused after the commit that\n * renders it.\n */\n const moveTo = (root: HTMLElement, index: number) => {\n const row = rows[index];\n if (!row) return;\n virtualWindow?.scrollToIndex(index, { align: 'auto' });\n const el = getRenderedItem(root, index);\n if (el) {\n focusStore.update({ pending: null });\n el.focus();\n } else {\n focusStore.update({ pending: row.item.value });\n }\n };\n\n // Typeahead over the visible items' labels (disabled items are skipped).\n const { onTypeahead, isSearching } = useTypeahead({\n getItems: () =>\n rows.map((row) => ({\n value: row.item.value,\n text: row.item.label ?? row.item.value,\n disabled: row.item.disabled,\n })),\n onMatch: (value) => {\n const root = rootRef.current;\n const row = model.getItem(value);\n if (root && row) moveTo(root, row.index);\n },\n });\n\n /** The visible item, its ancestors from the parent up, and its place, of the focused item. */\n const focusPathRef = React.useRef<{ path: string[]; index: number } | null>(null);\n\n /**\n * Set by a pointer press in a windowed tree until the focus it gives, or until a key press:\n * keyboard focus always follows one, so a press that gave no focus never keeps a later keyboard\n * focus from being scrolled into view. A press in a popup an item opened is the popup's.\n */\n const pointerPressRef = React.useRef(false);\n const handlePointerDownCapture = useEventCallback((event: React.PointerEvent<HTMLDivElement>) => {\n if (windowed && isOwnEvent(event)) pointerPressRef.current = true;\n });\n React.useEffect(() => {\n const doc = rootRef.current?.ownerDocument;\n if (!windowed || !doc) return;\n const clear = () => {\n pointerPressRef.current = false;\n };\n doc.addEventListener('keydown', clear, true);\n return () => doc.removeEventListener('keydown', clear, true);\n }, [windowed]);\n\n /**\n * Whether focus is in a popup that an item opened (an element outside the tree's DOM whose focus\n * React bubbles through the tree): the focused item stays kept. Written by the focus and blur\n * handlers.\n */\n const focusInPopupRef = React.useRef(false);\n\n // Focus moving onto an item makes it the focused item (the tab stop, kept rendered). Unless a\n // pointer press gave the focus, the window moves to it in the same update (a browser's own focus\n // scrolling moves the view a frame before the window would follow).\n const handleFocus = useEventCallback((event: React.FocusEvent<HTMLDivElement>) => {\n const pointerFocus = pointerPressRef.current;\n pointerPressRef.current = false;\n focusInPopupRef.current = !event.currentTarget.contains(event.target as Node);\n const el = getOwnItem(event.currentTarget, event.target);\n const index = el ? getIndex(el) : null;\n const row = index === null ? undefined : rows[index];\n if (!row || index === null) return;\n focusStore.update({ focused: row.item.value, pending: null });\n const path: string[] = [];\n for (let parent = row.parentValue; parent !== undefined;) {\n path.push(parent);\n parent = model.getItem(parent)?.parentValue;\n }\n focusPathRef.current = { path, index };\n if (virtualWindow && !pointerFocus) virtualWindow.scrollToIndex(index, { align: 'auto' });\n });\n\n // Focus leaving the tree (for an element outside it, or for nothing) ends the focused item; the\n // tab stop then returns to the selected or the first item. Decided once focus has landed: a\n // popup an item opened takes focus in the same task (`focusInPopupRef`).\n const handleBlur = useEventCallback((event: React.FocusEvent<HTMLDivElement>) => {\n const root = event.currentTarget;\n const next = event.relatedTarget as Node | null;\n if (next && root.contains(next)) return;\n focusInPopupRef.current = false;\n const blurred = event.target as Node;\n queueMicrotask(() => {\n if (!root.isConnected || focusInPopupRef.current) return;\n const active = root.ownerDocument.activeElement;\n if (active && root.contains(active)) return;\n // A focused item that left the document (a branch collapsed around it): the commit's check\n // below has moved focus, or decided that it cannot.\n if (!blurred.isConnected) return;\n focusStore.update({ focused: null });\n });\n });\n\n const handleKeyDown = useEventCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n const root = event.currentTarget;\n // A key from a portal is the portal's; a text field in the content keeps its keys.\n const el = getOwnItem(root, event.target);\n const current = el ? getIndex(el) : null;\n if (current === null || current >= count || isEditableTarget(event.target)) return;\n const row = rows[current];\n // Keys pressed before an awaited item renders move from it (possible only within one task).\n const awaited = focusStore.getSnapshot().pending;\n const from = (awaited === null ? undefined : model.getItem(awaited)?.index) ?? current;\n\n // Typeahead; a Space continues a search, and `*` starts none.\n if (event.key.length === 1 && (event.key !== '*' || isSearching())) {\n if (onTypeahead(event, rows[from].item.value)) {\n event.preventDefault();\n return;\n }\n }\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n\n let target: number | undefined;\n switch (event.key) {\n case 'ArrowDown':\n target = nextEnabled(rows, from, 1);\n break;\n case 'ArrowUp':\n target = nextEnabled(rows, from, -1);\n break;\n case 'Home':\n target = nextEnabled(rows, -1, 1);\n break;\n case 'End':\n target = nextEnabled(rows, count, -1);\n break;\n case 'Enter':\n event.preventDefault();\n activate(row);\n return;\n case ' ':\n event.preventDefault();\n // A checkbox tree toggles the focused item's check (APG); the other modes activate.\n if (selectionMode === 'multiple') toggleChecked(row, event.nativeEvent);\n else activate(row);\n return;\n case '*': {\n event.preventDefault();\n // The siblings of a visible item are all visible (their parent is expanded).\n const siblings = rows\n .filter(\n (other) =>\n other.parentValue === row.parentValue &&\n other.isBranch &&\n !other.expanded &&\n !other.item.disabled,\n )\n .map((other) => other.item.value);\n if (siblings.length > 0) model.expand(siblings);\n return;\n }\n default: {\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(root),\n });\n if (intent === null) return;\n if (intent === 'next') {\n // Expand a collapsed branch (focus stays), else move to the first child.\n if (row.isBranch && !row.expanded) {\n event.preventDefault();\n if (!row.item.disabled) model.expand(row.item.value);\n return;\n }\n if (row.expanded) target = firstEnabledChild(rows, current);\n } else {\n // Collapse an expanded branch (focus stays), else move to the nearest enabled ancestor.\n if (row.isBranch && row.expanded && !row.item.disabled) {\n event.preventDefault();\n model.collapse(row.item.value);\n return;\n }\n for (let parent = row.parentValue; parent !== undefined && target === undefined;) {\n const parentRow = model.getItem(parent);\n if (!parentRow) break;\n if (!parentRow.item.disabled) target = parentRow.index;\n parent = parentRow.parentValue;\n }\n }\n if (target === undefined) {\n event.preventDefault();\n return;\n }\n }\n }\n event.preventDefault();\n // No item to move to: the focused item stays, and is brought into view.\n const goal = target ?? from;\n if (goal === current) {\n focusStore.update({ pending: null });\n virtualWindow?.scrollToIndex(goal, { align: 'auto' });\n return;\n }\n moveTo(root, goal);\n });\n\n /**\n * The focused item of a windowed tree, its place in the visible rows and the scroll offset, at\n * the last commit (written by the layout effect below).\n */\n const focusPlaceRef = React.useRef<{ value: string; index: number; top: number } | null>(null);\n\n // After every commit of a windowed tree: rows inserted or removed above the focused item while\n // it was in view (`*`, a model change from code) move the view with it, so it stays where it\n // was, and the window follows in the same update. The browser's scroll anchoring would do the\n // same a frame before the window follows; it is off (the window lays the rows out).\n React.useLayoutEffect(() => {\n const root = rootRef.current;\n const value = focusStore.getSnapshot().focused;\n const index = value === null ? undefined : model.getItem(value)?.index;\n const last = focusPlaceRef.current;\n focusPlaceRef.current = null;\n if (!virtualWindow || !root || value === null || index === undefined) return;\n const size = virtualWindow.itemSize;\n let top = root.scrollTop;\n if (\n last?.value === value &&\n index !== last.index &&\n root.contains(root.ownerDocument.activeElement)\n ) {\n // Rows removed above may leave less content than the offset, which the browser has clamped\n // by now: an offset in another row than the one recorded (the tree commits at every row the\n // view enters) stands for that, and the recorded one is where the view was.\n const before = Math.floor(top / size) === Math.floor(last.top / size) ? top : last.top;\n const lastTop = last.index * size;\n if (lastTop + size > before && lastTop < before + root.clientHeight) {\n root.scrollTop = before + (index - last.index) * size;\n virtualWindow.scrollToIndex(index, { align: 'auto' });\n top = root.scrollTop;\n }\n }\n focusPlaceRef.current = { value, index, top };\n });\n\n // After every commit: focus the awaited item, which the commit rendered (it is kept), unless\n // focus went outside the tree meanwhile; and when the focused item is no longer visible (a\n // branch collapsed around it, or the items changed) while focus is lost with it, move focus to\n // its nearest visible ancestor, else to the visible item nearest to its place. Never to the body.\n React.useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const doc = root.ownerDocument;\n const active = doc.activeElement;\n const lost = !active || active === doc.body || !active.isConnected;\n const snapshot = focusStore.getSnapshot();\n if (snapshot.pending !== null) {\n focusStore.update({ pending: null });\n const row = model.getItem(snapshot.pending);\n const el = row ? getRenderedItem(root, row.index) : null;\n if (el && (lost || root.contains(active))) el.focus();\n return;\n }\n if (snapshot.focused === null || model.getItem(snapshot.focused)) return;\n focusStore.update({ focused: null });\n if (!lost || count === 0) return;\n const record = focusPathRef.current;\n let target = record?.path.map((value) => model.getItem(value)).find((row) => row)?.index;\n target ??= Math.min(record?.index ?? 0, count - 1);\n moveTo(root, target);\n });\n\n // Development diagnostics (C-DEV): emitted from effects, once per page.\n const unnamed = !rest['aria-label'] && !rest['aria-labelledby'];\n React.useEffect(() => {\n if (unnamed) warnOnce('FlatTree:name', NAME_MESSAGE);\n }, [unnamed]);\n const missingChecks = selectionMode === 'multiple' && modelMode !== 'multiple';\n React.useEffect(() => {\n if (missingChecks) warnOnce('FlatTree:selection-mode', SELECTION_MODE_MESSAGE);\n }, [missingChecks]);\n React.useEffect(() => {\n if (selectionMode === 'multiple' && selected !== undefined) {\n warnOnce('FlatTree:selected-with-multiple', SELECTED_WITH_MULTIPLE_MESSAGE);\n }\n if (selectionMode === 'single' && selected === undefined) {\n warnOnce('FlatTree:single-without-selected', SINGLE_WITHOUT_SELECTED_MESSAGE);\n }\n }, [selectionMode, selected]);\n\n const renderRow = (row: FlatTreeRow) => (\n <FlatTreeItem key={`item:${row.item.value}`} item={row}>\n {renderItem ? renderItem(row) : (row.item.label ?? row.item.value)}\n </FlatTreeItem>\n );\n const content = virtualWindow\n ? virtualWindow\n .layout(count, { keep })\n .map((entry) =>\n entry.kind === 'item' ? (\n renderRow(rows[entry.index])\n ) : (\n <FlatTreeSpacer key={`spacer:${entry.key}`} size={entry.size} />\n ),\n )\n : rows.map(renderRow);\n\n return (\n <FlatTreeContext.Provider value={context}>\n <div\n role=\"tree\"\n aria-multiselectable={selectionMode === 'multiple' ? true : undefined}\n data-selection-mode={selectionMode}\n // A windowed tree's tab stop is an item: the scroller is none of its own (Firefox makes a\n // scroller a tab stop). The consumer's `tabIndex` wins.\n tabIndex={windowed && tabStop !== null ? -1 : undefined}\n className={cn(\n flatTreeClassNames.root,\n 'text-body-1',\n // The window lays the rows out: the browser's scroll anchoring only fights it.\n windowed && 'overflow-y-auto [overflow-anchor:none]',\n className,\n )}\n {...rest}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onFocus={composeEventHandlers(onFocus, handleFocus, { checkDefaultPrevented: false })}\n onBlur={composeEventHandlers(onBlur, handleBlur, { checkDefaultPrevented: false })}\n onPointerDownCapture={composeEventHandlers(onPointerDownCapture, handlePointerDownCapture)}\n ref={mergedRef}\n >\n {content}\n </div>\n </FlatTreeContext.Provider>\n );\n};\nFlatTreeRoot.displayName = 'FlatTree';\n\n/**\n * A tree built from flat data (WAI-ARIA Tree View pattern) that can render only the items in\n * view, for trees of thousands of items. Its model comes from `useFlatTree(items, options)`: items\n * listed with a `parentValue`, in any order, the expanded and the checked state. The tree renders\n * the visible items (the roots and the children of every expanded branch) as sibling\n * `role=\"treeitem\"` elements with `aria-level`, `aria-setsize` and `aria-posinset` from the data,\n * `aria-expanded` on branches, and the nested `Tree`'s chevron, checkbox and radio.\n *\n * ```tsx\n * const model = useFlatTree(items, { defaultExpandedItems: ['docs'] });\n * const virtualWindow = useVirtualWindow({ itemSize: 28 });\n * <FlatTree aria-label=\"Files\" model={model} {...model.getTreeProps()} virtualWindow={virtualWindow} style={{ height: 400 }} />\n * ```\n *\n * Windowing: with `virtualWindow` the tree is the scrolling element (it needs a bounded height),\n * renders the items in view plus the window's overscan and spacers for the others, and every item\n * is exactly the window's `itemSize` tall. The server renders the first window. Keys move over the\n * whole visible list, scrolling an item that is not rendered into view before focusing it, and the\n * focused item stays rendered (and focused) while it is scrolled away.\n *\n * Keyboard: a single tab stop, on the focused item while focus is inside, else on the `selected`\n * item while it is visible, else on the first enabled item; Tab leaves the tree. Up/Down move\n * between the visible items, Home/End to the first and last, Right expands a collapsed branch or\n * moves to its first child, Left collapses an expanded branch or moves to the parent (both\n * mirrored in right-to-left layouts), Enter activates (and toggles a branch), and so does Space\n * unless the tree has checkboxes, `*` expands the sibling branches, and typing moves to the next\n * visible item whose label starts with the typed text (items under a collapsed branch are not\n * searched). The focused item stays the focused item (rendered, and the tab stop) while focus is\n * in a popup that its content opened, such as a menu in a portal, so the popup can return focus\n * to it.\n *\n * Selection, as the nested `Tree`: `selected` and `onItemSelect` (single selection and activation,\n * with radios in `selectionMode=\"single\"`), `current`, and with `selectionMode=\"multiple\"` a\n * checkbox on every item bound to the model's `checkedItems` (Space or a click on the checkbox\n * toggles it, and checks cascade). An item whose data is `disabled` is `aria-disabled`, is skipped\n * by the keys and typeahead, never holds the tab stop (except while a pointer press has focused\n * it), and is neither activated, expanded nor checked by the user (a check of its parent still\n * includes it).\n *\n * When a branch collapses around the focused item (from code), focus moves to that branch, so it\n * never falls to the page. Items expand and collapse at once, without motion: there is no child\n * group to animate. A selected item under a collapsed branch is not the tab stop until it is\n * visible again.\n *\n * `FlatTree.Item` is the row the tree renders for each visible item (it is not written by hand);\n * it is also exported as `FlatTreeItem` for React Server Components, which cannot use the dotted\n * form.\n */\nexport const FlatTree = /* @__PURE__ */ Object.assign(FlatTreeRoot, { Item: FlatTreeItem });\n\nexport { FlatTreeItem };\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/children.cjs"),r=require("../../lib/dev.cjs"),i=require("../../lib/slot.cjs"),a=require("../../lib/composeEventHandlers.cjs"),o=require("../../lib/classNames.cjs"),s=require("../../hooks/useEventCallback.cjs"),c=require("../../hooks/useControllable.cjs"),l=require("../../hooks/useId.cjs"),u=require("../../hooks/useRovingTabIndex.cjs"),d=require("../../hooks/useMergedRefs.cjs"),f=require("../../lib/styles.cjs"),p=require("./disclosureIds.cjs");let m=require("react");m=e.__toESM(m,1);let h=require("react/jsx-runtime");function g(e){r.warnOnce(`TabList:duplicate:${e}`,`TabList: several tabs share the value "${e}". Tab values must be unique within a TabList; tabs with the same value share one id and are selected (and tab stops) together.`)}function _(){let e={tab:new Map,panel:new Map},t=new Set,n=!1,r=()=>{t.forEach(e=>e())};return{register(t,n,i){let a=e[t],o=a.get(n)??[];return t===`tab`&&o.length>0&&g(n),a.set(n,[...o,i]),r(),()=>{let e=[...a.get(n)??[]],t=e.indexOf(i);t!==-1&&e.splice(t,1),e.length>0?a.set(n,e):a.delete(n),r()}},get:(t,r)=>n?e[t].get(r)?.[0]??null:void 0,markReady(){n||(n=!0,r())},subscribe(e){return t.add(e),()=>{t.delete(e)}}}}var v={register:()=>()=>{},get:()=>void 0,markReady:()=>{},subscribe:()=>()=>{}},y=m.createContext(null),b={orientation:`horizontal`,appearance:`transparent`,size:`medium`,isSelected:()=>!1,select:()=>{},getTabIndex:()=>-1,getGeneratedId:(e,t)=>`wave-tablist-inert-${e}-${t}`,getStaticTabId:e=>`wave-tablist-inert-tab-${e}`,getStaticPanelId:()=>void 0,registry:v};function x(e){return m.useContext(y)||(r.reportMissingContext(e,`<TabList>`),b)}function S(e){let t=e[`aria-disabled`];return e.disabled===!0||t===!0||t===`true`}function C(e){return typeof e==`string`&&e!==``?e:null}function w(e,t){if(Array.isArray(e))return e.forEach(e=>w(e,t)),t;if(!m.isValidElement(e))return t;let{props:r}=e,i=n.getElementType(e,{suspend:!1}),a=typeof r.value==`string`?r.value:void 0;if(i===P){if(a!==void 0){t.firstEnabled===void 0&&!S(r)&&(t.firstEnabled=a);let e=C(r.id);e!==null&&t.tabIds.push([a,e])}return t}return i===F?(a!==void 0&&t.panels.push([a,C(r.id)]),t):i===k?t:w(r.children,t)}function T(e,t){if(Array.isArray(e))return e.some(e=>T(e,t));if(!m.isValidElement(e))return!1;let r=n.getElementType(e,{suspend:!1});return r===P?t===`tab`:r===F||r===I?t===`panel`:r!==k&&T(e.props.children,t)}function E(e){return T(e,`panel`)&&!T(e,`tab`)}var D=m.createContext(null),O=`TabList.Panel was rendered inside the role="tablist" element, where only tabs belong (axe aria-required-children). The TabList moves a Panel after the tablist when it is its child, or in a wrapper that holds no Tab, but it cannot see a Panel that a component renders itself, or separate a wrapper's Panels from its Tabs. Place such panels inside TabList.Panels, which renders after the tablist.`,k=({value:e,defaultValue:i,onValueChange:f,orientation:g,appearance:v=`transparent`,size:b=`medium`,selectTabOnFocus:x=!0,selectedValue:S,defaultSelectedValue:C,onTabSelect:T,vertical:O,className:k,children:A,onKeyDown:j,onFocus:M,ref:N,...P})=>{let F=r.resolveDeprecatedProp(`TabList`,e,S,`selectedValue`,`value`),I=r.resolveDeprecatedProp(`TabList`,i,C,`defaultSelectedValue`,`defaultValue`),L=r.resolveDeprecatedProp(`TabList`,g,O===void 0?void 0:O?`vertical`:`horizontal`,`vertical`,`orientation`)??`horizontal`;T&&r.warnDeprecated(`TabList`,`onTabSelect`,`onValueChange`,"`onValueChange` is called only when the selected tab changes.");let[R,z,B]=c.useControllable(F,I??``,f),V=JSON.stringify(w(A,{tabIds:[],panels:[]})),H=m.useMemo(()=>{let e=JSON.parse(V);return{firstEnabled:e.firstEnabled,tabIds:new Map(e.tabIds),panels:new Map(e.panels)}},[V]),U=!B&&R===``,{containerProps:W,getTabIndex:G}=u.useRovingTabIndex({activeValue:U?H.firstEnabled??null:R,orientation:L,loop:!0,onFocusMove:x?e=>q(e):void 0}),K=m.useCallback(e=>U?G(e)===0:R===e,[U,G,R]),q=s.useEventCallback(e=>{T?.(e),K(e)||z(e)}),J=l.useId(`tablist`),[Y]=m.useState(_);m.useLayoutEffect(()=>Y.markReady(),[Y]);let X=m.useMemo(()=>({orientation:L,appearance:v,size:b,isSelected:K,select:q,getTabIndex:G,getGeneratedId:(e,t)=>p.getPartId(J,e,t),getStaticTabId:e=>H.tabIds.get(e)??p.getPartId(J,`tab`,e),getStaticPanelId:e=>{let t=H.panels.get(e);if(t!==void 0)return t??p.getPartId(J,`panel`,e)},registry:Y}),[L,v,b,K,q,G,J,H,Y]),ee=d.useMergedRefs(N,W.ref),Z=[],Q=[];n.flattenChildren(A).forEach(({key:e,node:t})=>{let n=(0,h.jsx)(m.Fragment,{children:t},e);(E(t)?Q:Z).push(n)});let $=L===`vertical`;return(0,h.jsx)(y.Provider,{value:X,children:(0,h.jsxs)(`div`,{className:t.cn($&&`flex`),children:[(0,h.jsx)(`div`,{role:`tablist`,"aria-orientation":L,"data-appearance":v,"data-size":b,"data-orientation":L,className:t.cn(o.tabListClassNames.root,$?`flex w-40 flex-col`:`flex`,v===`transparent`?$?`border-e border-border`:`border-b border-border`:`gap-1`,k),...P,"data-roving-container":``,onKeyDown:a.composeEventHandlers(j,W.onKeyDown),onFocus:a.composeEventHandlers(M,W.onFocus,{checkDefaultPrevented:!1}),ref:ee,children:(0,h.jsx)(D.Provider,{value:`tabs`,children:Z})}),(0,h.jsx)(D.Provider,{value:`panels`,children:Q})]})})};k.displayName=`TabList`;var A={small:`px-3 py-1.5`,medium:`px-4 py-2`,large:`px-5 py-3`},j={small:`p-1.5`,medium:`p-2`,large:`p-3`},M={small:`text-caption-1`,medium:`text-body-1`,large:`text-body-2`};function N(e,n,r){switch(e){case`subtle`:case`subtle-circular`:{let r=e===`subtle`?`rounded-md`:`rounded-full`;return n?t.cn(r,`bg-subtle-selected text-foreground`,f.forcedColors.selectedContainer):t.cn(r,`text-muted-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:hover:text-foreground not-disabled:not-aria-disabled:active:bg-subtle-pressed`)}case`filled-circular`:return n?t.cn(`rounded-full bg-primary text-primary-foreground not-disabled:not-aria-disabled:hover:bg-primary-hover not-disabled:not-aria-disabled:active:bg-primary-pressed`,f.forcedColors.selectedContainer):`rounded-full bg-muted text-muted-foreground not-disabled:not-aria-disabled:hover:bg-muted-hover not-disabled:not-aria-disabled:hover:text-foreground not-disabled:not-aria-disabled:active:bg-muted-pressed`;default:return n?t.cn(`text-primary forced-colors:border-[Highlight]`,r?`border-s-2 border-s-primary`:`border-b-2 border-b-primary`):`text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground`}}var P=({value:e,id:n,icon:s,className:c,children:l,onClick:u,ref:d,...p})=>{let g=x(`TabList.Tab`),_=g.isSelected(e),v=g.orientation===`vertical`,y=S(p),b=!!s&&i.slotRendersContent(s),w=b&&!i.slotRendersContent(l),T=p[`aria-label`],E=p[`aria-labelledby`],D=typeof T==`string`&&T.trim()!==``||typeof E==`string`&&E.trim()!==``;m.useEffect(()=>{w&&!D&&r.warnOnce(`TabList.Tab:icon-only-name`,"TabList.Tab: a tab with an icon and no text has no accessible name. Pass `aria-label` (or `aria-labelledby`).")},[w,D]);let{registry:O}=g,k=C(n)??g.getGeneratedId(`tab`,e);m.useLayoutEffect(()=>O.register(`tab`,e,k),[O,e,k]);let P=m.useSyncExternalStore(O.subscribe,()=>O.get(`panel`,e),()=>void 0),F=P===void 0?g.getStaticPanelId(e):P??void 0;return(0,h.jsxs)(`button`,{type:`button`,role:`tab`,className:t.cn(o.tabListTabClassNames.root,`font-semibold transition-colors motion-reduce:transition-none`,w?j[g.size]:A[g.size],M[g.size],b&&`inline-flex items-center justify-center gap-2`,v&&`text-start`,N(g.appearance,_,v),f.disabledStyles,f.focusRingInset,c),...p,id:k,"aria-selected":_,"aria-controls":_?F:void 0,tabIndex:g.getTabIndex(e),"data-roving-value":e,"data-selected":_?``:void 0,"data-icon-only":w?``:void 0,onClick:a.composeEventHandlers(u,()=>{y||g.select(e)}),ref:d,children:[b&&i.renderSlot(s,`span`,o.tabListTabClassNames.icon,{"aria-hidden":!0}),l]})};P.displayName=`Tab`;var F=({value:e,id:n,children:i,className:a,ref:s,...c})=>{let l=x(`TabList.Panel`),u=m.useContext(D)===`tabs`;m.useEffect(()=>{u&&r.warnOnce(`TabList.Panel:inside-tablist`,O)},[u]);let{registry:d}=l,p=C(n)??l.getGeneratedId(`panel`,e);m.useLayoutEffect(()=>d.register(`panel`,e,p),[d,e,p]);let g=m.useSyncExternalStore(d.subscribe,()=>d.get(`tab`,e),()=>void 0);if(!l.isSelected(e))return null;let _=g===void 0?l.getStaticTabId(e):g??void 0;return(0,h.jsx)(`div`,{role:`tabpanel`,tabIndex:0,className:t.cn(o.tabListPanelClassNames.root,`p-4`,f.focusRing,a),...c,id:p,"aria-labelledby":_,ref:s,children:i})};F.displayName=`TabPanel`;var I=({className:e,children:n,ref:r,...i})=>(0,h.jsx)(`div`,{ref:r,className:t.cn(o.tabListPanelsClassNames.root,`min-w-0 flex-1`,e),...i,children:n});I.displayName=`TabPanels`;var L=Object.assign(k,{Tab:P,Panel:F,Panels:I});exports.TabList=L,exports.TabListPanel=F,exports.TabListPanels=I,exports.TabListTab=P;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/children.cjs"),r=require("../../lib/dev.cjs"),i=require("../../lib/slot.cjs"),a=require("../../lib/composeEventHandlers.cjs"),o=require("../../lib/classNames.cjs"),s=require("../../hooks/useEventCallback.cjs"),c=require("../../hooks/useControllable.cjs"),l=require("../../hooks/useId.cjs"),u=require("../../hooks/useRovingTabIndex.cjs"),d=require("../../hooks/useMergedRefs.cjs"),f=require("../../hooks/usePrefersReducedMotion.cjs"),p=require("../../lib/styles.cjs"),m=require("../../lib/motion.cjs"),h=require("../../hooks/useMotion.cjs"),g=require("./disclosureIds.cjs");let _=require("react");_=e.__toESM(_,1);let v=require("react/jsx-runtime");function y(e){r.warnOnce(`TabList:duplicate:${e}`,`TabList: several tabs share the value "${e}". Tab values must be unique within a TabList; tabs with the same value share one id and are selected (and tab stops) together.`)}function b(){let e={tab:new Map,panel:new Map},t=new Set,n=!1,r=()=>{t.forEach(e=>e())};return{register(t,n,i){let a=e[t],o=a.get(n)??[];return t===`tab`&&o.length>0&&y(n),a.set(n,[...o,i]),r(),()=>{let e=[...a.get(n)??[]],t=e.indexOf(i);t!==-1&&e.splice(t,1),e.length>0?a.set(n,e):a.delete(n),r()}},get:(t,r)=>n?e[t].get(r)?.[0]??null:void 0,markReady(){n||(n=!0,r())},subscribe(e){return t.add(e),()=>{t.delete(e)}}}}var x={register:()=>()=>{},get:()=>void 0,markReady:()=>{},subscribe:()=>()=>{}},S=_.createContext(null),C={orientation:`horizontal`,appearance:`transparent`,size:`medium`,isSelected:()=>!1,select:()=>{},getTabIndex:()=>-1,getGeneratedId:(e,t)=>`wave-tablist-inert-${e}-${t}`,getStaticTabId:e=>`wave-tablist-inert-tab-${e}`,getStaticPanelId:()=>void 0,registry:x,indicator:null,indicatorMotion:``};function w(e){return _.useContext(S)||(r.reportMissingContext(e,`<TabList>`),C)}function T(e){let t=e[`aria-disabled`];return e.disabled===!0||t===!0||t===`true`}function E(e){return typeof e==`string`&&e!==``?e:null}function D(e,t){if(Array.isArray(e))return e.forEach(e=>D(e,t)),t;if(!_.isValidElement(e))return t;let{props:r}=e,i=n.getElementType(e,{suspend:!1}),a=typeof r.value==`string`?r.value:void 0;if(i===L){if(a!==void 0){t.firstEnabled===void 0&&!T(r)&&(t.firstEnabled=a);let e=E(r.id);e!==null&&t.tabIds.push([a,e])}return t}return i===R?(a!==void 0&&t.panels.push([a,E(r.id)]),t):i===M?t:D(r.children,t)}function O(e,t){if(Array.isArray(e))return e.some(e=>O(e,t));if(!_.isValidElement(e))return!1;let r=n.getElementType(e,{suspend:!1});return r===L?t===`tab`:r===R||r===z?t===`panel`:r!==M&&O(e.props.children,t)}function k(e){return O(e,`panel`)&&!O(e,`tab`)}var A=_.createContext(null),j=`TabList.Panel was rendered inside the role="tablist" element, where only tabs belong (axe aria-required-children). The TabList moves a Panel after the tablist when it is its child, or in a wrapper that holds no Tab, but it cannot see a Panel that a component renders itself, or separate a wrapper's Panels from its Tabs. Place such panels inside TabList.Panels, which renders after the tablist.`,M=({value:e,defaultValue:i,onValueChange:p,orientation:y,appearance:x=`transparent`,size:C=`medium`,selectTabOnFocus:w=!0,motion:T,selectedValue:E,defaultSelectedValue:O,onTabSelect:j,vertical:M,className:N,children:P,onKeyDown:ee,onFocus:F,ref:I,...L})=>{let R=r.resolveDeprecatedProp(`TabList`,e,E,`selectedValue`,`value`),z=r.resolveDeprecatedProp(`TabList`,i,O,`defaultSelectedValue`,`defaultValue`),B=r.resolveDeprecatedProp(`TabList`,y,M===void 0?void 0:M?`vertical`:`horizontal`,`vertical`,`orientation`)??`horizontal`;j&&r.warnDeprecated(`TabList`,`onTabSelect`,`onValueChange`,"`onValueChange` is called only when the selected tab changes.");let[V,te,ne]=c.useControllable(R,z??``,p),H=JSON.stringify(D(P,{tabIds:[],panels:[]})),U=_.useMemo(()=>{let e=JSON.parse(H);return{firstEnabled:e.firstEnabled,tabIds:new Map(e.tabIds),panels:new Map(e.panels)}},[H]),W=!ne&&V===``,{containerProps:G,getTabIndex:K}=u.useRovingTabIndex({activeValue:W?U.firstEnabled??null:V,orientation:B,loop:!0,onFocusMove:w?e=>J(e):void 0}),q=_.useCallback(e=>W?K(e)===0:V===e,[W,K,V]),J=s.useEventCallback(e=>{j?.(e),q(e)||te(e)}),Y=l.useId(`tablist`),[X]=_.useState(b);_.useLayoutEffect(()=>X.markReady(),[X]);let Z=B===`vertical`,Q=h.useMotionClasses(T,m.tabIndicatorMotion),re=f.usePrefersReducedMotion(),ie=x===`transparent`&&Q!==``&&!re,[$,ae]=_.useState(null),oe=_.useRef(null),se=_.useRef(null);_.useLayoutEffect(()=>{let e=oe.current;if(!e)return;let t=Array.from(e.querySelectorAll(`[role="tab"]`)),n=e=>e.getAttribute(`data-roving-value`),r=t.find(e=>{let t=n(e);return t!==null&&q(t)}),i=r?n(r):null,a=se.current;if(se.current=i,!ie||!r||i===null||a===null||i===a)return;let o=t.find(e=>n(e)===a);if(!o)return;let s=o.getBoundingClientRect(),c=r.getBoundingClientRect(),l=Z?c.height:c.width;l!==0&&ae({value:i,offset:Z?s.top-c.top:s.left-c.left,scale:(Z?s.height:s.width)/l})},[q,ie,Z]),_.useEffect(()=>{if(!$)return;let e=requestAnimationFrame(()=>ae(null));return()=>cancelAnimationFrame(e)},[$]);let ce=_.useMemo(()=>({orientation:B,appearance:x,size:C,isSelected:q,select:J,getTabIndex:K,getGeneratedId:(e,t)=>g.getPartId(Y,e,t),getStaticTabId:e=>U.tabIds.get(e)??g.getPartId(Y,`tab`,e),getStaticPanelId:e=>{let t=U.panels.get(e);if(t!==void 0)return t??g.getPartId(Y,`panel`,e)},registry:X,indicator:$,indicatorMotion:Q}),[B,x,C,q,J,K,Y,U,X,$,Q]),le=d.useMergedRefs(I,G.ref,oe),ue=[],de=[];return n.flattenChildren(P).forEach(({key:e,node:t})=>{let n=(0,v.jsx)(_.Fragment,{children:t},e);(k(t)?de:ue).push(n)}),(0,v.jsx)(S.Provider,{value:ce,children:(0,v.jsxs)(`div`,{className:t.cn(Z&&`flex`),children:[(0,v.jsx)(`div`,{role:`tablist`,"aria-orientation":B,"data-appearance":x,"data-size":C,"data-orientation":B,className:t.cn(o.tabListClassNames.root,Z?`flex w-40 flex-col`:`flex`,x===`transparent`?Z?`border-e border-border`:`border-b border-border`:`gap-1`,N),...L,"data-roving-container":``,onKeyDown:a.composeEventHandlers(ee,G.onKeyDown),onFocus:a.composeEventHandlers(F,G.onFocus,{checkDefaultPrevented:!1}),ref:le,children:(0,v.jsx)(A.Provider,{value:`tabs`,children:ue})}),(0,v.jsx)(A.Provider,{value:`panels`,children:de})]})})};M.displayName=`TabList`;var N={small:`px-3 py-1.5`,medium:`px-4 py-2`,large:`px-5 py-3`},P={small:`p-1.5`,medium:`p-2`,large:`p-3`},ee={small:`text-caption-1`,medium:`text-body-1`,large:`text-body-2`},F={horizontal:`relative border-b-2 border-b-transparent after:absolute after:inset-x-0 after:-bottom-0.5 after:border-b-2 after:border-b-primary after:origin-left after:translate-x-[var(--wave-tab-indicator-offset,0px)] after:scale-x-[var(--wave-tab-indicator-scale,1)] forced-colors:after:border-[Highlight]`,vertical:`relative border-s-2 border-s-transparent after:absolute after:inset-y-0 after:-start-0.5 after:border-s-2 after:border-s-primary after:origin-top after:translate-y-[var(--wave-tab-indicator-offset,0px)] after:scale-y-[var(--wave-tab-indicator-scale,1)] forced-colors:after:border-[Highlight]`};function I(e,n,r){switch(e){case`subtle`:case`subtle-circular`:{let r=e===`subtle`?`rounded-md`:`rounded-full`;return n?t.cn(r,`bg-subtle-selected text-foreground`,p.forcedColors.selectedContainer):t.cn(r,`text-muted-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:hover:text-foreground not-disabled:not-aria-disabled:active:bg-subtle-pressed`)}case`filled-circular`:return n?t.cn(`rounded-full bg-primary text-primary-foreground not-disabled:not-aria-disabled:hover:bg-primary-hover not-disabled:not-aria-disabled:active:bg-primary-pressed`,p.forcedColors.selectedContainer):`rounded-full bg-muted text-muted-foreground not-disabled:not-aria-disabled:hover:bg-muted-hover not-disabled:not-aria-disabled:hover:text-foreground not-disabled:not-aria-disabled:active:bg-muted-pressed`;default:return t.cn(`border-transparent forced-colors:border-[Canvas]`,n?t.cn(`text-primary`,F[r?`vertical`:`horizontal`]):`text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground`)}}var L=({value:e,id:n,icon:s,className:c,style:l,children:u,onClick:d,ref:f,...m})=>{let h=w(`TabList.Tab`),g=h.isSelected(e),y=h.orientation===`vertical`,b=g&&h.indicator?.value===e?h.indicator:null,x=g&&h.appearance===`transparent`&&!b?h.indicatorMotion:void 0,S=b?{...l,"--wave-tab-indicator-offset":`${b.offset}px`,"--wave-tab-indicator-scale":String(b.scale)}:l,C=T(m),D=!!s&&i.slotRendersContent(s),O=D&&!i.slotRendersContent(u),k=m[`aria-label`],A=m[`aria-labelledby`],j=typeof k==`string`&&k.trim()!==``||typeof A==`string`&&A.trim()!==``;_.useEffect(()=>{O&&!j&&r.warnOnce(`TabList.Tab:icon-only-name`,"TabList.Tab: a tab with an icon and no text has no accessible name. Pass `aria-label` (or `aria-labelledby`).")},[O,j]);let{registry:M}=h,F=E(n)??h.getGeneratedId(`tab`,e);_.useLayoutEffect(()=>M.register(`tab`,e,F),[M,e,F]);let L=_.useSyncExternalStore(M.subscribe,()=>M.get(`panel`,e),()=>void 0),R=L===void 0?h.getStaticPanelId(e):L??void 0;return(0,v.jsxs)(`button`,{type:`button`,role:`tab`,className:t.cn(o.tabListTabClassNames.root,`font-semibold transition-colors motion-reduce:transition-none`,O?P[h.size]:N[h.size],ee[h.size],D&&`inline-flex items-center justify-center gap-2`,y&&`text-start`,I(h.appearance,g,y),p.disabledStyles,p.focusRingInset,x,c),style:S,...m,id:F,"aria-selected":g,"aria-controls":g?R:void 0,tabIndex:h.getTabIndex(e),"data-roving-value":e,"data-selected":g?``:void 0,"data-icon-only":O?``:void 0,onClick:a.composeEventHandlers(d,()=>{C||h.select(e)}),ref:f,children:[D&&i.renderSlot(s,`span`,o.tabListTabClassNames.icon,{"aria-hidden":!0}),u]})};L.displayName=`Tab`;var R=({value:e,id:n,children:i,className:a,ref:s,...c})=>{let l=w(`TabList.Panel`),u=_.useContext(A)===`tabs`;_.useEffect(()=>{u&&r.warnOnce(`TabList.Panel:inside-tablist`,j)},[u]);let{registry:d}=l,f=E(n)??l.getGeneratedId(`panel`,e);_.useLayoutEffect(()=>d.register(`panel`,e,f),[d,e,f]);let m=_.useSyncExternalStore(d.subscribe,()=>d.get(`tab`,e),()=>void 0);if(!l.isSelected(e))return null;let h=m===void 0?l.getStaticTabId(e):m??void 0;return(0,v.jsx)(`div`,{role:`tabpanel`,tabIndex:0,className:t.cn(o.tabListPanelClassNames.root,`p-4`,p.focusRing,a),...c,id:f,"aria-labelledby":h,ref:s,children:i})};R.displayName=`TabPanel`;var z=({className:e,children:n,ref:r,...i})=>(0,v.jsx)(`div`,{ref:r,className:t.cn(o.tabListPanelsClassNames.root,`min-w-0 flex-1`,e),...i,children:n});z.displayName=`TabPanels`;var B=Object.assign(M,{Tab:L,Panel:R,Panels:z});exports.TabList=B,exports.TabListPanel=R,exports.TabListPanels=z,exports.TabListTab=L;
2
2
  //# sourceMappingURL=TabList.cjs.map