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

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 (356) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/css/salt-lab.css +125 -366
  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 +25 -30
  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/SidePanelProvider.js +20 -2
  53. package/dist-cjs/side-panel/SidePanelProvider.js.map +1 -1
  54. package/dist-cjs/side-panel/SidePanelTitle.css.js +1 -1
  55. package/dist-cjs/side-panel/SidePanelTitle.js +1 -0
  56. package/dist-cjs/side-panel/SidePanelTitle.js.map +1 -1
  57. package/dist-cjs/side-panel/SidePanelTrigger.js +4 -4
  58. package/dist-cjs/side-panel/SidePanelTrigger.js.map +1 -1
  59. package/dist-cjs/side-panel/internal/SidePanelContext.js +3 -0
  60. package/dist-cjs/side-panel/internal/SidePanelContext.js.map +1 -1
  61. package/dist-cjs/side-panel/internal/useIsScrollable.js +50 -0
  62. package/dist-cjs/side-panel/internal/useIsScrollable.js.map +1 -0
  63. package/dist-cjs/side-panel/internal/useSidePanelTabOrder.js +121 -0
  64. package/dist-cjs/side-panel/internal/useSidePanelTabOrder.js.map +1 -0
  65. package/dist-cjs/side-panel/useSidePanel.js +3 -1
  66. package/dist-cjs/side-panel/useSidePanel.js.map +1 -1
  67. package/dist-cjs/tree/Tree.js +8 -5
  68. package/dist-cjs/tree/Tree.js.map +1 -1
  69. package/dist-cjs/tree/TreeContext.js.map +1 -1
  70. package/dist-cjs/tree/TreeNode.js +18 -14
  71. package/dist-cjs/tree/TreeNode.js.map +1 -1
  72. package/dist-cjs/tree/TreeNodeTrigger.js +4 -3
  73. package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
  74. package/dist-cjs/tree/treeModel.js +61 -0
  75. package/dist-cjs/tree/treeModel.js.map +1 -0
  76. package/dist-cjs/tree/useTree.js +71 -65
  77. package/dist-cjs/tree/useTree.js.map +1 -1
  78. package/dist-es/index.js +10 -8
  79. package/dist-es/index.js.map +1 -1
  80. package/dist-es/mega-menu/MegaMenu.js +80 -0
  81. package/dist-es/mega-menu/MegaMenu.js.map +1 -0
  82. package/dist-es/mega-menu/MegaMenuContent.css.js +4 -0
  83. package/dist-es/mega-menu/MegaMenuContent.css.js.map +1 -0
  84. package/dist-es/mega-menu/MegaMenuContent.js +31 -0
  85. package/dist-es/mega-menu/MegaMenuContent.js.map +1 -0
  86. package/dist-es/mega-menu/MegaMenuContext.js +9 -0
  87. package/dist-es/mega-menu/MegaMenuContext.js.map +1 -0
  88. package/dist-es/mega-menu/MegaMenuGroup.css.js +4 -0
  89. package/dist-es/mega-menu/MegaMenuGroup.css.js.map +1 -0
  90. package/dist-es/mega-menu/MegaMenuGroup.js +56 -0
  91. package/dist-es/mega-menu/MegaMenuGroup.js.map +1 -0
  92. package/dist-es/mega-menu/MegaMenuHeader.css.js +4 -0
  93. package/dist-es/mega-menu/MegaMenuHeader.css.js.map +1 -0
  94. package/dist-es/mega-menu/MegaMenuHeader.js +24 -0
  95. package/dist-es/mega-menu/MegaMenuHeader.js.map +1 -0
  96. package/dist-es/mega-menu/MegaMenuItem.css.js +4 -0
  97. package/dist-es/mega-menu/MegaMenuItem.css.js.map +1 -0
  98. package/dist-es/mega-menu/MegaMenuItem.js +50 -0
  99. package/dist-es/mega-menu/MegaMenuItem.js.map +1 -0
  100. package/dist-es/mega-menu/MegaMenuItemContent.css.js +4 -0
  101. package/dist-es/mega-menu/MegaMenuItemContent.css.js.map +1 -0
  102. package/dist-es/mega-menu/MegaMenuItemContent.js +21 -0
  103. package/dist-es/mega-menu/MegaMenuItemContent.js.map +1 -0
  104. package/dist-es/mega-menu/MegaMenuPanel.css.js +4 -0
  105. package/dist-es/mega-menu/MegaMenuPanel.css.js.map +1 -0
  106. package/dist-es/mega-menu/MegaMenuPanel.js +106 -0
  107. package/dist-es/mega-menu/MegaMenuPanel.js.map +1 -0
  108. package/dist-es/mega-menu/MegaMenuSection.css.js +4 -0
  109. package/dist-es/mega-menu/MegaMenuSection.css.js.map +1 -0
  110. package/dist-es/mega-menu/MegaMenuSection.js +23 -0
  111. package/dist-es/mega-menu/MegaMenuSection.js.map +1 -0
  112. package/dist-es/mega-menu/MegaMenuTrigger.js +90 -0
  113. package/dist-es/mega-menu/MegaMenuTrigger.js.map +1 -0
  114. package/dist-es/mega-menu/useMegaMenu.js +13 -0
  115. package/dist-es/mega-menu/useMegaMenu.js.map +1 -0
  116. package/dist-es/mega-menu/useMegaMenuKeyboard.js +205 -0
  117. package/dist-es/mega-menu/useMegaMenuKeyboard.js.map +1 -0
  118. package/dist-es/side-panel/SidePanel.css.js +1 -1
  119. package/dist-es/side-panel/SidePanel.js +28 -33
  120. package/dist-es/side-panel/SidePanel.js.map +1 -1
  121. package/dist-es/side-panel/SidePanelCloseButton.js +36 -0
  122. package/dist-es/side-panel/SidePanelCloseButton.js.map +1 -0
  123. package/dist-es/side-panel/SidePanelContent.css.js +1 -1
  124. package/dist-es/side-panel/SidePanelContent.js +4 -24
  125. package/dist-es/side-panel/SidePanelContent.js.map +1 -1
  126. package/dist-es/side-panel/SidePanelHeader.css.js +1 -1
  127. package/dist-es/side-panel/SidePanelProvider.js +20 -2
  128. package/dist-es/side-panel/SidePanelProvider.js.map +1 -1
  129. package/dist-es/side-panel/SidePanelTitle.css.js +1 -1
  130. package/dist-es/side-panel/SidePanelTitle.js +1 -0
  131. package/dist-es/side-panel/SidePanelTitle.js.map +1 -1
  132. package/dist-es/side-panel/SidePanelTrigger.js +5 -5
  133. package/dist-es/side-panel/SidePanelTrigger.js.map +1 -1
  134. package/dist-es/side-panel/internal/SidePanelContext.js +3 -0
  135. package/dist-es/side-panel/internal/SidePanelContext.js.map +1 -1
  136. package/dist-es/side-panel/internal/useIsScrollable.js +48 -0
  137. package/dist-es/side-panel/internal/useIsScrollable.js.map +1 -0
  138. package/dist-es/side-panel/internal/useSidePanelTabOrder.js +119 -0
  139. package/dist-es/side-panel/internal/useSidePanelTabOrder.js.map +1 -0
  140. package/dist-es/side-panel/useSidePanel.js +3 -1
  141. package/dist-es/side-panel/useSidePanel.js.map +1 -1
  142. package/dist-es/tree/Tree.js +8 -5
  143. package/dist-es/tree/Tree.js.map +1 -1
  144. package/dist-es/tree/TreeContext.js.map +1 -1
  145. package/dist-es/tree/TreeNode.js +20 -16
  146. package/dist-es/tree/TreeNode.js.map +1 -1
  147. package/dist-es/tree/TreeNodeTrigger.js +4 -3
  148. package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
  149. package/dist-es/tree/treeModel.js +57 -0
  150. package/dist-es/tree/treeModel.js.map +1 -0
  151. package/dist-es/tree/useTree.js +49 -43
  152. package/dist-es/tree/useTree.js.map +1 -1
  153. package/dist-types/index.d.ts +1 -2
  154. package/dist-types/mega-menu/MegaMenu.d.ts +27 -0
  155. package/dist-types/mega-menu/MegaMenuContent.d.ts +8 -0
  156. package/dist-types/mega-menu/MegaMenuContext.d.ts +29 -0
  157. package/dist-types/mega-menu/MegaMenuGroup.d.ts +8 -0
  158. package/dist-types/mega-menu/MegaMenuHeader.d.ts +8 -0
  159. package/dist-types/mega-menu/MegaMenuItem.d.ts +12 -0
  160. package/dist-types/mega-menu/MegaMenuItemContent.d.ts +8 -0
  161. package/dist-types/mega-menu/MegaMenuPanel.d.ts +8 -0
  162. package/dist-types/mega-menu/MegaMenuSection.d.ts +8 -0
  163. package/dist-types/mega-menu/MegaMenuTrigger.d.ts +8 -0
  164. package/dist-types/mega-menu/index.d.ts +9 -0
  165. package/dist-types/mega-menu/useMegaMenu.d.ts +6 -0
  166. package/dist-types/mega-menu/useMegaMenuKeyboard.d.ts +30 -0
  167. package/dist-types/side-panel/SidePanelCloseButton.d.ts +2 -0
  168. package/dist-types/side-panel/SidePanelTrigger.d.ts +1 -2
  169. package/dist-types/side-panel/index.d.ts +1 -0
  170. package/dist-types/side-panel/internal/SidePanelContext.d.ts +8 -0
  171. package/dist-types/side-panel/internal/index.d.ts +2 -0
  172. package/dist-types/side-panel/internal/useIsScrollable.d.ts +2 -0
  173. package/dist-types/side-panel/internal/useSidePanelTabOrder.d.ts +7 -0
  174. package/dist-types/side-panel/useSidePanel.d.ts +11 -4
  175. package/dist-types/tree/TreeContext.d.ts +7 -1
  176. package/dist-types/tree/treeModel.d.ts +24 -0
  177. package/dist-types/tree/useTree.d.ts +3 -14
  178. package/package.json +2 -4
  179. package/dist-cjs/rating/Rating.css.js +0 -6
  180. package/dist-cjs/rating/Rating.css.js.map +0 -1
  181. package/dist-cjs/rating/Rating.js +0 -132
  182. package/dist-cjs/rating/Rating.js.map +0 -1
  183. package/dist-cjs/rating/RatingItem.css.js +0 -6
  184. package/dist-cjs/rating/RatingItem.css.js.map +0 -1
  185. package/dist-cjs/rating/RatingItem.js +0 -70
  186. package/dist-cjs/rating/RatingItem.js.map +0 -1
  187. package/dist-cjs/tabs-next/TabBar.css.js +0 -6
  188. package/dist-cjs/tabs-next/TabBar.css.js.map +0 -1
  189. package/dist-cjs/tabs-next/TabBar.js +0 -41
  190. package/dist-cjs/tabs-next/TabBar.js.map +0 -1
  191. package/dist-cjs/tabs-next/TabListLayoutContext.js +0 -13
  192. package/dist-cjs/tabs-next/TabListLayoutContext.js.map +0 -1
  193. package/dist-cjs/tabs-next/TabListNext.css.js +0 -6
  194. package/dist-cjs/tabs-next/TabListNext.css.js.map +0 -1
  195. package/dist-cjs/tabs-next/TabListNext.js +0 -271
  196. package/dist-cjs/tabs-next/TabListNext.js.map +0 -1
  197. package/dist-cjs/tabs-next/TabNext.css.js +0 -6
  198. package/dist-cjs/tabs-next/TabNext.css.js.map +0 -1
  199. package/dist-cjs/tabs-next/TabNext.js +0 -213
  200. package/dist-cjs/tabs-next/TabNext.js.map +0 -1
  201. package/dist-cjs/tabs-next/TabNextAction.js +0 -58
  202. package/dist-cjs/tabs-next/TabNextAction.js.map +0 -1
  203. package/dist-cjs/tabs-next/TabNextContext.js +0 -23
  204. package/dist-cjs/tabs-next/TabNextContext.js.map +0 -1
  205. package/dist-cjs/tabs-next/TabNextPanel.css.js +0 -6
  206. package/dist-cjs/tabs-next/TabNextPanel.css.js.map +0 -1
  207. package/dist-cjs/tabs-next/TabNextPanel.js +0 -92
  208. package/dist-cjs/tabs-next/TabNextPanel.js.map +0 -1
  209. package/dist-cjs/tabs-next/TabNextTrigger.css.js +0 -6
  210. package/dist-cjs/tabs-next/TabNextTrigger.css.js.map +0 -1
  211. package/dist-cjs/tabs-next/TabNextTrigger.js +0 -180
  212. package/dist-cjs/tabs-next/TabNextTrigger.js.map +0 -1
  213. package/dist-cjs/tabs-next/TabOverflowList.css.js +0 -6
  214. package/dist-cjs/tabs-next/TabOverflowList.css.js.map +0 -1
  215. package/dist-cjs/tabs-next/TabOverflowList.js +0 -237
  216. package/dist-cjs/tabs-next/TabOverflowList.js.map +0 -1
  217. package/dist-cjs/tabs-next/TabSlot.js +0 -30
  218. package/dist-cjs/tabs-next/TabSlot.js.map +0 -1
  219. package/dist-cjs/tabs-next/TabSlotRegistryContext.js +0 -16
  220. package/dist-cjs/tabs-next/TabSlotRegistryContext.js.map +0 -1
  221. package/dist-cjs/tabs-next/TabsNext.css.js +0 -6
  222. package/dist-cjs/tabs-next/TabsNext.css.js.map +0 -1
  223. package/dist-cjs/tabs-next/TabsNext.js +0 -195
  224. package/dist-cjs/tabs-next/TabsNext.js.map +0 -1
  225. package/dist-cjs/tabs-next/TabsNextContext.js +0 -47
  226. package/dist-cjs/tabs-next/TabsNextContext.js.map +0 -1
  227. package/dist-cjs/tabs-next/domUtils.js +0 -13
  228. package/dist-cjs/tabs-next/domUtils.js.map +0 -1
  229. package/dist-cjs/tabs-next/hooks/overflowMath.js +0 -86
  230. package/dist-cjs/tabs-next/hooks/overflowMath.js.map +0 -1
  231. package/dist-cjs/tabs-next/hooks/useCollection.js +0 -197
  232. package/dist-cjs/tabs-next/hooks/useCollection.js.map +0 -1
  233. package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js +0 -64
  234. package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js.map +0 -1
  235. package/dist-cjs/tabs-next/hooks/useOverflow.js +0 -266
  236. package/dist-cjs/tabs-next/hooks/useOverflow.js.map +0 -1
  237. package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js +0 -99
  238. package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js.map +0 -1
  239. package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js +0 -60
  240. package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js.map +0 -1
  241. package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js +0 -92
  242. package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js.map +0 -1
  243. package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js +0 -200
  244. package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js.map +0 -1
  245. package/dist-cjs/tabs-next/hooks/useTabListRecovery.js +0 -76
  246. package/dist-cjs/tabs-next/hooks/useTabListRecovery.js.map +0 -1
  247. package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js +0 -165
  248. package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js.map +0 -1
  249. package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js +0 -80
  250. package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js.map +0 -1
  251. package/dist-cjs/tabs-next/widthMeasurement.js +0 -42
  252. package/dist-cjs/tabs-next/widthMeasurement.js.map +0 -1
  253. package/dist-es/rating/Rating.css.js +0 -4
  254. package/dist-es/rating/Rating.css.js.map +0 -1
  255. package/dist-es/rating/Rating.js +0 -130
  256. package/dist-es/rating/Rating.js.map +0 -1
  257. package/dist-es/rating/RatingItem.css.js +0 -4
  258. package/dist-es/rating/RatingItem.css.js.map +0 -1
  259. package/dist-es/rating/RatingItem.js +0 -68
  260. package/dist-es/rating/RatingItem.js.map +0 -1
  261. package/dist-es/tabs-next/TabBar.css.js +0 -4
  262. package/dist-es/tabs-next/TabBar.css.js.map +0 -1
  263. package/dist-es/tabs-next/TabBar.js +0 -39
  264. package/dist-es/tabs-next/TabBar.js.map +0 -1
  265. package/dist-es/tabs-next/TabListLayoutContext.js +0 -10
  266. package/dist-es/tabs-next/TabListLayoutContext.js.map +0 -1
  267. package/dist-es/tabs-next/TabListNext.css.js +0 -4
  268. package/dist-es/tabs-next/TabListNext.css.js.map +0 -1
  269. package/dist-es/tabs-next/TabListNext.js +0 -269
  270. package/dist-es/tabs-next/TabListNext.js.map +0 -1
  271. package/dist-es/tabs-next/TabNext.css.js +0 -4
  272. package/dist-es/tabs-next/TabNext.css.js.map +0 -1
  273. package/dist-es/tabs-next/TabNext.js +0 -211
  274. package/dist-es/tabs-next/TabNext.js.map +0 -1
  275. package/dist-es/tabs-next/TabNextAction.js +0 -56
  276. package/dist-es/tabs-next/TabNextAction.js.map +0 -1
  277. package/dist-es/tabs-next/TabNextContext.js +0 -20
  278. package/dist-es/tabs-next/TabNextContext.js.map +0 -1
  279. package/dist-es/tabs-next/TabNextPanel.css.js +0 -4
  280. package/dist-es/tabs-next/TabNextPanel.css.js.map +0 -1
  281. package/dist-es/tabs-next/TabNextPanel.js +0 -90
  282. package/dist-es/tabs-next/TabNextPanel.js.map +0 -1
  283. package/dist-es/tabs-next/TabNextTrigger.css.js +0 -4
  284. package/dist-es/tabs-next/TabNextTrigger.css.js.map +0 -1
  285. package/dist-es/tabs-next/TabNextTrigger.js +0 -178
  286. package/dist-es/tabs-next/TabNextTrigger.js.map +0 -1
  287. package/dist-es/tabs-next/TabOverflowList.css.js +0 -4
  288. package/dist-es/tabs-next/TabOverflowList.css.js.map +0 -1
  289. package/dist-es/tabs-next/TabOverflowList.js +0 -235
  290. package/dist-es/tabs-next/TabOverflowList.js.map +0 -1
  291. package/dist-es/tabs-next/TabSlot.js +0 -28
  292. package/dist-es/tabs-next/TabSlot.js.map +0 -1
  293. package/dist-es/tabs-next/TabSlotRegistryContext.js +0 -13
  294. package/dist-es/tabs-next/TabSlotRegistryContext.js.map +0 -1
  295. package/dist-es/tabs-next/TabsNext.css.js +0 -4
  296. package/dist-es/tabs-next/TabsNext.css.js.map +0 -1
  297. package/dist-es/tabs-next/TabsNext.js +0 -193
  298. package/dist-es/tabs-next/TabsNext.js.map +0 -1
  299. package/dist-es/tabs-next/TabsNextContext.js +0 -44
  300. package/dist-es/tabs-next/TabsNextContext.js.map +0 -1
  301. package/dist-es/tabs-next/domUtils.js +0 -11
  302. package/dist-es/tabs-next/domUtils.js.map +0 -1
  303. package/dist-es/tabs-next/hooks/overflowMath.js +0 -82
  304. package/dist-es/tabs-next/hooks/overflowMath.js.map +0 -1
  305. package/dist-es/tabs-next/hooks/useCollection.js +0 -195
  306. package/dist-es/tabs-next/hooks/useCollection.js.map +0 -1
  307. package/dist-es/tabs-next/hooks/useFocusWithRetry.js +0 -62
  308. package/dist-es/tabs-next/hooks/useFocusWithRetry.js.map +0 -1
  309. package/dist-es/tabs-next/hooks/useOverflow.js +0 -264
  310. package/dist-es/tabs-next/hooks/useOverflow.js.map +0 -1
  311. package/dist-es/tabs-next/hooks/useOverflowLayoutState.js +0 -97
  312. package/dist-es/tabs-next/hooks/useOverflowLayoutState.js.map +0 -1
  313. package/dist-es/tabs-next/hooks/useOverflowSelectionState.js +0 -58
  314. package/dist-es/tabs-next/hooks/useOverflowSelectionState.js.map +0 -1
  315. package/dist-es/tabs-next/hooks/useRenderedTabWidth.js +0 -90
  316. package/dist-es/tabs-next/hooks/useRenderedTabWidth.js.map +0 -1
  317. package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js +0 -198
  318. package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js.map +0 -1
  319. package/dist-es/tabs-next/hooks/useTabListRecovery.js +0 -74
  320. package/dist-es/tabs-next/hooks/useTabListRecovery.js.map +0 -1
  321. package/dist-es/tabs-next/hooks/useTabRemovalHandler.js +0 -163
  322. package/dist-es/tabs-next/hooks/useTabRemovalHandler.js.map +0 -1
  323. package/dist-es/tabs-next/hooks/useTabSelectionFocus.js +0 -78
  324. package/dist-es/tabs-next/hooks/useTabSelectionFocus.js.map +0 -1
  325. package/dist-es/tabs-next/widthMeasurement.js +0 -36
  326. package/dist-es/tabs-next/widthMeasurement.js.map +0 -1
  327. package/dist-types/rating/Rating.d.ts +0 -48
  328. package/dist-types/rating/RatingItem.d.ts +0 -47
  329. package/dist-types/rating/index.d.ts +0 -1
  330. package/dist-types/tabs-next/TabBar.d.ts +0 -12
  331. package/dist-types/tabs-next/TabListLayoutContext.d.ts +0 -9
  332. package/dist-types/tabs-next/TabListNext.d.ts +0 -12
  333. package/dist-types/tabs-next/TabNext.d.ts +0 -12
  334. package/dist-types/tabs-next/TabNextAction.d.ts +0 -4
  335. package/dist-types/tabs-next/TabNextContext.d.ts +0 -12
  336. package/dist-types/tabs-next/TabNextPanel.d.ts +0 -9
  337. package/dist-types/tabs-next/TabNextTrigger.d.ts +0 -4
  338. package/dist-types/tabs-next/TabOverflowList.d.ts +0 -10
  339. package/dist-types/tabs-next/TabSlot.d.ts +0 -6
  340. package/dist-types/tabs-next/TabSlotRegistryContext.d.ts +0 -5
  341. package/dist-types/tabs-next/TabsNext.d.ts +0 -18
  342. package/dist-types/tabs-next/TabsNextContext.d.ts +0 -43
  343. package/dist-types/tabs-next/domUtils.d.ts +0 -1
  344. package/dist-types/tabs-next/hooks/overflowMath.d.ts +0 -18
  345. package/dist-types/tabs-next/hooks/useCollection.d.ts +0 -30
  346. package/dist-types/tabs-next/hooks/useFocusWithRetry.d.ts +0 -9
  347. package/dist-types/tabs-next/hooks/useOverflow.d.ts +0 -11
  348. package/dist-types/tabs-next/hooks/useOverflowLayoutState.d.ts +0 -13
  349. package/dist-types/tabs-next/hooks/useOverflowSelectionState.d.ts +0 -13
  350. package/dist-types/tabs-next/hooks/useRenderedTabWidth.d.ts +0 -12
  351. package/dist-types/tabs-next/hooks/useRenderedTabsRegistry.d.ts +0 -12
  352. package/dist-types/tabs-next/hooks/useTabListRecovery.d.ts +0 -12
  353. package/dist-types/tabs-next/hooks/useTabRemovalHandler.d.ts +0 -32
  354. package/dist-types/tabs-next/hooks/useTabSelectionFocus.d.ts +0 -15
  355. package/dist-types/tabs-next/index.d.ts +0 -7
  356. package/dist-types/tabs-next/widthMeasurement.d.ts +0 -5
@@ -0,0 +1,205 @@
1
+ import { useMemo } from 'react';
2
+
3
+ const COLUMN_SELECTOR = "[data-mega-menu-column]";
4
+ const ITEM_SELECTOR = "[data-mega-menu-item]";
5
+ const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';
6
+ function getColumnItems(column) {
7
+ const marked = Array.from(
8
+ column.querySelectorAll(ITEM_SELECTOR)
9
+ );
10
+ if (marked.length > 0) return marked;
11
+ return Array.from(column.querySelectorAll(FOCUSABLE_SELECTOR));
12
+ }
13
+ function buildGrid(panel) {
14
+ const columns = new Set(panel.querySelectorAll(COLUMN_SELECTOR));
15
+ const grid = [];
16
+ const processedColumns = /* @__PURE__ */ new Set();
17
+ const all = panel.querySelectorAll(
18
+ `${COLUMN_SELECTOR}, ${ITEM_SELECTOR}`
19
+ );
20
+ for (const el of all) {
21
+ if (columns.has(el) && !processedColumns.has(el)) {
22
+ processedColumns.add(el);
23
+ const items = getColumnItems(el);
24
+ if (items.length > 0) grid.push(items);
25
+ } else if (el.matches(ITEM_SELECTOR)) {
26
+ const parentCol = el.closest(COLUMN_SELECTOR);
27
+ if (!parentCol || !columns.has(parentCol)) {
28
+ grid.push([el]);
29
+ }
30
+ }
31
+ }
32
+ return grid;
33
+ }
34
+ function findPosition(grid, el) {
35
+ for (let col = 0; col < grid.length; col++) {
36
+ const row = grid[col].indexOf(el);
37
+ if (row !== -1) return { col, row };
38
+ }
39
+ return null;
40
+ }
41
+ function focusTrigger(context) {
42
+ const reference = context.elements.reference;
43
+ const focusable = (reference == null ? void 0 : reference.querySelector(FOCUSABLE_SELECTOR)) ?? reference;
44
+ focusable == null ? void 0 : focusable.focus();
45
+ }
46
+ function focusNextAfterPanel(context, panel) {
47
+ var _a, _b;
48
+ const reference = context.elements.reference;
49
+ const refFocusable = (reference == null ? void 0 : reference.querySelector(FOCUSABLE_SELECTOR)) ?? reference;
50
+ const nextSibling = (_b = (_a = refFocusable == null ? void 0 : refFocusable.closest("li")) == null ? void 0 : _a.nextElementSibling) == null ? void 0 : _b.querySelector(FOCUSABLE_SELECTOR);
51
+ const nextOutside = nextSibling || (() => {
52
+ const allFocusable = Array.from(
53
+ panel.ownerDocument.querySelectorAll(FOCUSABLE_SELECTOR)
54
+ ).filter((el) => !panel.contains(el));
55
+ const idx = refFocusable ? allFocusable.indexOf(refFocusable) : -1;
56
+ return idx >= 0 ? allFocusable[idx + 1] : void 0;
57
+ })();
58
+ if (nextOutside) {
59
+ const view = panel.ownerDocument.defaultView;
60
+ view == null ? void 0 : view.requestAnimationFrame(() => {
61
+ view == null ? void 0 : view.requestAnimationFrame(() => {
62
+ nextOutside.focus();
63
+ });
64
+ });
65
+ }
66
+ }
67
+ function useMegaMenuKeyboard(context, props = {}) {
68
+ const { enabled = true } = props;
69
+ const { open, onOpenChange } = context;
70
+ return useMemo(() => {
71
+ if (!enabled) {
72
+ return {};
73
+ }
74
+ return {
75
+ reference: {
76
+ onKeyDown(event) {
77
+ if (event.key === "ArrowDown" && open) {
78
+ event.preventDefault();
79
+ const floating = context.elements.floating;
80
+ if (floating instanceof HTMLElement) {
81
+ focusFirstItem(floating);
82
+ }
83
+ }
84
+ }
85
+ },
86
+ floating: {
87
+ onKeyDown(event) {
88
+ var _a, _b, _c, _d;
89
+ if (!open) return;
90
+ const panel = event.currentTarget;
91
+ const target = event.target;
92
+ const focusedItem = target.closest(ITEM_SELECTOR) ?? target.closest(FOCUSABLE_SELECTOR);
93
+ if (!focusedItem) return;
94
+ const grid = buildGrid(panel);
95
+ const pos = findPosition(grid, focusedItem);
96
+ if (!pos) return;
97
+ const allItems = grid.flat();
98
+ const linearIndex = allItems.indexOf(focusedItem);
99
+ switch (event.key) {
100
+ case "ArrowDown": {
101
+ event.preventDefault();
102
+ const next = pos.row + 1;
103
+ if (next < grid[pos.col].length) {
104
+ grid[pos.col][next].focus();
105
+ } else {
106
+ const nextCol = pos.col + 1;
107
+ if (nextCol < grid.length) {
108
+ grid[nextCol][0].focus();
109
+ }
110
+ }
111
+ break;
112
+ }
113
+ case "ArrowUp": {
114
+ event.preventDefault();
115
+ if (pos.row > 0) {
116
+ grid[pos.col][pos.row - 1].focus();
117
+ } else {
118
+ const prevCol = pos.col - 1;
119
+ if (prevCol >= 0) {
120
+ grid[prevCol][grid[prevCol].length - 1].focus();
121
+ } else {
122
+ focusTrigger(context);
123
+ }
124
+ }
125
+ break;
126
+ }
127
+ case "ArrowRight": {
128
+ event.preventDefault();
129
+ const nextCol = pos.col + 1;
130
+ if (nextCol < grid.length) {
131
+ grid[nextCol][0].focus();
132
+ } else {
133
+ const reference = context.elements.reference;
134
+ const trigger = (reference == null ? void 0 : reference.querySelector(FOCUSABLE_SELECTOR)) ?? reference;
135
+ const li = trigger == null ? void 0 : trigger.closest("li");
136
+ const nextSibling = (li == null ? void 0 : li.nextElementSibling) instanceof HTMLElement ? li.nextElementSibling.querySelector(
137
+ FOCUSABLE_SELECTOR
138
+ ) : null;
139
+ if (nextSibling) {
140
+ onOpenChange(false);
141
+ nextSibling.focus();
142
+ }
143
+ }
144
+ break;
145
+ }
146
+ case "ArrowLeft": {
147
+ event.preventDefault();
148
+ const prevCol = pos.col - 1;
149
+ if (prevCol >= 0) {
150
+ grid[prevCol][0].focus();
151
+ } else {
152
+ focusTrigger(context);
153
+ }
154
+ break;
155
+ }
156
+ case "Tab": {
157
+ event.preventDefault();
158
+ if (event.shiftKey) {
159
+ if (linearIndex === 0) {
160
+ focusTrigger(context);
161
+ } else {
162
+ (_a = allItems[linearIndex - 1]) == null ? void 0 : _a.focus();
163
+ }
164
+ } else {
165
+ if (linearIndex === allItems.length - 1) {
166
+ onOpenChange(false);
167
+ focusNextAfterPanel(context, panel);
168
+ } else {
169
+ (_b = allItems[linearIndex + 1]) == null ? void 0 : _b.focus();
170
+ }
171
+ }
172
+ break;
173
+ }
174
+ case "Home": {
175
+ event.preventDefault();
176
+ (_c = grid[pos.col][0]) == null ? void 0 : _c.focus();
177
+ break;
178
+ }
179
+ case "End": {
180
+ event.preventDefault();
181
+ (_d = grid[pos.col][grid[pos.col].length - 1]) == null ? void 0 : _d.focus();
182
+ break;
183
+ }
184
+ }
185
+ }
186
+ }
187
+ };
188
+ }, [enabled, open, context, onOpenChange]);
189
+ }
190
+ function focusFirstItem(panel, attempt = 0) {
191
+ var _a;
192
+ const grid = buildGrid(panel);
193
+ const firstItem = (_a = grid[0]) == null ? void 0 : _a[0];
194
+ if (firstItem) {
195
+ firstItem.focus();
196
+ return;
197
+ }
198
+ const view = panel.ownerDocument.defaultView;
199
+ if (attempt < 3 && view) {
200
+ view.requestAnimationFrame(() => focusFirstItem(panel, attempt + 1));
201
+ }
202
+ }
203
+
204
+ export { FOCUSABLE_SELECTOR, focusFirstItem, useMegaMenuKeyboard };
205
+ //# sourceMappingURL=useMegaMenuKeyboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMegaMenuKeyboard.js","sources":["../src/mega-menu/useMegaMenuKeyboard.ts"],"sourcesContent":["import type { ElementProps, FloatingRootContext } from \"@floating-ui/react\";\nimport { useMemo } from \"react\";\n\nconst COLUMN_SELECTOR = \"[data-mega-menu-column]\";\nconst ITEM_SELECTOR = \"[data-mega-menu-item]\";\nexport const FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Get navigable items within a column.\n * Prefers explicitly marked items (`data-mega-menu-item`), falling back\n * to all focusable elements when no marked items are found.\n */\nfunction getColumnItems(column: HTMLElement): HTMLElement[] {\n const marked = Array.from(\n column.querySelectorAll<HTMLElement>(ITEM_SELECTOR),\n );\n if (marked.length > 0) return marked;\n return Array.from(column.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n}\n\n/**\n * Build a 2D grid of navigable items from the panel DOM.\n * Each column is a `[data-mega-menu-column]` wrapper; items within each\n * column are discovered via `getColumnItems`.\n * Items not inside any column (orphans) are inserted at their DOM position\n * as single-item columns so keyboard navigation follows visual order.\n */\nfunction buildGrid(panel: HTMLElement): HTMLElement[][] {\n const columns = new Set(panel.querySelectorAll<HTMLElement>(COLUMN_SELECTOR));\n const grid: HTMLElement[][] = [];\n const processedColumns = new Set<HTMLElement>();\n\n // Walk columns and items in DOM order so orphans are interleaved correctly.\n const all = panel.querySelectorAll<HTMLElement>(\n `${COLUMN_SELECTOR}, ${ITEM_SELECTOR}`,\n );\n\n for (const el of all) {\n if (columns.has(el) && !processedColumns.has(el)) {\n processedColumns.add(el);\n const items = getColumnItems(el);\n if (items.length > 0) grid.push(items);\n } else if (el.matches(ITEM_SELECTOR)) {\n const parentCol = el.closest(COLUMN_SELECTOR);\n if (!parentCol || !columns.has(parentCol as HTMLElement)) {\n grid.push([el]);\n }\n }\n }\n\n return grid;\n}\n\nfunction findPosition(\n grid: HTMLElement[][],\n el: HTMLElement,\n): { col: number; row: number } | null {\n for (let col = 0; col < grid.length; col++) {\n const row = grid[col].indexOf(el);\n if (row !== -1) return { col, row };\n }\n return null;\n}\n\nfunction focusTrigger(context: FloatingRootContext) {\n const reference = context.elements.reference as HTMLElement | null;\n const focusable =\n reference?.querySelector<HTMLElement>(FOCUSABLE_SELECTOR) ?? reference;\n focusable?.focus();\n}\n\nfunction focusNextAfterPanel(context: FloatingRootContext, panel: HTMLElement) {\n const reference = context.elements.reference as HTMLElement | null;\n const refFocusable =\n reference?.querySelector<HTMLElement>(FOCUSABLE_SELECTOR) ?? reference;\n\n const nextSibling = refFocusable\n ?.closest(\"li\")\n ?.nextElementSibling?.querySelector<HTMLElement>(FOCUSABLE_SELECTOR);\n\n const nextOutside =\n nextSibling ||\n (() => {\n const allFocusable = Array.from(\n panel.ownerDocument.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).filter((el) => !panel.contains(el));\n const idx = refFocusable ? allFocusable.indexOf(refFocusable) : -1;\n return idx >= 0 ? allFocusable[idx + 1] : undefined;\n })();\n\n if (nextOutside) {\n const view = panel.ownerDocument.defaultView;\n view?.requestAnimationFrame(() => {\n view?.requestAnimationFrame(() => {\n nextOutside.focus();\n });\n });\n }\n}\n\nexport interface UseMegaMenuKeyboardProps {\n /**\n * Whether the interaction is enabled.\n * @default true\n */\n enabled?: boolean;\n}\n\n/**\n * Floating-ui custom interaction hook for mega menu grid keyboard navigation.\n *\n * Returns `ElementProps` that get merged via `useInteractions`, handling\n * keyboard events on both the reference (trigger) and floating (panel) elements.\n *\n * - **↑ / ↓** move within the current column.\n * - **← / →** jump to the top of the previous / next column.\n * - **Tab / Shift+Tab** move linearly through every item.\n * - **Home / End** jump to the first / last item in the column.\n * - **↑ from the first item** or **← from the first column** returns\n * focus to the trigger.\n * - **→ from the last column** closes the panel and moves focus to the\n * next sibling trigger.\n */\nexport function useMegaMenuKeyboard(\n context: FloatingRootContext,\n props: UseMegaMenuKeyboardProps = {},\n): ElementProps {\n const { enabled = true } = props;\n const { open, onOpenChange } = context;\n\n return useMemo(() => {\n if (!enabled) {\n return {};\n }\n\n return {\n reference: {\n onKeyDown(event: React.KeyboardEvent) {\n if (event.key === \"ArrowDown\" && open) {\n event.preventDefault();\n const floating = context.elements.floating;\n if (floating instanceof HTMLElement) {\n focusFirstItem(floating);\n }\n }\n },\n },\n floating: {\n onKeyDown(event: React.KeyboardEvent) {\n if (!open) return;\n\n const panel = event.currentTarget as HTMLElement;\n const target = event.target as HTMLElement;\n\n const focusedItem =\n target.closest<HTMLElement>(ITEM_SELECTOR) ??\n target.closest<HTMLElement>(FOCUSABLE_SELECTOR);\n if (!focusedItem) return;\n\n const grid = buildGrid(panel);\n const pos = findPosition(grid, focusedItem);\n if (!pos) return;\n\n const allItems = grid.flat();\n const linearIndex = allItems.indexOf(focusedItem);\n\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n const next = pos.row + 1;\n if (next < grid[pos.col].length) {\n grid[pos.col][next].focus();\n } else {\n const nextCol = pos.col + 1;\n if (nextCol < grid.length) {\n grid[nextCol][0].focus();\n }\n }\n break;\n }\n\n case \"ArrowUp\": {\n event.preventDefault();\n if (pos.row > 0) {\n grid[pos.col][pos.row - 1].focus();\n } else {\n const prevCol = pos.col - 1;\n if (prevCol >= 0) {\n grid[prevCol][grid[prevCol].length - 1].focus();\n } else {\n focusTrigger(context);\n }\n }\n break;\n }\n\n case \"ArrowRight\": {\n event.preventDefault();\n const nextCol = pos.col + 1;\n if (nextCol < grid.length) {\n grid[nextCol][0].focus();\n } else {\n // On the last column — close panel and move to next trigger\n const reference = context.elements\n .reference as HTMLElement | null;\n const trigger =\n reference?.querySelector<HTMLElement>(FOCUSABLE_SELECTOR) ??\n reference;\n const li = trigger?.closest(\"li\");\n const nextSibling =\n li?.nextElementSibling instanceof HTMLElement\n ? li.nextElementSibling.querySelector<HTMLElement>(\n FOCUSABLE_SELECTOR,\n )\n : null;\n if (nextSibling) {\n onOpenChange(false);\n nextSibling.focus();\n }\n }\n break;\n }\n\n case \"ArrowLeft\": {\n event.preventDefault();\n const prevCol = pos.col - 1;\n if (prevCol >= 0) {\n grid[prevCol][0].focus();\n } else {\n focusTrigger(context);\n }\n break;\n }\n\n case \"Tab\": {\n event.preventDefault();\n if (event.shiftKey) {\n if (linearIndex === 0) {\n focusTrigger(context);\n } else {\n allItems[linearIndex - 1]?.focus();\n }\n } else {\n if (linearIndex === allItems.length - 1) {\n onOpenChange(false);\n focusNextAfterPanel(context, panel);\n } else {\n allItems[linearIndex + 1]?.focus();\n }\n }\n break;\n }\n\n case \"Home\": {\n event.preventDefault();\n grid[pos.col][0]?.focus();\n break;\n }\n\n case \"End\": {\n event.preventDefault();\n grid[pos.col][grid[pos.col].length - 1]?.focus();\n break;\n }\n\n default:\n break;\n }\n },\n },\n };\n }, [enabled, open, context, onOpenChange]);\n}\n\n/**\n * Focus the first navigable item inside a mega menu panel.\n * Retries with `requestAnimationFrame` if content has not yet rendered.\n */\nexport function focusFirstItem(panel: HTMLElement, attempt = 0): void {\n const grid = buildGrid(panel);\n const firstItem = grid[0]?.[0];\n\n if (firstItem) {\n firstItem.focus();\n return;\n }\n\n const view = panel.ownerDocument.defaultView;\n if (attempt < 3 && view) {\n view.requestAnimationFrame(() => focusFirstItem(panel, attempt + 1));\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltSidePanel {\n background-color: var(--sidePanel-background, var(--salt-container-primary-background));\n --saltSidePanel-width: 300px;\n --sidePanel-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--sidePanel-borderColor, var(--salt-container-primary-borderColor));\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n}\n\n.saltSidePanel-primary {\n --sidePanel-background: var(--salt-container-primary-background);\n --sidePanel-borderColor: var(--salt-container-primary-borderColor);\n}\n\n.saltSidePanel-secondary {\n --sidePanel-background: var(--salt-container-secondary-background);\n --sidePanel-borderColor: var(--salt-container-secondary-borderColor);\n}\n\n.saltSidePanel-tertiary {\n --sidePanel-background: var(--salt-container-tertiary-background);\n --sidePanel-borderColor: var(--salt-container-tertiary-borderColor);\n}\n\n.saltSidePanel-left {\n border-right: var(--sidePanel-border);\n}\n.saltSidePanel-right {\n border-left: var(--sidePanel-border);\n}\n\n.saltSidePanel-none {\n --sidePanel-background: none;\n border: none;\n}\n\n.saltSidePanel-none .saltSidePanel-inner {\n padding: 0;\n}\n\n.saltSidePanel-left,\n.saltSidePanel-right {\n width: var(--saltSidePanel-width);\n height: 100%;\n min-height: 0;\n align-self: stretch;\n}\n\n.saltSidePanel-enterAnimation,\n.saltSidePanel-exitAnimation {\n overflow: hidden;\n}\n\n.saltSidePanel-left.saltSidePanel-enterAnimation,\n.saltSidePanel-right.saltSidePanel-enterAnimation {\n animation: saltSidePanel-expandWidth var(--salt-duration-perceptible) var(--salt-animation-timing-function);\n}\n\n.saltSidePanel-left.saltSidePanel-exitAnimation,\n.saltSidePanel-right.saltSidePanel-exitAnimation {\n animation: saltSidePanel-collapseWidth var(--salt-duration-perceptible) var(--salt-animation-timing-function) both;\n}\n\n.saltSidePanel-exitAnimation {\n pointer-events: none;\n}\n\n.saltSidePanel-inner {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n padding: var(--salt-spacing-300);\n}\n\n.saltSidePanel-left .saltSidePanel-inner,\n.saltSidePanel-right .saltSidePanel-inner {\n width: var(--saltSidePanel-width);\n height: 100%;\n}\n\n@keyframes saltSidePanel-expandWidth {\n from {\n width: 0;\n }\n}\n@keyframes saltSidePanel-collapseWidth {\n to {\n width: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .saltSidePanel-left.saltSidePanel-enterAnimation,\n .saltSidePanel-right.saltSidePanel-enterAnimation,\n .saltSidePanel-left.saltSidePanel-exitAnimation,\n .saltSidePanel-right.saltSidePanel-exitAnimation {\n animation: none;\n }\n}\n";
1
+ var css_248z = ".saltSidePanel {\n background-color: var(--sidePanel-background, var(--salt-container-primary-background));\n --saltSidePanel-width: 300px;\n --sidePanel-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--sidePanel-borderColor, var(--salt-container-primary-borderColor));\n --saltSidePanel-padding: var(--salt-spacing-300);\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n}\n\n.saltSidePanel-primary {\n --sidePanel-background: var(--salt-container-primary-background);\n --sidePanel-borderColor: var(--salt-container-primary-borderColor);\n}\n\n.saltSidePanel-secondary {\n --sidePanel-background: var(--salt-container-secondary-background);\n --sidePanel-borderColor: var(--salt-container-secondary-borderColor);\n}\n\n.saltSidePanel-tertiary {\n --sidePanel-background: var(--salt-container-tertiary-background);\n --sidePanel-borderColor: var(--salt-container-tertiary-borderColor);\n}\n\n.saltSidePanel-left {\n border-right: var(--sidePanel-border);\n}\n.saltSidePanel-right {\n border-left: var(--sidePanel-border);\n}\n\n.saltSidePanel-none {\n --sidePanel-background: none;\n border: none;\n}\n\n.saltSidePanel-none {\n --saltSidePanel-padding: var(--salt-spacing-200);\n}\n\n.saltSidePanel-left,\n.saltSidePanel-right {\n width: var(--saltSidePanel-width);\n height: 100%;\n min-height: 0;\n align-self: stretch;\n}\n\n.saltSidePanel-enterAnimation,\n.saltSidePanel-exitAnimation {\n overflow: hidden;\n}\n\n.saltSidePanel-left.saltSidePanel-enterAnimation,\n.saltSidePanel-right.saltSidePanel-enterAnimation {\n animation: saltSidePanel-expandWidth var(--salt-duration-perceptible) var(--salt-animation-timing-function);\n}\n\n.saltSidePanel-left.saltSidePanel-exitAnimation,\n.saltSidePanel-right.saltSidePanel-exitAnimation {\n animation: saltSidePanel-collapseWidth var(--salt-duration-perceptible) var(--salt-animation-timing-function) both;\n}\n\n.saltSidePanel-exitAnimation {\n pointer-events: none;\n}\n\n.saltSidePanel-inner {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n padding: var(--saltSidePanel-padding);\n}\n\n.saltSidePanel-left .saltSidePanel-inner,\n.saltSidePanel-right .saltSidePanel-inner {\n width: var(--saltSidePanel-width);\n height: 100%;\n}\n\n@keyframes saltSidePanel-expandWidth {\n from {\n width: 0;\n }\n}\n@keyframes saltSidePanel-collapseWidth {\n to {\n width: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .saltSidePanel-left.saltSidePanel-enterAnimation,\n .saltSidePanel-right.saltSidePanel-enterAnimation,\n .saltSidePanel-left.saltSidePanel-exitAnimation,\n .saltSidePanel-right.saltSidePanel-exitAnimation {\n animation: none;\n }\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=SidePanel.css.js.map
@@ -1,11 +1,12 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { FloatingFocusManager } from '@floating-ui/react';
3
- import { makePrefixer, useId, useFloatingUI, useForkRef } from '@salt-ds/core';
3
+ import { makePrefixer, useId, useFloatingUI, useForkRef, useIsomorphicLayoutEffect } from '@salt-ds/core';
4
4
  import { useComponentCssInjection } from '@salt-ds/styles';
5
5
  import { useWindow } from '@salt-ds/window';
6
6
  import { clsx } from 'clsx';
7
- import { forwardRef, useState, useRef, useEffect } from 'react';
8
- import { useSidePanelContext } from './internal/SidePanelContext.js';
7
+ import { forwardRef, useMemo, useState, useRef, useEffect } from 'react';
8
+ import { useSidePanelContext, SidePanelContext } from './internal/SidePanelContext.js';
9
+ import 'tabbable';
9
10
  import css_248z from './SidePanel.css.js';
10
11
 
11
12
  const withBaseName = makePrefixer("saltSidePanel");
@@ -20,19 +21,19 @@ const SidePanel = forwardRef(
20
21
  id: idProp,
21
22
  className,
22
23
  "aria-labelledby": ariaLabelledBy,
24
+ onAnimationEnd,
23
25
  ...rest
24
26
  } = props;
25
- const { openState, floatingRootContext, setFloating, setPanelId, titleId } = useSidePanelContext();
27
+ const sidePanelContext = useSidePanelContext();
28
+ const { openState, floatingRootContext, setFloating, setPanelId, titleId } = sidePanelContext;
29
+ const positionedContext = useMemo(
30
+ () => ({ ...sidePanelContext, position }),
31
+ [sidePanelContext, position]
32
+ );
26
33
  const id = useId(idProp);
27
34
  const [showComponent, setShowComponent] = useState(openState);
28
- const [animating, setAnimating] = useState(() => {
29
- var _a;
30
- if (!openState || disableAnimation) return false;
31
- const reference = floatingRootContext.elements.reference;
32
- if (!(reference instanceof Element)) return false;
33
- const activeElement = (_a = reference.ownerDocument) == null ? void 0 : _a.activeElement;
34
- return !!activeElement && reference.contains(activeElement);
35
- });
35
+ const [animating, setAnimating] = useState(false);
36
+ const shouldAnimateOpen = useRef(!openState);
36
37
  const [skipInitialFocus, setSkipInitialFocus] = useState(() => {
37
38
  var _a;
38
39
  if (!openState) return false;
@@ -41,7 +42,6 @@ const SidePanel = forwardRef(
41
42
  const activeElement = (_a = reference.ownerDocument) == null ? void 0 : _a.activeElement;
42
43
  return !activeElement || !reference.contains(activeElement);
43
44
  });
44
- const initialRender = useRef(true);
45
45
  const targetWindow = useWindow();
46
46
  useComponentCssInjection({
47
47
  testId: "salt-side-panel",
@@ -53,7 +53,8 @@ const SidePanel = forwardRef(
53
53
  });
54
54
  const handleRef = useForkRef(setFloating, ref);
55
55
  const handleAnimationEnd = (event) => {
56
- if (event.currentTarget !== event.target) return;
56
+ onAnimationEnd == null ? void 0 : onAnimationEnd(event);
57
+ if (event.currentTarget !== event.target || disableAnimation) return;
57
58
  setAnimating(false);
58
59
  if (!openState) {
59
60
  setShowComponent(false);
@@ -70,22 +71,21 @@ const SidePanel = forwardRef(
70
71
  setSkipInitialFocus(false);
71
72
  }
72
73
  }, [openState]);
73
- useEffect(() => {
74
+ useIsomorphicLayoutEffect(() => {
74
75
  var _a, _b;
75
76
  if (disableAnimation) {
76
77
  setShowComponent(openState);
77
78
  setAnimating(false);
78
- initialRender.current = false;
79
+ if (!openState) shouldAnimateOpen.current = true;
79
80
  return;
80
81
  }
81
- if (initialRender.current && openState) {
82
- const reference = floatingRootContext.elements.reference;
83
- if (!(reference instanceof Element)) {
84
- setShowComponent(true);
85
- setAnimating(false);
86
- initialRender.current = false;
87
- return;
88
- }
82
+ if (!openState) {
83
+ shouldAnimateOpen.current = true;
84
+ }
85
+ if (openState && !shouldAnimateOpen.current) {
86
+ setShowComponent(true);
87
+ setAnimating(false);
88
+ return;
89
89
  }
90
90
  const prefersReducedMotion = (_b = (_a = targetWindow == null ? void 0 : targetWindow.matchMedia) == null ? void 0 : _a.call(
91
91
  targetWindow,
@@ -102,13 +102,7 @@ const SidePanel = forwardRef(
102
102
  } else {
103
103
  setAnimating(true);
104
104
  }
105
- initialRender.current = false;
106
- }, [
107
- openState,
108
- targetWindow,
109
- disableAnimation,
110
- floatingRootContext.elements.reference
111
- ]);
105
+ }, [openState, targetWindow, disableAnimation]);
112
106
  if (!showComponent) return null;
113
107
  const resolvedInitialFocus = skipInitialFocus ? -1 : initialFocus ?? 0;
114
108
  const panelDiv = /* @__PURE__ */ jsx(
@@ -127,10 +121,11 @@ const SidePanel = forwardRef(
127
121
  },
128
122
  className
129
123
  ),
130
- onAnimationEnd: disableAnimation ? void 0 : handleAnimationEnd,
124
+ onAnimationEnd: handleAnimationEnd,
125
+ tabIndex: -1,
131
126
  ...rest,
132
127
  id,
133
- children: /* @__PURE__ */ jsx("div", { className: withBaseName("inner"), children })
128
+ children: /* @__PURE__ */ jsx(SidePanelContext.Provider, { value: positionedContext, children: /* @__PURE__ */ jsx("div", { className: withBaseName("inner"), children }) })
134
129
  }
135
130
  );
136
131
  if (openState || animating) {
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanel.js","sources":["../src/side-panel/SidePanel.tsx"],"sourcesContent":["import { FloatingFocusManager } from \"@floating-ui/react\";\nimport { makePrefixer, useFloatingUI, useForkRef, useId } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type AnimationEvent,\n type ComponentProps,\n type ComponentPropsWithRef,\n forwardRef,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useSidePanelContext } from \"./internal\";\nimport sidePanelCss from \"./SidePanel.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanel\");\n\nexport interface SidePanelProps extends ComponentPropsWithRef<\"div\"> {\n /**\n * Disable the panel's own open/close animation.\n * Set to `true` when the parent controls sizing and animation (e.g. inside a splitter).\n * @default false\n */\n disableAnimation?: boolean;\n /**\n * Edge the panel is anchored to; controls animation direction and divider side.\n * @default \"right\"\n */\n position?: \"right\" | \"left\";\n /**\n * Which element receives focus when the panel opens.\n * Pass a number for the tabbable element index (0 = first), or a ref to a specific element.\n * Defaults to the side panel close button.\n */\n initialFocus?: ComponentProps<typeof FloatingFocusManager>[\"initialFocus\"];\n /**\n * The background color palette. Options are 'primary', 'secondary', 'tertiary' and 'none'.\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"none\";\n}\n\nexport const SidePanel = forwardRef<HTMLDivElement, SidePanelProps>(\n function SidePanel(props, ref) {\n const {\n disableAnimation = false,\n position = \"right\",\n initialFocus,\n variant = \"primary\",\n children,\n id: idProp,\n className,\n \"aria-labelledby\": ariaLabelledBy,\n ...rest\n } = props;\n\n const { openState, floatingRootContext, setFloating, setPanelId, titleId } =\n useSidePanelContext();\n\n const id = useId(idProp);\n\n const [showComponent, setShowComponent] = useState(openState);\n const [animating, setAnimating] = useState(() => {\n if (!openState || disableAnimation) return false;\n // Animate on first mount only when the trigger has focus, indicating a\n // user-initiated open.\n const reference = floatingRootContext.elements.reference;\n if (!(reference instanceof Element)) return false;\n const activeElement = reference.ownerDocument?.activeElement;\n return !!activeElement && reference.contains(activeElement);\n });\n // On first mount while open, skip moving focus when focus did not come from the trigger.\n const [skipInitialFocus, setSkipInitialFocus] = useState(() => {\n if (!openState) return false;\n const reference = floatingRootContext.elements.reference;\n if (!(reference instanceof Element)) return true;\n const activeElement = reference.ownerDocument?.activeElement;\n return !activeElement || !reference.contains(activeElement);\n });\n // Track whether this is the initial render to skip the open animation.\n const initialRender = useRef(true);\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel\",\n css: sidePanelCss,\n window: targetWindow,\n });\n\n const { context } = useFloatingUI({\n rootContext: floatingRootContext,\n });\n\n const handleRef = useForkRef<HTMLDivElement>(setFloating, ref);\n\n const handleAnimationEnd = (event: AnimationEvent<HTMLDivElement>) => {\n if (event.currentTarget !== event.target) return;\n setAnimating(false);\n if (!openState) {\n setShowComponent(false);\n }\n };\n\n useEffect(() => {\n // Keep this as state (not ref): setPanelId causes a context re-render and\n // this value is consumed as a prop for initial focus behavior.\n setPanelId(id);\n\n return () => {\n setPanelId(undefined);\n };\n }, [id, setPanelId]);\n\n useEffect(() => {\n if (!openState) {\n setSkipInitialFocus(false);\n }\n }, [openState]);\n\n useEffect(() => {\n if (disableAnimation) {\n // When animation is disabled, show/hide immediately since there is\n // no exit animation to wait for before unmounting.\n setShowComponent(openState);\n setAnimating(false);\n initialRender.current = false;\n return;\n }\n\n // Skip animation on initial render when panel is already open\n // without a trigger interaction (i.e. defaultOpen scenario).\n if (initialRender.current && openState) {\n const reference = floatingRootContext.elements.reference;\n if (!(reference instanceof Element)) {\n setShowComponent(true);\n setAnimating(false);\n initialRender.current = false;\n return;\n }\n }\n\n const prefersReducedMotion = targetWindow?.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n )?.matches;\n\n if (openState) {\n setShowComponent(true);\n }\n\n if (prefersReducedMotion) {\n setAnimating(false);\n if (!openState) {\n setShowComponent(false);\n }\n } else {\n setAnimating(true);\n }\n\n initialRender.current = false;\n }, [\n openState,\n targetWindow,\n disableAnimation,\n floatingRootContext.elements.reference,\n ]);\n\n if (!showComponent) return null;\n\n // `-1` skips initial focus movement but preserves focus guards/return focus handling.\n const resolvedInitialFocus = skipInitialFocus ? -1 : (initialFocus ?? 0);\n\n const panelDiv = (\n <div\n role=\"region\"\n aria-labelledby={clsx(ariaLabelledBy, titleId) || undefined}\n ref={handleRef}\n className={clsx(\n withBaseName(),\n {\n [withBaseName(position)]: position,\n [withBaseName(variant)]: variant,\n [withBaseName(\"enterAnimation\")]:\n !disableAnimation && openState && animating,\n [withBaseName(\"exitAnimation\")]:\n !disableAnimation && !openState && animating,\n },\n className,\n )}\n onAnimationEnd={disableAnimation ? undefined : handleAnimationEnd}\n {...rest}\n id={id}\n >\n <div className={withBaseName(\"inner\")}>{children}</div>\n </div>\n );\n\n if (openState || animating) {\n return (\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={resolvedInitialFocus}\n closeOnFocusOut={false}\n guards={false}\n >\n {panelDiv}\n </FloatingFocusManager>\n );\n }\n\n return panelDiv;\n },\n);\n"],"names":["SidePanel","sidePanelCss"],"mappings":"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"}
1
+ {"version":3,"file":"SidePanel.js","sources":["../src/side-panel/SidePanel.tsx"],"sourcesContent":["import { FloatingFocusManager } from \"@floating-ui/react\";\nimport {\n makePrefixer,\n useFloatingUI,\n useForkRef,\n useId,\n useIsomorphicLayoutEffect,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type AnimationEvent,\n type ComponentProps,\n type ComponentPropsWithRef,\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { SidePanelContext, useSidePanelContext } from \"./internal\";\nimport sidePanelCss from \"./SidePanel.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanel\");\n\nexport interface SidePanelProps extends ComponentPropsWithRef<\"div\"> {\n /**\n * Disable the panel's own open/close animation.\n * Set to `true` when the parent controls sizing and animation (e.g. inside a splitter).\n * @default false\n */\n disableAnimation?: boolean;\n /**\n * Edge the panel is anchored to; controls animation direction and divider side.\n * @default \"right\"\n */\n position?: \"right\" | \"left\";\n /**\n * Which element receives focus when the panel opens.\n * Pass a number for the tabbable element index (0 = first), or a ref to a specific element.\n * Defaults to the side panel close button.\n */\n initialFocus?: ComponentProps<typeof FloatingFocusManager>[\"initialFocus\"];\n /**\n * The background color palette. Options are 'primary', 'secondary', 'tertiary' and 'none'.\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\" | \"tertiary\" | \"none\";\n}\n\nexport const SidePanel = forwardRef<HTMLDivElement, SidePanelProps>(\n function SidePanel(props, ref) {\n const {\n disableAnimation = false,\n position = \"right\",\n initialFocus,\n variant = \"primary\",\n children,\n id: idProp,\n className,\n \"aria-labelledby\": ariaLabelledBy,\n onAnimationEnd,\n ...rest\n } = props;\n\n const sidePanelContext = useSidePanelContext();\n const { openState, floatingRootContext, setFloating, setPanelId, titleId } =\n sidePanelContext;\n const positionedContext = useMemo(\n () => ({ ...sidePanelContext, position }),\n [sidePanelContext, position],\n );\n\n const id = useId(idProp);\n\n const [showComponent, setShowComponent] = useState(openState);\n const [animating, setAnimating] = useState(false);\n const shouldAnimateOpen = useRef(!openState);\n // On first mount while open, skip moving focus when focus did not come from the trigger.\n const [skipInitialFocus, setSkipInitialFocus] = useState(() => {\n if (!openState) return false;\n const reference = floatingRootContext.elements.reference;\n if (!(reference instanceof Element)) return true;\n const activeElement = reference.ownerDocument?.activeElement;\n return !activeElement || !reference.contains(activeElement);\n });\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel\",\n css: sidePanelCss,\n window: targetWindow,\n });\n\n const { context } = useFloatingUI({\n rootContext: floatingRootContext,\n });\n\n const handleRef = useForkRef<HTMLDivElement>(setFloating, ref);\n\n const handleAnimationEnd = (event: AnimationEvent<HTMLDivElement>) => {\n onAnimationEnd?.(event);\n\n if (event.currentTarget !== event.target || disableAnimation) return;\n setAnimating(false);\n if (!openState) {\n setShowComponent(false);\n }\n };\n\n useEffect(() => {\n setPanelId(id);\n return () => {\n setPanelId(undefined);\n };\n }, [id, setPanelId]);\n\n useEffect(() => {\n if (!openState) {\n setSkipInitialFocus(false);\n }\n }, [openState]);\n\n useIsomorphicLayoutEffect(() => {\n if (disableAnimation) {\n setShowComponent(openState);\n setAnimating(false);\n if (!openState) shouldAnimateOpen.current = true;\n return;\n }\n\n if (!openState) {\n shouldAnimateOpen.current = true;\n }\n\n // Don't animate if the panel has never been closed (defaultOpen scenario).\n if (openState && !shouldAnimateOpen.current) {\n setShowComponent(true);\n setAnimating(false);\n return;\n }\n\n const prefersReducedMotion = targetWindow?.matchMedia?.(\n \"(prefers-reduced-motion: reduce)\",\n )?.matches;\n\n if (openState) {\n setShowComponent(true);\n }\n\n if (prefersReducedMotion) {\n setAnimating(false);\n if (!openState) {\n setShowComponent(false);\n }\n } else {\n setAnimating(true);\n }\n }, [openState, targetWindow, disableAnimation]);\n\n if (!showComponent) return null;\n\n const resolvedInitialFocus = skipInitialFocus ? -1 : (initialFocus ?? 0);\n\n const panelDiv = (\n <div\n role=\"region\"\n aria-labelledby={clsx(ariaLabelledBy, titleId) || undefined}\n ref={handleRef}\n className={clsx(\n withBaseName(),\n {\n [withBaseName(position)]: position,\n [withBaseName(variant)]: variant,\n [withBaseName(\"enterAnimation\")]:\n !disableAnimation && openState && animating,\n [withBaseName(\"exitAnimation\")]:\n !disableAnimation && !openState && animating,\n },\n className,\n )}\n onAnimationEnd={handleAnimationEnd}\n tabIndex={-1}\n {...rest}\n id={id}\n >\n <SidePanelContext.Provider value={positionedContext}>\n <div className={withBaseName(\"inner\")}>{children}</div>\n </SidePanelContext.Provider>\n </div>\n );\n\n if (openState || animating) {\n return (\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={resolvedInitialFocus}\n closeOnFocusOut={false}\n guards={false}\n >\n {panelDiv}\n </FloatingFocusManager>\n );\n }\n\n return panelDiv;\n },\n);\n"],"names":["SidePanel","sidePanelCss"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { makePrefixer, useIcon, useId, Button } from '@salt-ds/core';
3
+ import { clsx } from 'clsx';
4
+ import { forwardRef } from 'react';
5
+ import { useSidePanelContext } from './internal/SidePanelContext.js';
6
+ import 'tabbable';
7
+
8
+ const withBaseName = makePrefixer("saltSidePanelCloseButton");
9
+ const SidePanelCloseButton = forwardRef(
10
+ function SidePanelCloseButton2({ className, onClick, id: idProp, ...rest }, ref) {
11
+ const { CollapseLeftIcon, CollapseRightIcon } = useIcon();
12
+ const { setOpen, titleId, position } = useSidePanelContext();
13
+ const closeButtonId = useId(idProp);
14
+ const handleClick = (event) => {
15
+ onClick == null ? void 0 : onClick(event);
16
+ setOpen(false);
17
+ };
18
+ return /* @__PURE__ */ jsx(
19
+ Button,
20
+ {
21
+ ref,
22
+ id: closeButtonId,
23
+ "aria-label": "Close",
24
+ "aria-labelledby": titleId ? clsx(closeButtonId, titleId) : void 0,
25
+ appearance: "transparent",
26
+ className: clsx(withBaseName(), className),
27
+ onClick: handleClick,
28
+ ...rest,
29
+ children: position === "left" ? /* @__PURE__ */ jsx(CollapseLeftIcon, { "aria-hidden": true }) : /* @__PURE__ */ jsx(CollapseRightIcon, { "aria-hidden": true })
30
+ }
31
+ );
32
+ }
33
+ );
34
+
35
+ export { SidePanelCloseButton };
36
+ //# sourceMappingURL=SidePanelCloseButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SidePanelCloseButton.js","sources":["../src/side-panel/SidePanelCloseButton.tsx"],"sourcesContent":["import {\n Button,\n type ButtonProps,\n makePrefixer,\n useIcon,\n useId,\n} from \"@salt-ds/core\";\nimport { clsx } from \"clsx\";\nimport { forwardRef, type MouseEvent } from \"react\";\nimport { useSidePanelContext } from \"./internal\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelCloseButton\");\n\nexport const SidePanelCloseButton = forwardRef<HTMLButtonElement, ButtonProps>(\n function SidePanelCloseButton(\n { className, onClick, id: idProp, ...rest },\n ref,\n ) {\n const { CollapseLeftIcon, CollapseRightIcon } = useIcon();\n const { setOpen, titleId, position } = useSidePanelContext();\n const closeButtonId = useId(idProp);\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n setOpen(false);\n };\n\n return (\n <Button\n ref={ref}\n id={closeButtonId}\n aria-label=\"Close\"\n aria-labelledby={titleId ? clsx(closeButtonId, titleId) : undefined}\n appearance=\"transparent\"\n className={clsx(withBaseName(), className)}\n onClick={handleClick}\n {...rest}\n >\n {position === \"left\" ? (\n <CollapseLeftIcon aria-hidden />\n ) : (\n <CollapseRightIcon aria-hidden />\n )}\n </Button>\n );\n },\n);\n"],"names":["SidePanelCloseButton"],"mappings":";;;;;;;AAWA,MAAM,YAAA,GAAe,aAAa,0BAA0B,CAAA;AAErD,MAAM,oBAAA,GAAuB,UAAA;AAAA,EAClC,SAASA,qBAAAA,CACP,EAAE,SAAA,EAAW,OAAA,EAAS,IAAI,MAAA,EAAQ,GAAG,IAAA,EAAK,EAC1C,GAAA,EACA;AACA,IAAA,MAAM,EAAE,gBAAA,EAAkB,iBAAA,EAAkB,GAAI,OAAA,EAAQ;AACxD,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,QAAA,KAAa,mBAAA,EAAoB;AAC3D,IAAA,MAAM,aAAA,GAAgB,MAAM,MAAM,CAAA;AAElC,IAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAyC;AAC5D,MAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAU,KAAA,CAAA;AACV,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,EAAA,EAAI,aAAA;AAAA,QACJ,YAAA,EAAW,OAAA;AAAA,QACX,iBAAA,EAAiB,OAAA,GAAU,IAAA,CAAK,aAAA,EAAe,OAAO,CAAA,GAAI,MAAA;AAAA,QAC1D,UAAA,EAAW,aAAA;AAAA,QACX,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACzC,OAAA,EAAS,WAAA;AAAA,QACR,GAAG,IAAA;AAAA,QAEH,QAAA,EAAA,QAAA,KAAa,MAAA,mBACZ,GAAA,CAAC,gBAAA,EAAA,EAAiB,aAAA,EAAW,MAAC,CAAA,mBAE9B,GAAA,CAAC,iBAAA,EAAA,EAAkB,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA,KAEnC;AAAA,EAEJ;AACF;;;;"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltSidePanelContent {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n box-sizing: border-box;\n}\n\n.saltSidePanelContent-body {\n flex: 1;\n overflow: auto;\n}\n";
1
+ var css_248z = ".saltSidePanelContent {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n.saltSidePanelContent-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=SidePanelContent.css.js.map
@@ -3,8 +3,10 @@ import { makePrefixer, useId } from '@salt-ds/core';
3
3
  import { useComponentCssInjection } from '@salt-ds/styles';
4
4
  import { useWindow } from '@salt-ds/window';
5
5
  import { clsx } from 'clsx';
6
- import { forwardRef, useRef, useState, useEffect } from 'react';
6
+ import { forwardRef, useRef } from 'react';
7
7
  import { useSidePanelContext } from './internal/SidePanelContext.js';
8
+ import { useIsScrollable } from './internal/useIsScrollable.js';
9
+ import 'tabbable';
8
10
  import css_248z from './SidePanelContent.css.js';
9
11
 
10
12
  const withBaseName = makePrefixer("saltSidePanelContent");
@@ -20,29 +22,7 @@ const SidePanelContent = forwardRef(function SidePanelContent2(props, ref) {
20
22
  const targetWindow = useWindow();
21
23
  const contentSuffixId = useId();
22
24
  const bodyRef = useRef(null);
23
- const [isScrollable, setIsScrollable] = useState(false);
24
- useEffect(() => {
25
- const bodyElement = bodyRef.current;
26
- if (!bodyElement) {
27
- return;
28
- }
29
- const checkScrollable = () => {
30
- setIsScrollable(
31
- bodyElement.scrollHeight > bodyElement.clientHeight || bodyElement.scrollWidth > bodyElement.clientWidth
32
- );
33
- };
34
- checkScrollable();
35
- const resizeObserver = new ResizeObserver(() => {
36
- checkScrollable();
37
- });
38
- resizeObserver.observe(bodyElement);
39
- const mutationObserver = new MutationObserver(checkScrollable);
40
- mutationObserver.observe(bodyElement, { childList: true, subtree: true });
41
- return () => {
42
- resizeObserver.disconnect();
43
- mutationObserver.disconnect();
44
- };
45
- }, []);
25
+ const isScrollable = useIsScrollable(bodyRef);
46
26
  useComponentCssInjection({
47
27
  testId: "salt-side-panel-content",
48
28
  css: css_248z,
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanelContent.js","sources":["../src/side-panel/SidePanelContent.tsx"],"sourcesContent":["import { makePrefixer, useId } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithRef,\n forwardRef,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useSidePanelContext } from \"./internal\";\nimport sidePanelContentCss from \"./SidePanelContent.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelContent\");\n\nexport interface SidePanelContentProps extends ComponentPropsWithRef<\"div\"> {}\n\nexport const SidePanelContent = forwardRef<\n HTMLDivElement,\n SidePanelContentProps\n>(function SidePanelContent(props, ref) {\n const {\n children,\n className,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-label\": ariaLabel,\n ...rest\n } = props;\n\n const { titleId } = useSidePanelContext();\n const targetWindow = useWindow();\n const contentSuffixId = useId();\n const bodyRef = useRef<HTMLDivElement | null>(null);\n const [isScrollable, setIsScrollable] = useState(false);\n\n // Monitor scrollability of the body element\n useEffect(() => {\n const bodyElement = bodyRef.current;\n if (!bodyElement) {\n return;\n }\n\n const checkScrollable = () => {\n // Element is scrollable if scrollHeight > clientHeight\n setIsScrollable(\n bodyElement.scrollHeight > bodyElement.clientHeight ||\n bodyElement.scrollWidth > bodyElement.clientWidth,\n );\n };\n\n // Check immediately\n checkScrollable();\n\n // Use ResizeObserver to detect when the panel resizes\n const resizeObserver = new ResizeObserver(() => {\n checkScrollable();\n });\n\n resizeObserver.observe(bodyElement);\n\n // Use MutationObserver to detect when dynamic content is added/removed,\n // since child size changes don't trigger ResizeObserver on the parent.\n const mutationObserver = new MutationObserver(checkScrollable);\n mutationObserver.observe(bodyElement, { childList: true, subtree: true });\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n }, []);\n\n useComponentCssInjection({\n testId: \"salt-side-panel-content\",\n css: sidePanelContentCss,\n window: targetWindow,\n });\n\n const explicitLabelledBy = ariaLabelledBy;\n const explicitLabel = ariaLabel;\n\n let bodyAriaLabelledBy: string | undefined;\n let bodyAriaLabel: string | undefined;\n\n if (isScrollable) {\n if (explicitLabelledBy) {\n bodyAriaLabelledBy = explicitLabelledBy;\n } else if (titleId) {\n bodyAriaLabelledBy = clsx(titleId, contentSuffixId) || undefined;\n } else {\n bodyAriaLabel = explicitLabel ?? \"Content\";\n }\n }\n\n return (\n <div ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {isScrollable ? (\n <span id={contentSuffixId} hidden>\n content\n </span>\n ) : null}\n <div\n ref={bodyRef}\n className={withBaseName(\"body\")}\n {...(isScrollable && {\n role: \"region\",\n tabIndex: 0,\n \"aria-labelledby\": bodyAriaLabelledBy,\n \"aria-label\": bodyAriaLabel,\n })}\n >\n {children}\n </div>\n </div>\n );\n});\n"],"names":["SidePanelContent","sidePanelContentCss"],"mappings":"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"}
1
+ {"version":3,"file":"SidePanelContent.js","sources":["../src/side-panel/SidePanelContent.tsx"],"sourcesContent":["import { makePrefixer, useId } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentPropsWithRef, forwardRef, useRef } from \"react\";\nimport { useIsScrollable, useSidePanelContext } from \"./internal\";\nimport sidePanelContentCss from \"./SidePanelContent.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelContent\");\n\nexport interface SidePanelContentProps extends ComponentPropsWithRef<\"div\"> {}\n\nexport const SidePanelContent = forwardRef<\n HTMLDivElement,\n SidePanelContentProps\n>(function SidePanelContent(props, ref) {\n const {\n children,\n className,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-label\": ariaLabel,\n ...rest\n } = props;\n\n const { titleId } = useSidePanelContext();\n const targetWindow = useWindow();\n const contentSuffixId = useId();\n const bodyRef = useRef<HTMLDivElement>(null);\n const isScrollable = useIsScrollable(bodyRef);\n\n useComponentCssInjection({\n testId: \"salt-side-panel-content\",\n css: sidePanelContentCss,\n window: targetWindow,\n });\n\n const explicitLabelledBy = ariaLabelledBy;\n const explicitLabel = ariaLabel;\n\n let bodyAriaLabelledBy: string | undefined;\n let bodyAriaLabel: string | undefined;\n\n if (isScrollable) {\n if (explicitLabelledBy) {\n bodyAriaLabelledBy = explicitLabelledBy;\n } else if (titleId) {\n bodyAriaLabelledBy = clsx(titleId, contentSuffixId) || undefined;\n } else {\n bodyAriaLabel = explicitLabel ?? \"Content\";\n }\n }\n\n return (\n <div ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {isScrollable ? (\n <span id={contentSuffixId} hidden>\n content\n </span>\n ) : null}\n <div\n ref={bodyRef}\n className={withBaseName(\"body\")}\n {...(isScrollable && {\n role: \"region\",\n tabIndex: 0,\n \"aria-labelledby\": bodyAriaLabelledBy,\n \"aria-label\": bodyAriaLabel,\n })}\n >\n {children}\n </div>\n </div>\n );\n});\n"],"names":["SidePanelContent","sidePanelContentCss"],"mappings":";;;;;;;;;;;AAQA,MAAM,YAAA,GAAe,aAAa,sBAAsB,CAAA;AAIjD,MAAM,gBAAA,GAAmB,UAAA,CAG9B,SAASA,iBAAAA,CAAiB,OAAO,GAAA,EAAK;AACtC,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,SAAA;AAAA,IACA,iBAAA,EAAmB,cAAA;AAAA,IACnB,YAAA,EAAc,SAAA;AAAA,IACd,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,mBAAA,EAAoB;AACxC,EAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,EAAA,MAAM,kBAAkB,KAAA,EAAM;AAC9B,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,YAAA,GAAe,gBAAgB,OAAO,CAAA;AAE5C,EAAA,wBAAA,CAAyB;AAAA,IACvB,MAAA,EAAQ,yBAAA;AAAA,IACR,GAAA,EAAKC,QAAA;AAAA,IACL,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,kBAAA,GAAqB,cAAA;AAC3B,EAAA,MAAM,aAAA,GAAgB,SAAA;AAEtB,EAAA,IAAI,kBAAA;AACJ,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,IAAI,kBAAA,EAAoB;AACtB,MAAA,kBAAA,GAAqB,kBAAA;AAAA,IACvB,WAAW,OAAA,EAAS;AAClB,MAAA,kBAAA,GAAqB,IAAA,CAAK,OAAA,EAAS,eAAe,CAAA,IAAK,MAAA;AAAA,IACzD,CAAA,MAAO;AACL,MAAA,aAAA,GAAgB,aAAA,IAAiB,SAAA;AAAA,IACnC;AAAA,EACF;AAEA,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,SAAA,EAAW,IAAA,CAAK,cAAa,EAAG,SAAS,CAAA,EAAI,GAAG,IAAA,EAC5D,QAAA,EAAA;AAAA,IAAA,YAAA,uBACE,MAAA,EAAA,EAAK,EAAA,EAAI,iBAAiB,MAAA,EAAM,IAAA,EAAC,qBAElC,CAAA,GACE,IAAA;AAAA,oBACJ,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,OAAA;AAAA,QACL,SAAA,EAAW,aAAa,MAAM,CAAA;AAAA,QAC7B,GAAI,YAAA,IAAgB;AAAA,UACnB,IAAA,EAAM,QAAA;AAAA,UACN,QAAA,EAAU,CAAA;AAAA,UACV,iBAAA,EAAmB,kBAAA;AAAA,UACnB,YAAA,EAAc;AAAA,SAChB;AAAA,QAEC;AAAA;AAAA;AACH,GAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltSidePanelHeader {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n gap: var(--salt-spacing-100);\n padding: 0 0 var(--salt-spacing-300);\n}\n";
1
+ var css_248z = ".saltSidePanelHeader {\n display: flex;\n align-items: flex-start;\n flex-shrink: 0;\n gap: var(--salt-spacing-100);\n padding: 0 0 var(--salt-spacing-300);\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=SidePanelHeader.css.js.map
@@ -3,6 +3,7 @@ import { useFloatingRootContext } from '@floating-ui/react';
3
3
  import { useControlled } from '@salt-ds/core';
4
4
  import { useCallback, useState, useEffect, useMemo } from 'react';
5
5
  import { SidePanelContext } from './internal/SidePanelContext.js';
6
+ import { useSidePanelTabOrder } from './internal/useSidePanelTabOrder.js';
6
7
 
7
8
  function SidePanelProvider(props) {
8
9
  const { children, open: openProp, defaultOpen, onOpenChange } = props;
@@ -23,6 +24,9 @@ function SidePanelProvider(props) {
23
24
  const [floating, setFloating] = useState(null);
24
25
  const [panelId, setPanelId] = useState(void 0);
25
26
  const [titleId, setTitleId] = useState(void 0);
27
+ const [position, setPosition] = useState(
28
+ void 0
29
+ );
26
30
  const floatingRootContext = useFloatingRootContext({
27
31
  open: openState,
28
32
  onOpenChange: handleOpenChange,
@@ -48,6 +52,11 @@ function SidePanelProvider(props) {
48
52
  floating.removeEventListener("keydown", onKeyDown);
49
53
  };
50
54
  }, [floating, openState, handleOpenChange]);
55
+ useSidePanelTabOrder({
56
+ floating,
57
+ open: openState,
58
+ reference
59
+ });
51
60
  const context = useMemo(
52
61
  () => ({
53
62
  openState,
@@ -58,9 +67,18 @@ function SidePanelProvider(props) {
58
67
  panelId,
59
68
  setPanelId,
60
69
  titleId,
61
- setTitleId
70
+ setTitleId,
71
+ position,
72
+ setPosition
62
73
  }),
63
- [openState, floatingRootContext, handleOpenChange, panelId, titleId]
74
+ [
75
+ openState,
76
+ floatingRootContext,
77
+ handleOpenChange,
78
+ panelId,
79
+ titleId,
80
+ position
81
+ ]
64
82
  );
65
83
  return /* @__PURE__ */ jsx(SidePanelContext.Provider, { value: context, children });
66
84
  }