@salt-ds/lab 1.0.0-alpha.90 → 1.0.0-alpha.92

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 (362) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/css/salt-lab.css +169 -404
  3. package/dist-cjs/index.js +20 -16
  4. package/dist-cjs/index.js.map +1 -1
  5. package/dist-cjs/mega-menu/MegaMenu.js +82 -0
  6. package/dist-cjs/mega-menu/MegaMenu.js.map +1 -0
  7. package/dist-cjs/mega-menu/MegaMenuContent.css.js +6 -0
  8. package/dist-cjs/mega-menu/MegaMenuContent.css.js.map +1 -0
  9. package/dist-cjs/mega-menu/MegaMenuContent.js +33 -0
  10. package/dist-cjs/mega-menu/MegaMenuContent.js.map +1 -0
  11. package/dist-cjs/mega-menu/MegaMenuContext.js +11 -0
  12. package/dist-cjs/mega-menu/MegaMenuContext.js.map +1 -0
  13. package/dist-cjs/mega-menu/MegaMenuGroup.css.js +6 -0
  14. package/dist-cjs/mega-menu/MegaMenuGroup.css.js.map +1 -0
  15. package/dist-cjs/mega-menu/MegaMenuGroup.js +58 -0
  16. package/dist-cjs/mega-menu/MegaMenuGroup.js.map +1 -0
  17. package/dist-cjs/mega-menu/MegaMenuHeader.css.js +6 -0
  18. package/dist-cjs/mega-menu/MegaMenuHeader.css.js.map +1 -0
  19. package/dist-cjs/mega-menu/MegaMenuHeader.js +26 -0
  20. package/dist-cjs/mega-menu/MegaMenuHeader.js.map +1 -0
  21. package/dist-cjs/mega-menu/MegaMenuItem.css.js +6 -0
  22. package/dist-cjs/mega-menu/MegaMenuItem.css.js.map +1 -0
  23. package/dist-cjs/mega-menu/MegaMenuItem.js +52 -0
  24. package/dist-cjs/mega-menu/MegaMenuItem.js.map +1 -0
  25. package/dist-cjs/mega-menu/MegaMenuItemContent.css.js +6 -0
  26. package/dist-cjs/mega-menu/MegaMenuItemContent.css.js.map +1 -0
  27. package/dist-cjs/mega-menu/MegaMenuItemContent.js +23 -0
  28. package/dist-cjs/mega-menu/MegaMenuItemContent.js.map +1 -0
  29. package/dist-cjs/mega-menu/MegaMenuPanel.css.js +6 -0
  30. package/dist-cjs/mega-menu/MegaMenuPanel.css.js.map +1 -0
  31. package/dist-cjs/mega-menu/MegaMenuPanel.js +108 -0
  32. package/dist-cjs/mega-menu/MegaMenuPanel.js.map +1 -0
  33. package/dist-cjs/mega-menu/MegaMenuSection.css.js +6 -0
  34. package/dist-cjs/mega-menu/MegaMenuSection.css.js.map +1 -0
  35. package/dist-cjs/mega-menu/MegaMenuSection.js +25 -0
  36. package/dist-cjs/mega-menu/MegaMenuSection.js.map +1 -0
  37. package/dist-cjs/mega-menu/MegaMenuTrigger.js +92 -0
  38. package/dist-cjs/mega-menu/MegaMenuTrigger.js.map +1 -0
  39. package/dist-cjs/mega-menu/useMegaMenu.js +15 -0
  40. package/dist-cjs/mega-menu/useMegaMenu.js.map +1 -0
  41. package/dist-cjs/mega-menu/useMegaMenuKeyboard.js +209 -0
  42. package/dist-cjs/mega-menu/useMegaMenuKeyboard.js.map +1 -0
  43. package/dist-cjs/side-panel/SidePanel.css.js +1 -1
  44. package/dist-cjs/side-panel/SidePanel.js +107 -66
  45. package/dist-cjs/side-panel/SidePanel.js.map +1 -1
  46. package/dist-cjs/side-panel/SidePanelCloseButton.js +38 -0
  47. package/dist-cjs/side-panel/SidePanelCloseButton.js.map +1 -0
  48. package/dist-cjs/side-panel/SidePanelContent.css.js +1 -1
  49. package/dist-cjs/side-panel/SidePanelContent.js +3 -23
  50. package/dist-cjs/side-panel/SidePanelContent.js.map +1 -1
  51. package/dist-cjs/side-panel/SidePanelHeader.css.js +1 -1
  52. package/dist-cjs/side-panel/SidePanelHeader.js.map +1 -1
  53. package/dist-cjs/side-panel/SidePanelProvider.js +11 -4
  54. package/dist-cjs/side-panel/SidePanelProvider.js.map +1 -1
  55. package/dist-cjs/side-panel/SidePanelTitle.css.js +1 -1
  56. package/dist-cjs/side-panel/SidePanelTitle.js +1 -0
  57. package/dist-cjs/side-panel/SidePanelTitle.js.map +1 -1
  58. package/dist-cjs/side-panel/SidePanelTrigger.js +4 -4
  59. package/dist-cjs/side-panel/SidePanelTrigger.js.map +1 -1
  60. package/dist-cjs/side-panel/internal/SidePanelContext.js +2 -1
  61. package/dist-cjs/side-panel/internal/SidePanelContext.js.map +1 -1
  62. package/dist-cjs/side-panel/internal/useIsScrollable.js +50 -0
  63. package/dist-cjs/side-panel/internal/useIsScrollable.js.map +1 -0
  64. package/dist-cjs/side-panel/internal/useSidePanelTabOrder.js +214 -0
  65. package/dist-cjs/side-panel/internal/useSidePanelTabOrder.js.map +1 -0
  66. package/dist-cjs/side-panel/useSidePanel.js +9 -7
  67. package/dist-cjs/side-panel/useSidePanel.js.map +1 -1
  68. package/dist-cjs/tree/Tree.js +8 -5
  69. package/dist-cjs/tree/Tree.js.map +1 -1
  70. package/dist-cjs/tree/TreeContext.js.map +1 -1
  71. package/dist-cjs/tree/TreeNode.js +18 -14
  72. package/dist-cjs/tree/TreeNode.js.map +1 -1
  73. package/dist-cjs/tree/TreeNodeTrigger.js +4 -3
  74. package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
  75. package/dist-cjs/tree/treeModel.js +61 -0
  76. package/dist-cjs/tree/treeModel.js.map +1 -0
  77. package/dist-cjs/tree/useTree.js +71 -65
  78. package/dist-cjs/tree/useTree.js.map +1 -1
  79. package/dist-es/index.js +10 -8
  80. package/dist-es/index.js.map +1 -1
  81. package/dist-es/mega-menu/MegaMenu.js +80 -0
  82. package/dist-es/mega-menu/MegaMenu.js.map +1 -0
  83. package/dist-es/mega-menu/MegaMenuContent.css.js +4 -0
  84. package/dist-es/mega-menu/MegaMenuContent.css.js.map +1 -0
  85. package/dist-es/mega-menu/MegaMenuContent.js +31 -0
  86. package/dist-es/mega-menu/MegaMenuContent.js.map +1 -0
  87. package/dist-es/mega-menu/MegaMenuContext.js +9 -0
  88. package/dist-es/mega-menu/MegaMenuContext.js.map +1 -0
  89. package/dist-es/mega-menu/MegaMenuGroup.css.js +4 -0
  90. package/dist-es/mega-menu/MegaMenuGroup.css.js.map +1 -0
  91. package/dist-es/mega-menu/MegaMenuGroup.js +56 -0
  92. package/dist-es/mega-menu/MegaMenuGroup.js.map +1 -0
  93. package/dist-es/mega-menu/MegaMenuHeader.css.js +4 -0
  94. package/dist-es/mega-menu/MegaMenuHeader.css.js.map +1 -0
  95. package/dist-es/mega-menu/MegaMenuHeader.js +24 -0
  96. package/dist-es/mega-menu/MegaMenuHeader.js.map +1 -0
  97. package/dist-es/mega-menu/MegaMenuItem.css.js +4 -0
  98. package/dist-es/mega-menu/MegaMenuItem.css.js.map +1 -0
  99. package/dist-es/mega-menu/MegaMenuItem.js +50 -0
  100. package/dist-es/mega-menu/MegaMenuItem.js.map +1 -0
  101. package/dist-es/mega-menu/MegaMenuItemContent.css.js +4 -0
  102. package/dist-es/mega-menu/MegaMenuItemContent.css.js.map +1 -0
  103. package/dist-es/mega-menu/MegaMenuItemContent.js +21 -0
  104. package/dist-es/mega-menu/MegaMenuItemContent.js.map +1 -0
  105. package/dist-es/mega-menu/MegaMenuPanel.css.js +4 -0
  106. package/dist-es/mega-menu/MegaMenuPanel.css.js.map +1 -0
  107. package/dist-es/mega-menu/MegaMenuPanel.js +106 -0
  108. package/dist-es/mega-menu/MegaMenuPanel.js.map +1 -0
  109. package/dist-es/mega-menu/MegaMenuSection.css.js +4 -0
  110. package/dist-es/mega-menu/MegaMenuSection.css.js.map +1 -0
  111. package/dist-es/mega-menu/MegaMenuSection.js +23 -0
  112. package/dist-es/mega-menu/MegaMenuSection.js.map +1 -0
  113. package/dist-es/mega-menu/MegaMenuTrigger.js +90 -0
  114. package/dist-es/mega-menu/MegaMenuTrigger.js.map +1 -0
  115. package/dist-es/mega-menu/useMegaMenu.js +13 -0
  116. package/dist-es/mega-menu/useMegaMenu.js.map +1 -0
  117. package/dist-es/mega-menu/useMegaMenuKeyboard.js +205 -0
  118. package/dist-es/mega-menu/useMegaMenuKeyboard.js.map +1 -0
  119. package/dist-es/side-panel/SidePanel.css.js +1 -1
  120. package/dist-es/side-panel/SidePanel.js +110 -69
  121. package/dist-es/side-panel/SidePanel.js.map +1 -1
  122. package/dist-es/side-panel/SidePanelCloseButton.js +36 -0
  123. package/dist-es/side-panel/SidePanelCloseButton.js.map +1 -0
  124. package/dist-es/side-panel/SidePanelContent.css.js +1 -1
  125. package/dist-es/side-panel/SidePanelContent.js +4 -24
  126. package/dist-es/side-panel/SidePanelContent.js.map +1 -1
  127. package/dist-es/side-panel/SidePanelHeader.css.js +1 -1
  128. package/dist-es/side-panel/SidePanelHeader.js.map +1 -1
  129. package/dist-es/side-panel/SidePanelProvider.js +12 -5
  130. package/dist-es/side-panel/SidePanelProvider.js.map +1 -1
  131. package/dist-es/side-panel/SidePanelTitle.css.js +1 -1
  132. package/dist-es/side-panel/SidePanelTitle.js +1 -0
  133. package/dist-es/side-panel/SidePanelTitle.js.map +1 -1
  134. package/dist-es/side-panel/SidePanelTrigger.js +5 -5
  135. package/dist-es/side-panel/SidePanelTrigger.js.map +1 -1
  136. package/dist-es/side-panel/internal/SidePanelContext.js +2 -1
  137. package/dist-es/side-panel/internal/SidePanelContext.js.map +1 -1
  138. package/dist-es/side-panel/internal/useIsScrollable.js +48 -0
  139. package/dist-es/side-panel/internal/useIsScrollable.js.map +1 -0
  140. package/dist-es/side-panel/internal/useSidePanelTabOrder.js +212 -0
  141. package/dist-es/side-panel/internal/useSidePanelTabOrder.js.map +1 -0
  142. package/dist-es/side-panel/useSidePanel.js +9 -7
  143. package/dist-es/side-panel/useSidePanel.js.map +1 -1
  144. package/dist-es/tree/Tree.js +8 -5
  145. package/dist-es/tree/Tree.js.map +1 -1
  146. package/dist-es/tree/TreeContext.js.map +1 -1
  147. package/dist-es/tree/TreeNode.js +20 -16
  148. package/dist-es/tree/TreeNode.js.map +1 -1
  149. package/dist-es/tree/TreeNodeTrigger.js +4 -3
  150. package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
  151. package/dist-es/tree/treeModel.js +57 -0
  152. package/dist-es/tree/treeModel.js.map +1 -0
  153. package/dist-es/tree/useTree.js +49 -43
  154. package/dist-es/tree/useTree.js.map +1 -1
  155. package/dist-types/index.d.ts +1 -2
  156. package/dist-types/mega-menu/MegaMenu.d.ts +27 -0
  157. package/dist-types/mega-menu/MegaMenuContent.d.ts +8 -0
  158. package/dist-types/mega-menu/MegaMenuContext.d.ts +29 -0
  159. package/dist-types/mega-menu/MegaMenuGroup.d.ts +8 -0
  160. package/dist-types/mega-menu/MegaMenuHeader.d.ts +8 -0
  161. package/dist-types/mega-menu/MegaMenuItem.d.ts +12 -0
  162. package/dist-types/mega-menu/MegaMenuItemContent.d.ts +8 -0
  163. package/dist-types/mega-menu/MegaMenuPanel.d.ts +8 -0
  164. package/dist-types/mega-menu/MegaMenuSection.d.ts +8 -0
  165. package/dist-types/mega-menu/MegaMenuTrigger.d.ts +8 -0
  166. package/dist-types/mega-menu/index.d.ts +9 -0
  167. package/dist-types/mega-menu/useMegaMenu.d.ts +6 -0
  168. package/dist-types/mega-menu/useMegaMenuKeyboard.d.ts +30 -0
  169. package/dist-types/side-panel/SidePanel.d.ts +3 -4
  170. package/dist-types/side-panel/SidePanelCloseButton.d.ts +2 -0
  171. package/dist-types/side-panel/SidePanelContent.d.ts +4 -3
  172. package/dist-types/side-panel/SidePanelHeader.d.ts +4 -3
  173. package/dist-types/side-panel/SidePanelTitle.d.ts +1 -2
  174. package/dist-types/side-panel/SidePanelTrigger.d.ts +3 -5
  175. package/dist-types/side-panel/index.d.ts +1 -0
  176. package/dist-types/side-panel/internal/SidePanelContext.d.ts +4 -0
  177. package/dist-types/side-panel/internal/index.d.ts +2 -0
  178. package/dist-types/side-panel/internal/useIsScrollable.d.ts +2 -0
  179. package/dist-types/side-panel/internal/useSidePanelTabOrder.d.ts +7 -0
  180. package/dist-types/side-panel/useSidePanel.d.ts +32 -6
  181. package/dist-types/tree/TreeContext.d.ts +7 -1
  182. package/dist-types/tree/treeModel.d.ts +24 -0
  183. package/dist-types/tree/useTree.d.ts +3 -14
  184. package/package.json +2 -4
  185. package/dist-cjs/rating/Rating.css.js +0 -6
  186. package/dist-cjs/rating/Rating.css.js.map +0 -1
  187. package/dist-cjs/rating/Rating.js +0 -132
  188. package/dist-cjs/rating/Rating.js.map +0 -1
  189. package/dist-cjs/rating/RatingItem.css.js +0 -6
  190. package/dist-cjs/rating/RatingItem.css.js.map +0 -1
  191. package/dist-cjs/rating/RatingItem.js +0 -70
  192. package/dist-cjs/rating/RatingItem.js.map +0 -1
  193. package/dist-cjs/tabs-next/TabBar.css.js +0 -6
  194. package/dist-cjs/tabs-next/TabBar.css.js.map +0 -1
  195. package/dist-cjs/tabs-next/TabBar.js +0 -41
  196. package/dist-cjs/tabs-next/TabBar.js.map +0 -1
  197. package/dist-cjs/tabs-next/TabListLayoutContext.js +0 -13
  198. package/dist-cjs/tabs-next/TabListLayoutContext.js.map +0 -1
  199. package/dist-cjs/tabs-next/TabListNext.css.js +0 -6
  200. package/dist-cjs/tabs-next/TabListNext.css.js.map +0 -1
  201. package/dist-cjs/tabs-next/TabListNext.js +0 -271
  202. package/dist-cjs/tabs-next/TabListNext.js.map +0 -1
  203. package/dist-cjs/tabs-next/TabNext.css.js +0 -6
  204. package/dist-cjs/tabs-next/TabNext.css.js.map +0 -1
  205. package/dist-cjs/tabs-next/TabNext.js +0 -213
  206. package/dist-cjs/tabs-next/TabNext.js.map +0 -1
  207. package/dist-cjs/tabs-next/TabNextAction.js +0 -58
  208. package/dist-cjs/tabs-next/TabNextAction.js.map +0 -1
  209. package/dist-cjs/tabs-next/TabNextContext.js +0 -23
  210. package/dist-cjs/tabs-next/TabNextContext.js.map +0 -1
  211. package/dist-cjs/tabs-next/TabNextPanel.css.js +0 -6
  212. package/dist-cjs/tabs-next/TabNextPanel.css.js.map +0 -1
  213. package/dist-cjs/tabs-next/TabNextPanel.js +0 -92
  214. package/dist-cjs/tabs-next/TabNextPanel.js.map +0 -1
  215. package/dist-cjs/tabs-next/TabNextTrigger.css.js +0 -6
  216. package/dist-cjs/tabs-next/TabNextTrigger.css.js.map +0 -1
  217. package/dist-cjs/tabs-next/TabNextTrigger.js +0 -180
  218. package/dist-cjs/tabs-next/TabNextTrigger.js.map +0 -1
  219. package/dist-cjs/tabs-next/TabOverflowList.css.js +0 -6
  220. package/dist-cjs/tabs-next/TabOverflowList.css.js.map +0 -1
  221. package/dist-cjs/tabs-next/TabOverflowList.js +0 -237
  222. package/dist-cjs/tabs-next/TabOverflowList.js.map +0 -1
  223. package/dist-cjs/tabs-next/TabSlot.js +0 -30
  224. package/dist-cjs/tabs-next/TabSlot.js.map +0 -1
  225. package/dist-cjs/tabs-next/TabSlotRegistryContext.js +0 -16
  226. package/dist-cjs/tabs-next/TabSlotRegistryContext.js.map +0 -1
  227. package/dist-cjs/tabs-next/TabsNext.css.js +0 -6
  228. package/dist-cjs/tabs-next/TabsNext.css.js.map +0 -1
  229. package/dist-cjs/tabs-next/TabsNext.js +0 -195
  230. package/dist-cjs/tabs-next/TabsNext.js.map +0 -1
  231. package/dist-cjs/tabs-next/TabsNextContext.js +0 -47
  232. package/dist-cjs/tabs-next/TabsNextContext.js.map +0 -1
  233. package/dist-cjs/tabs-next/domUtils.js +0 -13
  234. package/dist-cjs/tabs-next/domUtils.js.map +0 -1
  235. package/dist-cjs/tabs-next/hooks/overflowMath.js +0 -86
  236. package/dist-cjs/tabs-next/hooks/overflowMath.js.map +0 -1
  237. package/dist-cjs/tabs-next/hooks/useCollection.js +0 -197
  238. package/dist-cjs/tabs-next/hooks/useCollection.js.map +0 -1
  239. package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js +0 -64
  240. package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js.map +0 -1
  241. package/dist-cjs/tabs-next/hooks/useOverflow.js +0 -266
  242. package/dist-cjs/tabs-next/hooks/useOverflow.js.map +0 -1
  243. package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js +0 -99
  244. package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js.map +0 -1
  245. package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js +0 -60
  246. package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js.map +0 -1
  247. package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js +0 -92
  248. package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js.map +0 -1
  249. package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js +0 -200
  250. package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js.map +0 -1
  251. package/dist-cjs/tabs-next/hooks/useTabListRecovery.js +0 -76
  252. package/dist-cjs/tabs-next/hooks/useTabListRecovery.js.map +0 -1
  253. package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js +0 -165
  254. package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js.map +0 -1
  255. package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js +0 -80
  256. package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js.map +0 -1
  257. package/dist-cjs/tabs-next/widthMeasurement.js +0 -42
  258. package/dist-cjs/tabs-next/widthMeasurement.js.map +0 -1
  259. package/dist-es/rating/Rating.css.js +0 -4
  260. package/dist-es/rating/Rating.css.js.map +0 -1
  261. package/dist-es/rating/Rating.js +0 -130
  262. package/dist-es/rating/Rating.js.map +0 -1
  263. package/dist-es/rating/RatingItem.css.js +0 -4
  264. package/dist-es/rating/RatingItem.css.js.map +0 -1
  265. package/dist-es/rating/RatingItem.js +0 -68
  266. package/dist-es/rating/RatingItem.js.map +0 -1
  267. package/dist-es/tabs-next/TabBar.css.js +0 -4
  268. package/dist-es/tabs-next/TabBar.css.js.map +0 -1
  269. package/dist-es/tabs-next/TabBar.js +0 -39
  270. package/dist-es/tabs-next/TabBar.js.map +0 -1
  271. package/dist-es/tabs-next/TabListLayoutContext.js +0 -10
  272. package/dist-es/tabs-next/TabListLayoutContext.js.map +0 -1
  273. package/dist-es/tabs-next/TabListNext.css.js +0 -4
  274. package/dist-es/tabs-next/TabListNext.css.js.map +0 -1
  275. package/dist-es/tabs-next/TabListNext.js +0 -269
  276. package/dist-es/tabs-next/TabListNext.js.map +0 -1
  277. package/dist-es/tabs-next/TabNext.css.js +0 -4
  278. package/dist-es/tabs-next/TabNext.css.js.map +0 -1
  279. package/dist-es/tabs-next/TabNext.js +0 -211
  280. package/dist-es/tabs-next/TabNext.js.map +0 -1
  281. package/dist-es/tabs-next/TabNextAction.js +0 -56
  282. package/dist-es/tabs-next/TabNextAction.js.map +0 -1
  283. package/dist-es/tabs-next/TabNextContext.js +0 -20
  284. package/dist-es/tabs-next/TabNextContext.js.map +0 -1
  285. package/dist-es/tabs-next/TabNextPanel.css.js +0 -4
  286. package/dist-es/tabs-next/TabNextPanel.css.js.map +0 -1
  287. package/dist-es/tabs-next/TabNextPanel.js +0 -90
  288. package/dist-es/tabs-next/TabNextPanel.js.map +0 -1
  289. package/dist-es/tabs-next/TabNextTrigger.css.js +0 -4
  290. package/dist-es/tabs-next/TabNextTrigger.css.js.map +0 -1
  291. package/dist-es/tabs-next/TabNextTrigger.js +0 -178
  292. package/dist-es/tabs-next/TabNextTrigger.js.map +0 -1
  293. package/dist-es/tabs-next/TabOverflowList.css.js +0 -4
  294. package/dist-es/tabs-next/TabOverflowList.css.js.map +0 -1
  295. package/dist-es/tabs-next/TabOverflowList.js +0 -235
  296. package/dist-es/tabs-next/TabOverflowList.js.map +0 -1
  297. package/dist-es/tabs-next/TabSlot.js +0 -28
  298. package/dist-es/tabs-next/TabSlot.js.map +0 -1
  299. package/dist-es/tabs-next/TabSlotRegistryContext.js +0 -13
  300. package/dist-es/tabs-next/TabSlotRegistryContext.js.map +0 -1
  301. package/dist-es/tabs-next/TabsNext.css.js +0 -4
  302. package/dist-es/tabs-next/TabsNext.css.js.map +0 -1
  303. package/dist-es/tabs-next/TabsNext.js +0 -193
  304. package/dist-es/tabs-next/TabsNext.js.map +0 -1
  305. package/dist-es/tabs-next/TabsNextContext.js +0 -44
  306. package/dist-es/tabs-next/TabsNextContext.js.map +0 -1
  307. package/dist-es/tabs-next/domUtils.js +0 -11
  308. package/dist-es/tabs-next/domUtils.js.map +0 -1
  309. package/dist-es/tabs-next/hooks/overflowMath.js +0 -82
  310. package/dist-es/tabs-next/hooks/overflowMath.js.map +0 -1
  311. package/dist-es/tabs-next/hooks/useCollection.js +0 -195
  312. package/dist-es/tabs-next/hooks/useCollection.js.map +0 -1
  313. package/dist-es/tabs-next/hooks/useFocusWithRetry.js +0 -62
  314. package/dist-es/tabs-next/hooks/useFocusWithRetry.js.map +0 -1
  315. package/dist-es/tabs-next/hooks/useOverflow.js +0 -264
  316. package/dist-es/tabs-next/hooks/useOverflow.js.map +0 -1
  317. package/dist-es/tabs-next/hooks/useOverflowLayoutState.js +0 -97
  318. package/dist-es/tabs-next/hooks/useOverflowLayoutState.js.map +0 -1
  319. package/dist-es/tabs-next/hooks/useOverflowSelectionState.js +0 -58
  320. package/dist-es/tabs-next/hooks/useOverflowSelectionState.js.map +0 -1
  321. package/dist-es/tabs-next/hooks/useRenderedTabWidth.js +0 -90
  322. package/dist-es/tabs-next/hooks/useRenderedTabWidth.js.map +0 -1
  323. package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js +0 -198
  324. package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js.map +0 -1
  325. package/dist-es/tabs-next/hooks/useTabListRecovery.js +0 -74
  326. package/dist-es/tabs-next/hooks/useTabListRecovery.js.map +0 -1
  327. package/dist-es/tabs-next/hooks/useTabRemovalHandler.js +0 -163
  328. package/dist-es/tabs-next/hooks/useTabRemovalHandler.js.map +0 -1
  329. package/dist-es/tabs-next/hooks/useTabSelectionFocus.js +0 -78
  330. package/dist-es/tabs-next/hooks/useTabSelectionFocus.js.map +0 -1
  331. package/dist-es/tabs-next/widthMeasurement.js +0 -36
  332. package/dist-es/tabs-next/widthMeasurement.js.map +0 -1
  333. package/dist-types/rating/Rating.d.ts +0 -48
  334. package/dist-types/rating/RatingItem.d.ts +0 -47
  335. package/dist-types/rating/index.d.ts +0 -1
  336. package/dist-types/tabs-next/TabBar.d.ts +0 -12
  337. package/dist-types/tabs-next/TabListLayoutContext.d.ts +0 -9
  338. package/dist-types/tabs-next/TabListNext.d.ts +0 -12
  339. package/dist-types/tabs-next/TabNext.d.ts +0 -12
  340. package/dist-types/tabs-next/TabNextAction.d.ts +0 -4
  341. package/dist-types/tabs-next/TabNextContext.d.ts +0 -12
  342. package/dist-types/tabs-next/TabNextPanel.d.ts +0 -9
  343. package/dist-types/tabs-next/TabNextTrigger.d.ts +0 -4
  344. package/dist-types/tabs-next/TabOverflowList.d.ts +0 -10
  345. package/dist-types/tabs-next/TabSlot.d.ts +0 -6
  346. package/dist-types/tabs-next/TabSlotRegistryContext.d.ts +0 -5
  347. package/dist-types/tabs-next/TabsNext.d.ts +0 -18
  348. package/dist-types/tabs-next/TabsNextContext.d.ts +0 -43
  349. package/dist-types/tabs-next/domUtils.d.ts +0 -1
  350. package/dist-types/tabs-next/hooks/overflowMath.d.ts +0 -18
  351. package/dist-types/tabs-next/hooks/useCollection.d.ts +0 -30
  352. package/dist-types/tabs-next/hooks/useFocusWithRetry.d.ts +0 -9
  353. package/dist-types/tabs-next/hooks/useOverflow.d.ts +0 -11
  354. package/dist-types/tabs-next/hooks/useOverflowLayoutState.d.ts +0 -13
  355. package/dist-types/tabs-next/hooks/useOverflowSelectionState.d.ts +0 -13
  356. package/dist-types/tabs-next/hooks/useRenderedTabWidth.d.ts +0 -12
  357. package/dist-types/tabs-next/hooks/useRenderedTabsRegistry.d.ts +0 -12
  358. package/dist-types/tabs-next/hooks/useTabListRecovery.d.ts +0 -12
  359. package/dist-types/tabs-next/hooks/useTabRemovalHandler.d.ts +0 -32
  360. package/dist-types/tabs-next/hooks/useTabSelectionFocus.d.ts +0 -15
  361. package/dist-types/tabs-next/index.d.ts +0 -7
  362. package/dist-types/tabs-next/widthMeasurement.d.ts +0 -5
@@ -39,6 +39,8 @@ const TreeNodeTrigger = forwardRef(function TreeNodeTrigger2(props, ref) {
39
39
  expanded,
40
40
  disabled,
41
41
  id,
42
+ nodeRef,
43
+ setNodeRef,
42
44
  selected,
43
45
  indeterminate,
44
46
  nodeChildren
@@ -51,7 +53,6 @@ const TreeNodeTrigger = forwardRef(function TreeNodeTrigger2(props, ref) {
51
53
  tabbableNodeId,
52
54
  registerElement
53
55
  } = useTreeContext();
54
- const nodeRef = useRef(null);
55
56
  const triggerContentRef = useForkRef(useRef(null), ref);
56
57
  const wasMouseDownRef = useRef(false);
57
58
  const [focusVisible, setFocusVisible] = useState(false);
@@ -61,7 +62,7 @@ const TreeNodeTrigger = forwardRef(function TreeNodeTrigger2(props, ref) {
61
62
  if (nodeRef.current) {
62
63
  return registerElement(value, nodeRef.current);
63
64
  }
64
- }, [value, registerElement]);
65
+ }, [value, registerElement, nodeRef]);
65
66
  const handleClick = (event) => {
66
67
  onClick == null ? void 0 : onClick(event);
67
68
  if (disabled) return;
@@ -95,7 +96,7 @@ const TreeNodeTrigger = forwardRef(function TreeNodeTrigger2(props, ref) {
95
96
  return /* @__PURE__ */ jsxs(
96
97
  "li",
97
98
  {
98
- ref: nodeRef,
99
+ ref: setNodeRef,
99
100
  id,
100
101
  role: "treeitem",
101
102
  "aria-expanded": hasChildren ? expanded : void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"TreeNodeTrigger.js","sources":["../src/tree/TreeNodeTrigger.tsx"],"sourcesContent":["import { CheckboxIcon, makePrefixer, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type FocusEvent,\n forwardRef,\n type MouseEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useTreeContext, useTreeNodeContext } from \"./TreeContext\";\nimport { TreeNodeExpansionIcon } from \"./TreeNodeExpansionIcon\";\nimport treeNodeTriggerCss from \"./TreeNodeTrigger.css\";\n\nexport interface TreeNodeTriggerProps extends ComponentPropsWithoutRef<\"li\"> {}\n\nconst withBaseName = makePrefixer(\"saltTreeNodeTrigger\");\nconst withNodeBaseName = makePrefixer(\"saltTreeNode\");\n\n/**\n * The forwarded ref points to the inner trigger content span (for tooltip positioning),\n * while the <li> handles focus, ARIA, and event handling.\n */\nexport const TreeNodeTrigger = forwardRef<\n HTMLSpanElement,\n TreeNodeTriggerProps\n>(function TreeNodeTrigger(props, ref) {\n const {\n className,\n children,\n style,\n onClick,\n onFocus,\n onBlur,\n onMouseDown,\n onKeyDown,\n ...rest\n } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node-trigger\",\n css: treeNodeTriggerCss,\n window: targetWindow,\n });\n\n const nodeContext = useTreeNodeContext();\n if (!nodeContext) {\n throw new Error(\"TreeNodeTrigger must be used within a TreeNode\");\n }\n\n const {\n value,\n level,\n hasChildren,\n expanded,\n disabled,\n id,\n selected,\n indeterminate,\n nodeChildren,\n } = nodeContext;\n\n const {\n multiselect,\n activeNode,\n setActiveNode,\n select,\n tabbableNodeId,\n registerElement,\n } = useTreeContext();\n\n const nodeRef = useRef<HTMLLIElement>(null);\n const triggerContentRef = useForkRef(useRef<HTMLSpanElement>(null), ref);\n const wasMouseDownRef = useRef(false);\n const [focusVisible, setFocusVisible] = useState(false);\n\n const isActive = activeNode === value;\n\n const isTabbable = tabbableNodeId === value;\n\n useEffect(() => {\n if (nodeRef.current) {\n return registerElement(value, nodeRef.current);\n }\n }, [value, registerElement]);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n onClick?.(event);\n if (disabled) return;\n const target = event.target as HTMLElement;\n if (target.closest(\".saltTreeNodeExpansionIcon\")) return;\n const nestedTreeItem = target.closest('[role=\"treeitem\"]');\n if (nestedTreeItem && nestedTreeItem !== nodeRef.current) {\n return;\n }\n setActiveNode(value);\n select(event, value);\n };\n\n const handleFocus = (event: FocusEvent<HTMLLIElement>) => {\n if (event.target !== event.currentTarget) return;\n onFocus?.(event);\n if (!wasMouseDownRef.current) {\n setFocusVisible(true);\n }\n wasMouseDownRef.current = false;\n setActiveNode(value);\n };\n\n const handleBlur = (event: FocusEvent<HTMLLIElement>) => {\n if (event.target !== event.currentTarget) return;\n onBlur?.(event);\n setFocusVisible(false);\n };\n\n const handleMouseDown = (event: MouseEvent<HTMLLIElement>) => {\n wasMouseDownRef.current = true;\n onMouseDown?.(event);\n };\n\n return (\n <li\n ref={nodeRef}\n id={id}\n role=\"treeitem\"\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={multiselect ? undefined : selected}\n aria-checked={\n multiselect ? (indeterminate ? \"mixed\" : selected) : undefined\n }\n aria-level={level}\n aria-disabled={disabled || undefined}\n tabIndex={isTabbable ? 0 : -1}\n className={clsx(\n withNodeBaseName(),\n {\n [withNodeBaseName(\"expanded\")]: expanded,\n [withNodeBaseName(\"selected\")]: selected && !multiselect,\n [withNodeBaseName(\"active\")]: isActive,\n [withNodeBaseName(\"disabled\")]: disabled,\n [withNodeBaseName(\"hasChildren\")]: hasChildren,\n [withNodeBaseName(\"focusVisible\")]: focusVisible,\n },\n className,\n )}\n style={\n {\n \"--saltTreeNode-level\": level,\n ...style,\n } as CSSProperties\n }\n onClick={handleClick}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onMouseDown={handleMouseDown}\n onKeyDown={onKeyDown}\n {...rest}\n >\n <span ref={triggerContentRef} className={withBaseName()}>\n <TreeNodeExpansionIcon />\n {multiselect && (\n <CheckboxIcon\n checked={selected}\n indeterminate={indeterminate}\n disabled={disabled}\n className={withNodeBaseName(\"checkbox\")}\n />\n )}\n {children}\n </span>\n\n {hasChildren && expanded && (\n <ul role=\"group\" className={withNodeBaseName(\"group\")}>\n {nodeChildren}\n </ul>\n )}\n </li>\n );\n});\n"],"names":["TreeNodeTrigger","treeNodeTriggerCss"],"mappings":"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"}
1
+ {"version":3,"file":"TreeNodeTrigger.js","sources":["../src/tree/TreeNodeTrigger.tsx"],"sourcesContent":["import { CheckboxIcon, makePrefixer, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type FocusEvent,\n forwardRef,\n type MouseEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useTreeContext, useTreeNodeContext } from \"./TreeContext\";\nimport { TreeNodeExpansionIcon } from \"./TreeNodeExpansionIcon\";\nimport treeNodeTriggerCss from \"./TreeNodeTrigger.css\";\n\nexport interface TreeNodeTriggerProps extends ComponentPropsWithoutRef<\"li\"> {}\n\nconst withBaseName = makePrefixer(\"saltTreeNodeTrigger\");\nconst withNodeBaseName = makePrefixer(\"saltTreeNode\");\n\n/**\n * The forwarded ref points to the inner trigger content span (for tooltip positioning),\n * while the <li> handles focus, ARIA, and event handling.\n */\nexport const TreeNodeTrigger = forwardRef<\n HTMLSpanElement,\n TreeNodeTriggerProps\n>(function TreeNodeTrigger(props, ref) {\n const {\n className,\n children,\n style,\n onClick,\n onFocus,\n onBlur,\n onMouseDown,\n onKeyDown,\n ...rest\n } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node-trigger\",\n css: treeNodeTriggerCss,\n window: targetWindow,\n });\n\n const nodeContext = useTreeNodeContext();\n if (!nodeContext) {\n throw new Error(\"TreeNodeTrigger must be used within a TreeNode\");\n }\n\n const {\n value,\n level,\n hasChildren,\n expanded,\n disabled,\n id,\n nodeRef,\n setNodeRef,\n selected,\n indeterminate,\n nodeChildren,\n } = nodeContext;\n\n const {\n multiselect,\n activeNode,\n setActiveNode,\n select,\n tabbableNodeId,\n registerElement,\n } = useTreeContext();\n\n const triggerContentRef = useForkRef(useRef<HTMLSpanElement>(null), ref);\n const wasMouseDownRef = useRef(false);\n const [focusVisible, setFocusVisible] = useState(false);\n\n const isActive = activeNode === value;\n\n const isTabbable = tabbableNodeId === value;\n\n useEffect(() => {\n if (nodeRef.current) {\n return registerElement(value, nodeRef.current);\n }\n }, [value, registerElement, nodeRef]);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n onClick?.(event);\n if (disabled) return;\n const target = event.target as HTMLElement;\n if (target.closest(\".saltTreeNodeExpansionIcon\")) return;\n const nestedTreeItem = target.closest('[role=\"treeitem\"]');\n if (nestedTreeItem && nestedTreeItem !== nodeRef.current) {\n return;\n }\n setActiveNode(value);\n select(event, value);\n };\n\n const handleFocus = (event: FocusEvent<HTMLLIElement>) => {\n if (event.target !== event.currentTarget) return;\n onFocus?.(event);\n if (!wasMouseDownRef.current) {\n setFocusVisible(true);\n }\n wasMouseDownRef.current = false;\n setActiveNode(value);\n };\n\n const handleBlur = (event: FocusEvent<HTMLLIElement>) => {\n if (event.target !== event.currentTarget) return;\n onBlur?.(event);\n setFocusVisible(false);\n };\n\n const handleMouseDown = (event: MouseEvent<HTMLLIElement>) => {\n wasMouseDownRef.current = true;\n onMouseDown?.(event);\n };\n\n return (\n <li\n ref={setNodeRef}\n id={id}\n role=\"treeitem\"\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={multiselect ? undefined : selected}\n aria-checked={\n multiselect ? (indeterminate ? \"mixed\" : selected) : undefined\n }\n aria-level={level}\n aria-disabled={disabled || undefined}\n tabIndex={isTabbable ? 0 : -1}\n className={clsx(\n withNodeBaseName(),\n {\n [withNodeBaseName(\"expanded\")]: expanded,\n [withNodeBaseName(\"selected\")]: selected && !multiselect,\n [withNodeBaseName(\"active\")]: isActive,\n [withNodeBaseName(\"disabled\")]: disabled,\n [withNodeBaseName(\"hasChildren\")]: hasChildren,\n [withNodeBaseName(\"focusVisible\")]: focusVisible,\n },\n className,\n )}\n style={\n {\n \"--saltTreeNode-level\": level,\n ...style,\n } as CSSProperties\n }\n onClick={handleClick}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onMouseDown={handleMouseDown}\n onKeyDown={onKeyDown}\n {...rest}\n >\n <span ref={triggerContentRef} className={withBaseName()}>\n <TreeNodeExpansionIcon />\n {multiselect && (\n <CheckboxIcon\n checked={selected}\n indeterminate={indeterminate}\n disabled={disabled}\n className={withNodeBaseName(\"checkbox\")}\n />\n )}\n {children}\n </span>\n\n {hasChildren && expanded && (\n <ul role=\"group\" className={withNodeBaseName(\"group\")}>\n {nodeChildren}\n </ul>\n )}\n </li>\n );\n});\n"],"names":["TreeNodeTrigger","treeNodeTriggerCss"],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { Children, isValidElement, Fragment } from 'react';
2
+
3
+ function isFragmentElement(child) {
4
+ return isValidElement(child) && child.type === Fragment;
5
+ }
6
+ function isTreeNodeElement(child) {
7
+ return isValidElement(child) && typeof child.props.value === "string";
8
+ }
9
+ function flattenTreeNodeChildren(children) {
10
+ const flattenedChildren = [];
11
+ Children.forEach(children, (child) => {
12
+ if (isFragmentElement(child)) {
13
+ flattenedChildren.push(...flattenTreeNodeChildren(child.props.children));
14
+ } else if (child !== null && child !== void 0 && typeof child !== "boolean") {
15
+ flattenedChildren.push(child);
16
+ }
17
+ });
18
+ return flattenedChildren;
19
+ }
20
+ function getTreeNodeElements(children) {
21
+ return flattenTreeNodeChildren(children).filter(isTreeNodeElement);
22
+ }
23
+ function buildTreeModel(children) {
24
+ const nodes = /* @__PURE__ */ new Map();
25
+ const rootValues = [];
26
+ const childrenOf = /* @__PURE__ */ new Map();
27
+ function traverse(reactChildren, parentValue, parentDisabled = false) {
28
+ const treeNodeChildren = getTreeNodeElements(reactChildren);
29
+ const siblingValues = [];
30
+ for (const child of treeNodeChildren) {
31
+ const value = child.props.value;
32
+ const childTreeNodes = getTreeNodeElements(child.props.children);
33
+ const hasChildren = childTreeNodes.length > 0;
34
+ const disabled = parentDisabled || Boolean(child.props.disabled);
35
+ nodes.set(value, {
36
+ value,
37
+ parentValue,
38
+ hasChildren,
39
+ disabled
40
+ });
41
+ siblingValues.push(value);
42
+ if (hasChildren) {
43
+ traverse(child.props.children, value, disabled);
44
+ }
45
+ }
46
+ if (parentValue !== void 0) {
47
+ childrenOf.set(parentValue, siblingValues);
48
+ } else {
49
+ rootValues.push(...siblingValues);
50
+ }
51
+ }
52
+ traverse(children);
53
+ return { nodes, rootValues, childrenOf };
54
+ }
55
+
56
+ export { buildTreeModel, flattenTreeNodeChildren, isTreeNodeElement };
57
+ //# sourceMappingURL=treeModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeModel.js","sources":["../src/tree/treeModel.ts"],"sourcesContent":["import {\n Children,\n Fragment,\n isValidElement,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nexport interface TreeNodeMeta {\n value: string;\n parentValue: string | undefined;\n hasChildren: boolean;\n disabled: boolean;\n}\n\nexport interface TreeModel {\n /** All nodes indexed by value */\n nodes: Map<string, TreeNodeMeta>;\n /** Ordered list of root node values */\n rootValues: string[];\n /** Maps parent value to ordered list of child values */\n childrenOf: Map<string, string[]>;\n}\n\ninterface TreeNodeElementProps {\n value: string;\n disabled?: boolean;\n children?: ReactNode;\n}\n\nfunction isFragmentElement(\n child: ReactNode,\n): child is ReactElement<{ children?: ReactNode }> {\n return (\n isValidElement<{ children?: ReactNode }>(child) && child.type === Fragment\n );\n}\n\nexport function isTreeNodeElement(\n child: ReactNode,\n): child is ReactElement<TreeNodeElementProps> {\n return (\n isValidElement<TreeNodeElementProps>(child) &&\n typeof child.props.value === \"string\"\n );\n}\n\nexport function flattenTreeNodeChildren(children: ReactNode): ReactNode[] {\n const flattenedChildren: ReactNode[] = [];\n\n Children.forEach(children, (child) => {\n if (isFragmentElement(child)) {\n flattenedChildren.push(...flattenTreeNodeChildren(child.props.children));\n } else if (\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\"\n ) {\n flattenedChildren.push(child);\n }\n });\n\n return flattenedChildren;\n}\n\nfunction getTreeNodeElements(\n children: ReactNode,\n): ReactElement<TreeNodeElementProps>[] {\n return flattenTreeNodeChildren(children).filter(isTreeNodeElement);\n}\n\nexport function buildTreeModel(children: ReactNode): TreeModel {\n const nodes = new Map<string, TreeNodeMeta>();\n const rootValues: string[] = [];\n const childrenOf = new Map<string, string[]>();\n\n function traverse(\n reactChildren: ReactNode,\n parentValue?: string,\n parentDisabled = false,\n ): void {\n const treeNodeChildren = getTreeNodeElements(reactChildren);\n const siblingValues: string[] = [];\n\n for (const child of treeNodeChildren) {\n const value = child.props.value;\n const childTreeNodes = getTreeNodeElements(child.props.children);\n const hasChildren = childTreeNodes.length > 0;\n const disabled = parentDisabled || Boolean(child.props.disabled);\n\n nodes.set(value, {\n value,\n parentValue,\n hasChildren,\n disabled,\n });\n\n siblingValues.push(value);\n\n if (hasChildren) {\n traverse(child.props.children, value, disabled);\n }\n }\n\n if (parentValue !== undefined) {\n childrenOf.set(parentValue, siblingValues);\n } else {\n rootValues.push(...siblingValues);\n }\n }\n\n traverse(children);\n\n return { nodes, rootValues, childrenOf };\n}\n"],"names":[],"mappings":";;AA8BA,SAAS,kBACP,KAAA,EACiD;AACjD,EAAA,OACE,cAAA,CAAyC,KAAK,CAAA,IAAK,KAAA,CAAM,IAAA,KAAS,QAAA;AAEtE;AAEO,SAAS,kBACd,KAAA,EAC6C;AAC7C,EAAA,OACE,eAAqC,KAAK,CAAA,IAC1C,OAAO,KAAA,CAAM,MAAM,KAAA,KAAU,QAAA;AAEjC;AAEO,SAAS,wBAAwB,QAAA,EAAkC;AACxE,EAAA,MAAM,oBAAiC,EAAC;AAExC,EAAA,QAAA,CAAS,OAAA,CAAQ,QAAA,EAAU,CAAC,KAAA,KAAU;AACpC,IAAA,IAAI,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAC5B,MAAA,iBAAA,CAAkB,KAAK,GAAG,uBAAA,CAAwB,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,IACzE,WACE,KAAA,KAAU,IAAA,IACV,UAAU,MAAA,IACV,OAAO,UAAU,SAAA,EACjB;AACA,MAAA,iBAAA,CAAkB,KAAK,KAAK,CAAA;AAAA,IAC9B;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,iBAAA;AACT;AAEA,SAAS,oBACP,QAAA,EACsC;AACtC,EAAA,OAAO,uBAAA,CAAwB,QAAQ,CAAA,CAAE,MAAA,CAAO,iBAAiB,CAAA;AACnE;AAEO,SAAS,eAAe,QAAA,EAAgC;AAC7D,EAAA,MAAM,KAAA,uBAAY,GAAA,EAA0B;AAC5C,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAsB;AAE7C,EAAA,SAAS,QAAA,CACP,aAAA,EACA,WAAA,EACA,cAAA,GAAiB,KAAA,EACX;AACN,IAAA,MAAM,gBAAA,GAAmB,oBAAoB,aAAa,CAAA;AAC1D,IAAA,MAAM,gBAA0B,EAAC;AAEjC,IAAA,KAAA,MAAW,SAAS,gBAAA,EAAkB;AACpC,MAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,KAAA;AAC1B,MAAA,MAAM,cAAA,GAAiB,mBAAA,CAAoB,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AAC/D,MAAA,MAAM,WAAA,GAAc,eAAe,MAAA,GAAS,CAAA;AAC5C,MAAA,MAAM,QAAA,GAAW,cAAA,IAAkB,OAAA,CAAQ,KAAA,CAAM,MAAM,QAAQ,CAAA;AAE/D,MAAA,KAAA,CAAM,IAAI,KAAA,EAAO;AAAA,QACf,KAAA;AAAA,QACA,WAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AAExB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,QAAA,CAAS,KAAA,CAAM,KAAA,CAAM,QAAA,EAAU,KAAA,EAAO,QAAQ,CAAA;AAAA,MAChD;AAAA,IACF;AAEA,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,UAAA,CAAW,GAAA,CAAI,aAAa,aAAa,CAAA;AAAA,IAC3C,CAAA,MAAO;AACL,MAAA,UAAA,CAAW,IAAA,CAAK,GAAG,aAAa,CAAA;AAAA,IAClC;AAAA,EACF;AAEA,EAAA,QAAA,CAAS,QAAQ,CAAA;AAEjB,EAAA,OAAO,EAAE,KAAA,EAAO,UAAA,EAAY,UAAA,EAAW;AACzC;;;;"}
@@ -1,38 +1,12 @@
1
1
  import { useControlled } from '@salt-ds/core';
2
- import { useMemo, useState, useRef, useCallback, Children, isValidElement } from 'react';
2
+ import { useMemo, useRef, useCallback, useState, useEffect } from 'react';
3
+ import { buildTreeModel } from './treeModel.js';
3
4
 
4
- function buildTreeModel(children) {
5
- const nodes = /* @__PURE__ */ new Map();
6
- const rootValues = [];
7
- const childrenOf = /* @__PURE__ */ new Map();
8
- function traverse(reactChildren, parentValue, parentDisabled = false) {
9
- const siblingValues = [];
10
- Children.forEach(reactChildren, (child) => {
11
- if (isValidElement(child) && typeof child.props.value === "string") {
12
- const value = child.props.value;
13
- const nodeChildren = child.props.children;
14
- const hasChildren = Children.count(nodeChildren) > 0;
15
- const disabled = parentDisabled || Boolean(child.props.disabled);
16
- nodes.set(value, {
17
- value,
18
- parentValue,
19
- hasChildren,
20
- disabled
21
- });
22
- siblingValues.push(value);
23
- if (hasChildren) {
24
- traverse(nodeChildren, value, disabled);
25
- }
26
- }
27
- });
28
- if (parentValue !== void 0) {
29
- childrenOf.set(parentValue, siblingValues);
30
- } else {
31
- rootValues.push(...siblingValues);
32
- }
5
+ function arraysEqual(a, b) {
6
+ if (a.length !== b.length) {
7
+ return false;
33
8
  }
34
- traverse(children);
35
- return { nodes, rootValues, childrenOf };
9
+ return a.every((value, index) => value === b[index]);
36
10
  }
37
11
  function expandSelectionWithDescendants(selection, model, disabledIds) {
38
12
  const expanded = new Set(selection);
@@ -78,6 +52,8 @@ function useTree(props) {
78
52
  const clampedDefaultSelected = multiselect ? defaultSelected : defaultSelected.slice(0, 1);
79
53
  const clampedSelectedProp = selectedProp && !multiselect ? selectedProp.slice(0, 1) : selectedProp;
80
54
  const treeModel = useMemo(() => buildTreeModel(children), [children]);
55
+ const elementsRef = useRef(/* @__PURE__ */ new Map());
56
+ const suppressUncontrolledSelectionExpansionRef = useRef(false);
81
57
  const disabledIdsSet = useMemo(() => {
82
58
  const set = /* @__PURE__ */ new Set();
83
59
  for (const [value, meta] of treeModel.nodes) {
@@ -104,24 +80,29 @@ function useTree(props) {
104
80
  expanded = expandSelectionUpwards(expanded, treeModel, disabledIdsSet);
105
81
  return expanded;
106
82
  }, [clampedDefaultSelected, treeModel, disabledIdsSet, multiselect]);
107
- const [selectedState, setSelectedState] = useControlled({
83
+ const [selectedState, setSelectedState, selectedControlled] = useControlled({
108
84
  controlled: clampedSelectedProp,
109
85
  default: expandedDefaultSelected,
110
86
  name: "Tree",
111
87
  state: "selected"
112
88
  });
89
+ const setVisibleSelectionState = useCallback((selection) => {
90
+ suppressUncontrolledSelectionExpansionRef.current = true;
91
+ setSelectedState(selection);
92
+ }, []);
113
93
  const selectedSet = useMemo(() => new Set(selectedState), [selectedState]);
114
94
  const [activeNode, setActiveNode] = useState(void 0);
115
- const elementsRef = useRef(/* @__PURE__ */ new Map());
116
- const registerElement = (value, element) => {
95
+ const registerElement = useCallback((value, element) => {
117
96
  elementsRef.current.set(value, element);
118
97
  return () => {
119
- elementsRef.current.delete(value);
98
+ if (elementsRef.current.get(value) === element) {
99
+ elementsRef.current.delete(value);
100
+ }
120
101
  };
121
- };
122
- const getElement = (value) => {
102
+ }, []);
103
+ const getElement = useCallback((value) => {
123
104
  return elementsRef.current.get(value);
124
- };
105
+ }, []);
125
106
  const getNodeMeta = useCallback(
126
107
  (value) => {
127
108
  return treeModel.nodes.get(value);
@@ -213,10 +194,34 @@ function useTree(props) {
213
194
  },
214
195
  [getParent, getChildren, disabledIdsSet]
215
196
  );
216
- const indeterminateState = useMemo(
217
- () => multiselect ? calculateIndeterminateState(selectedState) : /* @__PURE__ */ new Set(),
218
- [multiselect, selectedState, calculateIndeterminateState]
219
- );
197
+ const indeterminateState = useMemo(() => {
198
+ const state = multiselect ? calculateIndeterminateState(selectedState) : /* @__PURE__ */ new Set();
199
+ return state;
200
+ }, [multiselect, selectedState, calculateIndeterminateState]);
201
+ useEffect(() => {
202
+ if (suppressUncontrolledSelectionExpansionRef.current) {
203
+ suppressUncontrolledSelectionExpansionRef.current = false;
204
+ return;
205
+ }
206
+ if (selectedControlled || !multiselect || selectedState.length === 0) {
207
+ return;
208
+ }
209
+ let expanded = expandSelectionWithDescendants(
210
+ selectedState,
211
+ treeModel,
212
+ disabledIdsSet
213
+ );
214
+ expanded = expandSelectionUpwards(expanded, treeModel, disabledIdsSet);
215
+ if (!arraysEqual(selectedState, expanded)) {
216
+ setSelectedState(expanded);
217
+ }
218
+ }, [
219
+ selectedControlled,
220
+ multiselect,
221
+ selectedState,
222
+ treeModel,
223
+ disabledIdsSet
224
+ ]);
220
225
  const updateAncestors = (currentSet, value) => {
221
226
  const ancestors = getAncestors(value);
222
227
  for (const ancestor of ancestors) {
@@ -305,6 +310,7 @@ function useTree(props) {
305
310
  selectedState,
306
311
  selectedSet,
307
312
  setSelectedState,
313
+ setVisibleSelectionState,
308
314
  select,
309
315
  multiselect,
310
316
  disabled,
@@ -1 +1 @@
1
- {"version":3,"file":"useTree.js","sources":["../src/tree/useTree.ts"],"sourcesContent":["import { useControlled } from \"@salt-ds/core\";\nimport {\n Children,\n isValidElement,\n type ReactNode,\n type SyntheticEvent,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport interface UseTreeProps {\n /**\n * Default expanded nodes (uncontrolled)\n */\n defaultExpanded?: string[];\n /**\n * Expanded nodes (controlled)\n */\n expanded?: string[];\n /**\n * Callback on expanded nodes change\n */\n onExpandedChange?: (event: SyntheticEvent, expanded: string[]) => void;\n /**\n * Default selected nodes (uncontrolled)\n */\n defaultSelected?: string[];\n /**\n * Selected nodes\n */\n selected?: string[];\n /**\n * Callback on selected nodes change\n */\n onSelectionChange?: (event: SyntheticEvent, selected: string[]) => void;\n /**\n * Sets multiselect mode with checkboxes and allows for multiple node selection\n */\n multiselect?: boolean;\n /**\n * Sets tree to disabled state, preventing all interaction\n */\n disabled?: boolean;\n /**\n * Tree children used to build the tree model for traversal an state management\n */\n children?: ReactNode;\n}\n\nexport interface TreeNodeMeta {\n value: string;\n parentValue: string | undefined;\n hasChildren: boolean;\n disabled: boolean;\n}\n\nexport interface TreeModel {\n /** All nodes indexed by value */\n nodes: Map<string, TreeNodeMeta>;\n /** Ordered list of root node values */\n rootValues: string[];\n /** Maps parent value to ordered list of child values */\n childrenOf: Map<string, string[]>;\n}\n\nfunction buildTreeModel(children: ReactNode): TreeModel {\n const nodes = new Map<string, TreeNodeMeta>();\n const rootValues: string[] = [];\n const childrenOf = new Map<string, string[]>();\n\n function traverse(\n reactChildren: ReactNode,\n parentValue?: string,\n parentDisabled = false,\n ): void {\n const siblingValues: string[] = [];\n\n Children.forEach(reactChildren, (child) => {\n if (isValidElement(child) && typeof child.props.value === \"string\") {\n const value = child.props.value;\n const nodeChildren = child.props.children;\n const hasChildren = Children.count(nodeChildren) > 0;\n const disabled = parentDisabled || Boolean(child.props.disabled);\n\n nodes.set(value, {\n value,\n parentValue,\n hasChildren,\n disabled,\n });\n\n siblingValues.push(value);\n\n // Process children recursively and pass down disabled state\n if (hasChildren) {\n traverse(nodeChildren, value, disabled);\n }\n }\n });\n\n // Ordered children of parent\n if (parentValue !== undefined) {\n childrenOf.set(parentValue, siblingValues);\n } else {\n // ...and the root nodes\n rootValues.push(...siblingValues);\n }\n }\n\n traverse(children);\n\n return { nodes, rootValues, childrenOf };\n}\n\nfunction expandSelectionWithDescendants(\n selection: string[],\n model: TreeModel,\n disabledIds: Set<string>,\n): string[] {\n const expanded = new Set(selection);\n\n function addDescendants(parentValue: string): void {\n const children = model.childrenOf.get(parentValue) ?? [];\n for (const child of children) {\n if (!disabledIds.has(child)) {\n expanded.add(child);\n addDescendants(child);\n }\n }\n }\n\n for (const value of selection) {\n addDescendants(value);\n }\n\n return Array.from(expanded);\n}\n\nfunction expandSelectionUpwards(\n selection: string[],\n model: TreeModel,\n disabledIds: Set<string>,\n): string[] {\n const selectedSet = new Set(selection);\n\n for (const [value, meta] of model.nodes) {\n if (\n meta.hasChildren &&\n !selectedSet.has(value) &&\n !disabledIds.has(value)\n ) {\n const children = model.childrenOf.get(value) ?? [];\n const enabledChildren = children.filter((c) => !disabledIds.has(c));\n\n if (\n enabledChildren.length > 0 &&\n enabledChildren.every((c) => selectedSet.has(c))\n ) {\n selectedSet.add(value);\n }\n }\n }\n\n return Array.from(selectedSet);\n}\n\nexport function useTree(props: UseTreeProps) {\n const {\n defaultExpanded = [],\n expanded: expandedProp,\n onExpandedChange,\n defaultSelected = [],\n selected: selectedProp,\n onSelectionChange,\n multiselect = false,\n disabled = false,\n children,\n } = props;\n\n const clampedDefaultSelected = multiselect\n ? defaultSelected\n : defaultSelected.slice(0, 1);\n\n const clampedSelectedProp =\n selectedProp && !multiselect ? selectedProp.slice(0, 1) : selectedProp;\n\n const treeModel = useMemo(() => buildTreeModel(children), [children]);\n\n const disabledIdsSet = useMemo(() => {\n const set = new Set<string>();\n for (const [value, meta] of treeModel.nodes) {\n if (meta.disabled) set.add(value);\n }\n return set;\n }, [treeModel]);\n\n const [expandedArray, setExpandedArray] = useControlled({\n controlled: expandedProp,\n default: defaultExpanded,\n name: \"Tree\",\n state: \"expanded\",\n });\n\n // Convert array to Set for more efficient lookups during rendering and nav\n const expandedState = useMemo(() => new Set(expandedArray), [expandedArray]);\n\n const expandedDefaultSelected = useMemo(() => {\n if (!multiselect || clampedDefaultSelected.length === 0) {\n return clampedDefaultSelected;\n }\n\n let expanded = expandSelectionWithDescendants(\n clampedDefaultSelected,\n treeModel,\n disabledIdsSet,\n );\n\n expanded = expandSelectionUpwards(expanded, treeModel, disabledIdsSet);\n\n return expanded;\n }, [clampedDefaultSelected, treeModel, disabledIdsSet, multiselect]);\n\n const [selectedState, setSelectedState] = useControlled({\n controlled: clampedSelectedProp,\n default: expandedDefaultSelected,\n name: \"Tree\",\n state: \"selected\",\n });\n\n const selectedSet = useMemo(() => new Set(selectedState), [selectedState]);\n\n const [activeNode, setActiveNode] = useState<string | undefined>(undefined);\n\n const elementsRef = useRef<Map<string, HTMLElement>>(new Map());\n\n const registerElement = (value: string, element: HTMLElement) => {\n elementsRef.current.set(value, element);\n return () => {\n elementsRef.current.delete(value);\n };\n };\n\n const getElement = (value: string): HTMLElement | undefined => {\n return elementsRef.current.get(value);\n };\n\n const getNodeMeta = useCallback(\n (value: string): TreeNodeMeta | undefined => {\n return treeModel.nodes.get(value);\n },\n [treeModel],\n );\n\n const getParent = useCallback(\n (value: string): string | undefined => {\n return treeModel.nodes.get(value)?.parentValue;\n },\n [treeModel],\n );\n\n const getChildren = useCallback(\n (parentValue: string): string[] => {\n return treeModel.childrenOf.get(parentValue) ?? [];\n },\n [treeModel],\n );\n\n // Depth-first search (with pre-order traversal)\n const getDescendants = useCallback(\n (value: string): string[] => {\n const descendants: string[] = [];\n\n function traverse(parentValue: string): void {\n const children = treeModel.childrenOf.get(parentValue) ?? [];\n for (const child of children) {\n if (!disabledIdsSet.has(child)) {\n descendants.push(child);\n traverse(child);\n }\n }\n }\n\n traverse(value);\n return descendants;\n },\n [treeModel, disabledIdsSet],\n );\n\n const getAncestors = useCallback(\n (value: string): string[] => {\n const ancestors: string[] = [];\n let current = treeModel.nodes.get(value)?.parentValue;\n\n while (current) {\n ancestors.push(current);\n current = treeModel.nodes.get(current)?.parentValue;\n }\n\n return ancestors;\n },\n [treeModel],\n );\n\n const toggleExpanded = useCallback(\n (event: SyntheticEvent, value: string) => {\n const isExpanding = !expandedState.has(value);\n const newExpanded = isExpanding\n ? [...expandedArray, value]\n : expandedArray.filter((v) => v !== value);\n\n setExpandedArray(newExpanded);\n onExpandedChange?.(event, newExpanded);\n },\n [expandedArray, expandedState, onExpandedChange],\n );\n\n const calculateIndeterminateState = useCallback(\n (selected: string[]): Set<string> => {\n const indeterminate = new Set<string>();\n const selectedSet = new Set(selected);\n\n for (const selectedValue of selected) {\n let current = getParent(selectedValue);\n\n while (current) {\n const children = getChildren(current);\n const enabledChildren = children.filter(\n (child) => !disabledIdsSet.has(child),\n );\n\n if (enabledChildren.length === 0) {\n current = getParent(current);\n continue;\n }\n\n const selectedChildren = enabledChildren.filter((child) =>\n selectedSet.has(child),\n );\n const allChildrenSelected =\n selectedChildren.length === enabledChildren.length;\n const someChildrenSelected = selectedChildren.length > 0;\n\n const someChildrenIndeterminate = enabledChildren.some((child) =>\n indeterminate.has(child),\n );\n\n if (\n someChildrenIndeterminate ||\n (someChildrenSelected && !allChildrenSelected)\n ) {\n indeterminate.add(current);\n }\n\n current = getParent(current);\n }\n }\n\n return indeterminate;\n },\n [getParent, getChildren, disabledIdsSet],\n );\n\n const indeterminateState = useMemo(\n () =>\n multiselect\n ? calculateIndeterminateState(selectedState)\n : new Set<string>(),\n [multiselect, selectedState, calculateIndeterminateState],\n );\n\n const updateAncestors = (\n currentSet: Set<string>,\n value: string,\n ): string[] => {\n const ancestors = getAncestors(value);\n\n for (const ancestor of ancestors) {\n const children = treeModel.childrenOf.get(ancestor) ?? [];\n const enabledChildren = children.filter(\n (child) => !disabledIdsSet.has(child),\n );\n\n if (enabledChildren.length === 0) continue;\n\n const allSelected = enabledChildren.every((child) =>\n currentSet.has(child),\n );\n\n if (allSelected) {\n currentSet.add(ancestor);\n } else {\n currentSet.delete(ancestor);\n }\n }\n\n return Array.from(currentSet);\n };\n\n const getMultiSelectState = (value: string) => {\n const currentSet = new Set(selectedState);\n const descendants = getDescendants(value);\n\n if (currentSet.has(value)) {\n currentSet.delete(value);\n const descendantSet = new Set(descendants);\n for (const d of descendantSet) {\n currentSet.delete(d);\n }\n } else {\n currentSet.add(value);\n for (const d of descendants) {\n if (!currentSet.has(d)) {\n currentSet.add(d);\n }\n }\n }\n\n return updateAncestors(currentSet, value);\n };\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: getMultiSelectState/updateAncestors are intentionally not memoized - their captured values (selectedState, treeModel, etc.) are already in deps\n const select = useCallback(\n (event: SyntheticEvent, value: string) => {\n if (disabled || disabledIdsSet.has(value)) return;\n\n let newSelected: string[];\n\n if (multiselect) {\n newSelected = getMultiSelectState(value);\n } else {\n const isCurrentlySelected = selectedSet.has(value);\n newSelected = isCurrentlySelected ? [] : [value];\n }\n\n setSelectedState(newSelected);\n onSelectionChange?.(event, newSelected);\n },\n [disabled, disabledIdsSet, multiselect, selectedState, onSelectionChange],\n );\n\n // Visible nodes in depth-first order matching visual tree order\n const visibleNodes = useMemo((): string[] => {\n const visible: string[] = [];\n\n function traverse(values: string[]): void {\n for (const value of values) {\n visible.push(value);\n\n const nodeMeta = treeModel.nodes.get(value);\n if (nodeMeta?.hasChildren && expandedState.has(value)) {\n const children = treeModel.childrenOf.get(value) ?? [];\n traverse(children);\n }\n }\n }\n\n traverse(treeModel.rootValues);\n return visible;\n }, [treeModel, expandedState]);\n\n const tabbableNodeId = useMemo((): string | undefined => {\n if (activeNode) {\n return activeNode;\n }\n\n const firstSelectedVisible = visibleNodes.find((node) =>\n selectedSet.has(node),\n );\n\n if (firstSelectedVisible !== undefined) {\n return firstSelectedVisible;\n }\n\n return visibleNodes[0];\n }, [activeNode, selectedSet, visibleNodes]);\n\n return {\n expandedArray,\n setExpandedArray,\n expandedState,\n toggleExpanded,\n selectedState,\n selectedSet,\n setSelectedState,\n select,\n multiselect,\n disabled,\n disabledIdsSet,\n treeModel,\n getNodeMeta,\n getParent,\n getChildren,\n getDescendants,\n getAncestors,\n visibleNodes,\n tabbableNodeId,\n registerElement,\n getElement,\n activeNode,\n setActiveNode,\n indeterminateState,\n };\n}\n"],"names":["children","selectedSet"],"mappings":"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"}
1
+ {"version":3,"file":"useTree.js","sources":["../src/tree/useTree.ts"],"sourcesContent":["import { useControlled } from \"@salt-ds/core\";\nimport {\n type ReactNode,\n type SyntheticEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { buildTreeModel, type TreeModel, type TreeNodeMeta } from \"./treeModel\";\n\nexport type { TreeModel, TreeNodeMeta } from \"./treeModel\";\n\nexport interface UseTreeProps {\n /**\n * Default expanded nodes (uncontrolled)\n */\n defaultExpanded?: string[];\n /**\n * Expanded nodes (controlled)\n */\n expanded?: string[];\n /**\n * Callback on expanded nodes change\n */\n onExpandedChange?: (event: SyntheticEvent, expanded: string[]) => void;\n /**\n * Default selected nodes (uncontrolled)\n */\n defaultSelected?: string[];\n /**\n * Selected nodes\n */\n selected?: string[];\n /**\n * Callback on selected nodes change\n */\n onSelectionChange?: (event: SyntheticEvent, selected: string[]) => void;\n /**\n * Sets multiselect mode with checkboxes and allows for multiple node selection\n */\n multiselect?: boolean;\n /**\n * Sets tree to disabled state, preventing all interaction\n */\n disabled?: boolean;\n /**\n * Tree children used to build the tree model for traversal an state management\n */\n children?: ReactNode;\n}\n\nfunction arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n return a.every((value, index) => value === b[index]);\n}\n\nfunction expandSelectionWithDescendants(\n selection: string[],\n model: TreeModel,\n disabledIds: Set<string>,\n): string[] {\n const expanded = new Set(selection);\n\n function addDescendants(parentValue: string): void {\n const children = model.childrenOf.get(parentValue) ?? [];\n for (const child of children) {\n if (!disabledIds.has(child)) {\n expanded.add(child);\n addDescendants(child);\n }\n }\n }\n\n for (const value of selection) {\n addDescendants(value);\n }\n\n return Array.from(expanded);\n}\n\nfunction expandSelectionUpwards(\n selection: string[],\n model: TreeModel,\n disabledIds: Set<string>,\n): string[] {\n const selectedSet = new Set(selection);\n\n for (const [value, meta] of model.nodes) {\n if (\n meta.hasChildren &&\n !selectedSet.has(value) &&\n !disabledIds.has(value)\n ) {\n const children = model.childrenOf.get(value) ?? [];\n const enabledChildren = children.filter((c) => !disabledIds.has(c));\n\n if (\n enabledChildren.length > 0 &&\n enabledChildren.every((c) => selectedSet.has(c))\n ) {\n selectedSet.add(value);\n }\n }\n }\n\n return Array.from(selectedSet);\n}\n\nexport function useTree(props: UseTreeProps) {\n const {\n defaultExpanded = [],\n expanded: expandedProp,\n onExpandedChange,\n defaultSelected = [],\n selected: selectedProp,\n onSelectionChange,\n multiselect = false,\n disabled = false,\n children,\n } = props;\n\n const clampedDefaultSelected = multiselect\n ? defaultSelected\n : defaultSelected.slice(0, 1);\n\n const clampedSelectedProp =\n selectedProp && !multiselect ? selectedProp.slice(0, 1) : selectedProp;\n\n const treeModel = useMemo(() => buildTreeModel(children), [children]);\n const elementsRef = useRef<Map<string, HTMLElement>>(new Map());\n const suppressUncontrolledSelectionExpansionRef = useRef(false);\n\n const disabledIdsSet = useMemo(() => {\n const set = new Set<string>();\n for (const [value, meta] of treeModel.nodes) {\n if (meta.disabled) set.add(value);\n }\n return set;\n }, [treeModel]);\n\n const [expandedArray, setExpandedArray] = useControlled({\n controlled: expandedProp,\n default: defaultExpanded,\n name: \"Tree\",\n state: \"expanded\",\n });\n\n // Convert array to Set for more efficient lookups during rendering and nav\n const expandedState = useMemo(() => new Set(expandedArray), [expandedArray]);\n\n const expandedDefaultSelected = useMemo(() => {\n if (!multiselect || clampedDefaultSelected.length === 0) {\n return clampedDefaultSelected;\n }\n\n let expanded = expandSelectionWithDescendants(\n clampedDefaultSelected,\n treeModel,\n disabledIdsSet,\n );\n\n expanded = expandSelectionUpwards(expanded, treeModel, disabledIdsSet);\n\n return expanded;\n }, [clampedDefaultSelected, treeModel, disabledIdsSet, multiselect]);\n\n const [selectedState, setSelectedState, selectedControlled] = useControlled({\n controlled: clampedSelectedProp,\n default: expandedDefaultSelected,\n name: \"Tree\",\n state: \"selected\",\n });\n\n const setVisibleSelectionState = useCallback((selection: string[]) => {\n suppressUncontrolledSelectionExpansionRef.current = true;\n setSelectedState(selection);\n }, []);\n\n const selectedSet = useMemo(() => new Set(selectedState), [selectedState]);\n\n const [activeNode, setActiveNode] = useState<string | undefined>(undefined);\n\n const registerElement = useCallback((value: string, element: HTMLElement) => {\n elementsRef.current.set(value, element);\n\n return () => {\n if (elementsRef.current.get(value) === element) {\n elementsRef.current.delete(value);\n }\n };\n }, []);\n\n const getElement = useCallback((value: string): HTMLElement | undefined => {\n return elementsRef.current.get(value);\n }, []);\n\n const getNodeMeta = useCallback(\n (value: string): TreeNodeMeta | undefined => {\n return treeModel.nodes.get(value);\n },\n [treeModel],\n );\n\n const getParent = useCallback(\n (value: string): string | undefined => {\n return treeModel.nodes.get(value)?.parentValue;\n },\n [treeModel],\n );\n\n const getChildren = useCallback(\n (parentValue: string): string[] => {\n return treeModel.childrenOf.get(parentValue) ?? [];\n },\n [treeModel],\n );\n\n // Depth-first search (with pre-order traversal)\n const getDescendants = useCallback(\n (value: string): string[] => {\n const descendants: string[] = [];\n\n function traverse(parentValue: string): void {\n const children = treeModel.childrenOf.get(parentValue) ?? [];\n for (const child of children) {\n if (!disabledIdsSet.has(child)) {\n descendants.push(child);\n traverse(child);\n }\n }\n }\n\n traverse(value);\n return descendants;\n },\n [treeModel, disabledIdsSet],\n );\n\n const getAncestors = useCallback(\n (value: string): string[] => {\n const ancestors: string[] = [];\n let current = treeModel.nodes.get(value)?.parentValue;\n\n while (current) {\n ancestors.push(current);\n current = treeModel.nodes.get(current)?.parentValue;\n }\n\n return ancestors;\n },\n [treeModel],\n );\n\n const toggleExpanded = useCallback(\n (event: SyntheticEvent, value: string) => {\n const isExpanding = !expandedState.has(value);\n const newExpanded = isExpanding\n ? [...expandedArray, value]\n : expandedArray.filter((v) => v !== value);\n\n setExpandedArray(newExpanded);\n onExpandedChange?.(event, newExpanded);\n },\n [expandedArray, expandedState, onExpandedChange],\n );\n\n const calculateIndeterminateState = useCallback(\n (selected: string[]): Set<string> => {\n const indeterminate = new Set<string>();\n const selectedSet = new Set(selected);\n\n for (const selectedValue of selected) {\n let current = getParent(selectedValue);\n\n while (current) {\n const children = getChildren(current);\n const enabledChildren = children.filter(\n (child) => !disabledIdsSet.has(child),\n );\n\n if (enabledChildren.length === 0) {\n current = getParent(current);\n continue;\n }\n\n const selectedChildren = enabledChildren.filter((child) =>\n selectedSet.has(child),\n );\n const allChildrenSelected =\n selectedChildren.length === enabledChildren.length;\n const someChildrenSelected = selectedChildren.length > 0;\n\n const someChildrenIndeterminate = enabledChildren.some((child) =>\n indeterminate.has(child),\n );\n\n if (\n someChildrenIndeterminate ||\n (someChildrenSelected && !allChildrenSelected)\n ) {\n indeterminate.add(current);\n }\n\n current = getParent(current);\n }\n }\n\n return indeterminate;\n },\n [getParent, getChildren, disabledIdsSet],\n );\n\n const indeterminateState = useMemo(() => {\n const state = multiselect\n ? calculateIndeterminateState(selectedState)\n : new Set<string>();\n return state;\n }, [multiselect, selectedState, calculateIndeterminateState]);\n\n useEffect(() => {\n if (suppressUncontrolledSelectionExpansionRef.current) {\n suppressUncontrolledSelectionExpansionRef.current = false;\n return;\n }\n\n if (selectedControlled || !multiselect || selectedState.length === 0) {\n return;\n }\n\n let expanded = expandSelectionWithDescendants(\n selectedState,\n treeModel,\n disabledIdsSet,\n );\n expanded = expandSelectionUpwards(expanded, treeModel, disabledIdsSet);\n\n if (!arraysEqual(selectedState, expanded)) {\n setSelectedState(expanded);\n }\n }, [\n selectedControlled,\n multiselect,\n selectedState,\n treeModel,\n disabledIdsSet,\n ]);\n\n const updateAncestors = (\n currentSet: Set<string>,\n value: string,\n ): string[] => {\n const ancestors = getAncestors(value);\n\n for (const ancestor of ancestors) {\n const children = treeModel.childrenOf.get(ancestor) ?? [];\n const enabledChildren = children.filter(\n (child) => !disabledIdsSet.has(child),\n );\n\n if (enabledChildren.length === 0) continue;\n\n const allSelected = enabledChildren.every((child) =>\n currentSet.has(child),\n );\n\n if (allSelected) {\n currentSet.add(ancestor);\n } else {\n currentSet.delete(ancestor);\n }\n }\n\n return Array.from(currentSet);\n };\n\n const getMultiSelectState = (value: string) => {\n const currentSet = new Set(selectedState);\n const descendants = getDescendants(value);\n\n if (currentSet.has(value)) {\n currentSet.delete(value);\n const descendantSet = new Set(descendants);\n for (const d of descendantSet) {\n currentSet.delete(d);\n }\n } else {\n currentSet.add(value);\n for (const d of descendants) {\n if (!currentSet.has(d)) {\n currentSet.add(d);\n }\n }\n }\n\n return updateAncestors(currentSet, value);\n };\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: getMultiSelectState/updateAncestors are intentionally not memoized - their captured values (selectedState, treeModel, etc.) are already in deps\n const select = useCallback(\n (event: SyntheticEvent, value: string) => {\n if (disabled || disabledIdsSet.has(value)) return;\n\n let newSelected: string[];\n\n if (multiselect) {\n newSelected = getMultiSelectState(value);\n } else {\n const isCurrentlySelected = selectedSet.has(value);\n newSelected = isCurrentlySelected ? [] : [value];\n }\n\n setSelectedState(newSelected);\n onSelectionChange?.(event, newSelected);\n },\n [disabled, disabledIdsSet, multiselect, selectedState, onSelectionChange],\n );\n\n // Visible nodes in depth-first order matching visual tree order\n const visibleNodes = useMemo((): string[] => {\n const visible: string[] = [];\n\n function traverse(values: string[]): void {\n for (const value of values) {\n visible.push(value);\n\n const nodeMeta = treeModel.nodes.get(value);\n if (nodeMeta?.hasChildren && expandedState.has(value)) {\n const children = treeModel.childrenOf.get(value) ?? [];\n traverse(children);\n }\n }\n }\n\n traverse(treeModel.rootValues);\n return visible;\n }, [treeModel, expandedState]);\n\n const tabbableNodeId = useMemo((): string | undefined => {\n if (activeNode) {\n return activeNode;\n }\n\n const firstSelectedVisible = visibleNodes.find((node) =>\n selectedSet.has(node),\n );\n\n if (firstSelectedVisible !== undefined) {\n return firstSelectedVisible;\n }\n\n return visibleNodes[0];\n }, [activeNode, selectedSet, visibleNodes]);\n\n return {\n expandedArray,\n setExpandedArray,\n expandedState,\n toggleExpanded,\n selectedState,\n selectedSet,\n setSelectedState,\n setVisibleSelectionState,\n select,\n multiselect,\n disabled,\n disabledIdsSet,\n treeModel,\n getNodeMeta,\n getParent,\n getChildren,\n getDescendants,\n getAncestors,\n visibleNodes,\n tabbableNodeId,\n registerElement,\n getElement,\n activeNode,\n setActiveNode,\n indeterminateState,\n };\n}\n"],"names":["children","selectedSet"],"mappings":"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"}
@@ -27,18 +27,17 @@ export { ListItemBase as ListItemBaseDeprecated, useListItem as useListItemDepre
27
27
  export * from "./list-next";
28
28
  export * from "./localization-provider";
29
29
  export * from "./logo";
30
+ export * from "./mega-menu";
30
31
  export * from "./menu-button";
31
32
  export * from "./metric";
32
33
  export * from "./portal";
33
34
  export * from "./query-input";
34
- export * from "./rating";
35
35
  export * from "./responsive";
36
36
  export * from "./search-input";
37
37
  export * from "./side-panel";
38
38
  export * from "./static-list";
39
39
  export * from "./system-status";
40
40
  export * from "./tabs";
41
- export * from "./tabs-next";
42
41
  export * from "./toast-group";
43
42
  export * from "./tokenized-input";
44
43
  export * from "./tokenized-input-next";
@@ -0,0 +1,27 @@
1
+ import { type Placement } from "@floating-ui/react";
2
+ import { type ReactNode } from "react";
3
+ export interface MegaMenuProps {
4
+ /**
5
+ * The content of the mega menu, typically `MegaMenuTrigger` and `MegaMenuPanel`.
6
+ */
7
+ children?: ReactNode;
8
+ /**
9
+ * Whether the mega menu is open. Use for controlled mode.
10
+ */
11
+ open?: boolean;
12
+ /**
13
+ * Whether the mega menu is initially open. Use for uncontrolled mode.
14
+ * @default false
15
+ */
16
+ defaultOpen?: boolean;
17
+ /**
18
+ * Callback fired when the open state changes.
19
+ */
20
+ onOpenChange?: (open: boolean) => void;
21
+ /**
22
+ * The placement of the mega menu panel relative to the trigger.
23
+ * @default "bottom"
24
+ */
25
+ placement?: Placement;
26
+ }
27
+ export declare function MegaMenu({ children, open, defaultOpen, onOpenChange, placement, }: MegaMenuProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { type ComponentPropsWithoutRef, type ReactNode } from "react";
2
+ export interface MegaMenuContentProps extends ComponentPropsWithoutRef<"div"> {
3
+ /**
4
+ * The content of the region.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuContent: import("react").ForwardRefExoticComponent<MegaMenuContentProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,29 @@
1
+ import type { FloatingRootContext, Placement } from "@floating-ui/react";
2
+ import type { Dispatch, HTMLProps, SetStateAction } from "react";
3
+ export interface MegaMenuContextValue {
4
+ /** Whether the mega menu is currently open. */
5
+ openState: boolean;
6
+ /** Toggle or set the open state of the mega menu. */
7
+ setOpen: (open: boolean) => void;
8
+ /** The floating-ui root context for coordinating interactions. */
9
+ floatingRootContext: FloatingRootContext;
10
+ /** The placement of the mega menu panel relative to the trigger. */
11
+ placement: Placement;
12
+ /** Props getter for the trigger (reference) element. Merges floating-ui interaction props with user props. */
13
+ getReferenceProps: (userProps?: HTMLProps<Element> | undefined) => Record<string, unknown>;
14
+ /** Props getter for the floating panel element. Merges floating-ui interaction props with user props. */
15
+ getFloatingProps: (userProps?: HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
16
+ /** Ref setter for the floating panel element. */
17
+ setFloating: Dispatch<SetStateAction<HTMLElement | null>>;
18
+ /** Ref setter for the trigger (reference) element. */
19
+ setReference: Dispatch<SetStateAction<HTMLElement | null>>;
20
+ /** Whether the first item should receive focus when the panel opens. */
21
+ focusFirstItemOnOpen: boolean;
22
+ /** Toggle the focus-first-item-on-open flag. */
23
+ setFocusFirstItemOnOpen: Dispatch<SetStateAction<boolean>>;
24
+ /** The id of the mega menu panel, used for aria-controls on the trigger. */
25
+ panelId: string | undefined;
26
+ /** Set the panel id when the panel mounts. */
27
+ setPanelId: Dispatch<SetStateAction<string | undefined>>;
28
+ }
29
+ export declare const MegaMenuContext: import("react").Context<MegaMenuContextValue | undefined>;
@@ -0,0 +1,8 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ export interface MegaMenuGroupProps extends HTMLAttributes<HTMLDivElement> {
3
+ /**
4
+ * The content of the mega menu group, typically MegaMenuHeader and MegaMenuItem components.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuGroup: import("react").ForwardRefExoticComponent<MegaMenuGroupProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,8 @@
1
+ import { type ComponentPropsWithoutRef, type ReactNode } from "react";
2
+ export interface MegaMenuHeaderProps extends ComponentPropsWithoutRef<"div"> {
3
+ /**
4
+ * The content of the mega menu header.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuHeader: import("react").ForwardRefExoticComponent<MegaMenuHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,12 @@
1
+ import { type AnchorHTMLAttributes, type ReactNode } from "react";
2
+ export interface MegaMenuItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
3
+ /**
4
+ * The content of the mega menu item.
5
+ */
6
+ children?: ReactNode;
7
+ /**
8
+ * Href to be passed to the Link element.
9
+ */
10
+ href?: string;
11
+ }
12
+ export declare const MegaMenuItem: import("react").ForwardRefExoticComponent<MegaMenuItemProps & import("react").RefAttributes<HTMLLIElement>>;
@@ -0,0 +1,8 @@
1
+ import { type ComponentPropsWithoutRef, type ReactNode } from "react";
2
+ export interface MegaMenuItemContentProps extends ComponentPropsWithoutRef<"div"> {
3
+ /**
4
+ * The content of Mega Menu Item.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuItemContent: import("react").ForwardRefExoticComponent<MegaMenuItemContentProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,8 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ export interface MegaMenuPanelProps extends HTMLAttributes<HTMLDivElement> {
3
+ /**
4
+ * The content of the mega menu panel.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuPanel: import("react").ForwardRefExoticComponent<MegaMenuPanelProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,8 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ export interface MegaMenuSectionProps extends HTMLAttributes<HTMLDivElement> {
3
+ /**
4
+ * The content of the mega menu section.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuSection: import("react").ForwardRefExoticComponent<MegaMenuSectionProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,8 @@
1
+ import { type ReactNode } from "react";
2
+ export interface MegaMenuTriggerProps {
3
+ /**
4
+ * The trigger element for the mega menu, typically a `NavigationItem` or `Button`.
5
+ */
6
+ children?: ReactNode;
7
+ }
8
+ export declare const MegaMenuTrigger: import("react").ForwardRefExoticComponent<MegaMenuTriggerProps & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,9 @@
1
+ export * from "./MegaMenu";
2
+ export * from "./MegaMenuContent";
3
+ export * from "./MegaMenuGroup";
4
+ export * from "./MegaMenuHeader";
5
+ export * from "./MegaMenuItem";
6
+ export * from "./MegaMenuItemContent";
7
+ export * from "./MegaMenuPanel";
8
+ export * from "./MegaMenuSection";
9
+ export * from "./MegaMenuTrigger";
@@ -0,0 +1,6 @@
1
+ import { type MegaMenuContextValue } from "./MegaMenuContext";
2
+ /**
3
+ * Access the nearest MegaMenu context.
4
+ * Must be used within a `MegaMenu` provider.
5
+ */
6
+ export declare function useMegaMenu(): MegaMenuContextValue;
@@ -0,0 +1,30 @@
1
+ import type { ElementProps, FloatingRootContext } from "@floating-ui/react";
2
+ export declare const FOCUSABLE_SELECTOR = "a[href], button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
3
+ export interface UseMegaMenuKeyboardProps {
4
+ /**
5
+ * Whether the interaction is enabled.
6
+ * @default true
7
+ */
8
+ enabled?: boolean;
9
+ }
10
+ /**
11
+ * Floating-ui custom interaction hook for mega menu grid keyboard navigation.
12
+ *
13
+ * Returns `ElementProps` that get merged via `useInteractions`, handling
14
+ * keyboard events on both the reference (trigger) and floating (panel) elements.
15
+ *
16
+ * - **↑ / ↓** move within the current column.
17
+ * - **← / →** jump to the top of the previous / next column.
18
+ * - **Tab / Shift+Tab** move linearly through every item.
19
+ * - **Home / End** jump to the first / last item in the column.
20
+ * - **↑ from the first item** or **← from the first column** returns
21
+ * focus to the trigger.
22
+ * - **→ from the last column** closes the panel and moves focus to the
23
+ * next sibling trigger.
24
+ */
25
+ export declare function useMegaMenuKeyboard(context: FloatingRootContext, props?: UseMegaMenuKeyboardProps): ElementProps;
26
+ /**
27
+ * Focus the first navigable item inside a mega menu panel.
28
+ * Retries with `requestAnimationFrame` if content has not yet rendered.
29
+ */
30
+ export declare function focusFirstItem(panel: HTMLElement, attempt?: number): void;