@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
@@ -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 {\n makePrefixer,\n useEventCallback,\n useForkRef,\n useId,\n useIsomorphicLayoutEffect,\n usePrevious,\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 ComponentPropsWithRef,\n forwardRef,\n type RefObject,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { tabbable } from \"tabbable\";\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 first tabbable element inside the panel (close button if present).\n */\n initialFocus?: number | RefObject<HTMLElement | null>;\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, setFloating, setPanelId, titleId } = 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 // Stays true until a ref-callback invocation observes focus already\n // inside the trigger (a user-driven open). Flipping this from a mount\n // effect would break under React 18 strict-mode double-mounting.\n const initialMountRef = useRef(true);\n const panelRef = useRef<HTMLDivElement | null>(null);\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel\",\n css: sidePanelCss,\n window: targetWindow,\n });\n\n // Guards against re-focusing the panel multiple times per open session.\n const initialFocusDoneRef = useRef(false);\n useEffect(() => {\n if (!openState) {\n initialFocusDoneRef.current = false;\n }\n }, [openState]);\n\n // useEventCallback keeps a stable identity while always reading the\n // latest closure, so React doesn't tear down and re-invoke the ref\n // callback per render.\n const handleInitialFocus = useEventCallback((el: HTMLDivElement | null) => {\n if (!el || !openState || initialFocusDoneRef.current) {\n return;\n }\n\n // On first mount, only auto-focus if focus is already in the trigger\n // (the common click path). For defaultOpen without user interaction\n // we leave focus alone.\n if (initialMountRef.current) {\n const reference =\n sidePanelContext.floatingRootContext.elements.reference;\n const activeElement =\n reference instanceof Element\n ? reference.ownerDocument?.activeElement\n : null;\n const focusCameFromTrigger =\n reference instanceof Element &&\n activeElement instanceof Node &&\n reference.contains(activeElement);\n if (!focusCameFromTrigger) {\n return;\n }\n initialMountRef.current = false;\n }\n\n initialFocusDoneRef.current = true;\n // Defer one frame so useSidePanelTabOrder has marked descendants\n // with data-salt-original-tabindex and any child layout effects\n // (e.g. SidePanelContent's scrollable-body tabIndex toggle) have\n // settled. Scoped to the panel's owner window for iframe/shadow-root\n // hosts.\n const raf =\n el.ownerDocument.defaultView?.requestAnimationFrame ??\n targetWindow?.requestAnimationFrame ??\n requestAnimationFrame;\n raf(() => {\n if (!el.isConnected) return;\n const focusTarget = resolveInitialFocusTarget(el, initialFocus);\n focusTarget?.focus();\n });\n });\n\n const setPanelEl = useEventCallback((el: HTMLDivElement | null) => {\n panelRef.current = el;\n setFloating(el);\n handleInitialFocus(el);\n });\n\n const handleRef = useForkRef<HTMLDivElement>(setPanelEl, ref);\n\n // Snapshot the panel's natural width (in px) into a CSS variable so the\n // inner can keep its full size while the outer animates between 0 and\n // its target width. This makes percentage values for\n // --saltSidePanel-width work, since the inner no longer resolves a\n // percentage against the outer's animating width.\n useIsomorphicLayoutEffect(() => {\n if (!animating || disableAnimation) return;\n const panel = panelRef.current;\n if (!panel) return;\n\n // Read the natural width with the animation suspended so we see the\n // resting size rather than the in-flight interpolated value.\n // getBoundingClientRect() flushes style/layout, so the inline\n // `animation: none` takes effect for this read.\n const previousAnimation = panel.style.animation;\n panel.style.animation = \"none\";\n const widthPx = panel.getBoundingClientRect().width;\n panel.style.animation = previousAnimation;\n\n panel.style.setProperty(\n \"--saltSidePanel-animation-width\",\n `${widthPx}px`,\n );\n\n return () => {\n panel.style.removeProperty(\"--saltSidePanel-animation-width\");\n };\n }, [animating, disableAnimation]);\n\n const handleAnimationEnd = useEventCallback(\n (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\n useEffect(() => {\n setPanelId(id);\n return () => {\n setPanelId(undefined);\n };\n }, [id, setPanelId]);\n\n // Return focus to the trigger on close (mirrors floating-ui's\n // returnFocus). Initial previousOpenState of `false` ensures we never\n // restore on mount — only on a real true→false transition.\n const reference = sidePanelContext.floatingRootContext.elements.reference;\n const previousOpenState = usePrevious(openState, [openState], false);\n useEffect(() => {\n if (!previousOpenState || openState) return;\n const panel = panelRef.current;\n if (!(reference instanceof HTMLElement)) return;\n const doc = reference.ownerDocument;\n const active = doc?.activeElement;\n const focusInsidePanel =\n panel && active instanceof Node && panel.contains(active);\n const focusOnBody = active === doc?.body || active == null;\n if (focusInsidePanel || focusOnBody) {\n reference.focus();\n }\n }, [openState, previousOpenState, reference]);\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 // Skip enter animation when the panel was open from the start.\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 return (\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);\n\nfunction resolveInitialFocusTarget(\n panel: HTMLElement,\n initialFocus: SidePanelProps[\"initialFocus\"],\n): HTMLElement | null {\n if (initialFocus && typeof initialFocus === \"object\") {\n return initialFocus.current ?? null;\n }\n\n // Prefer the panel's \"managed\" sequence (elements detached from the\n // natural tab order by useSidePanelTabOrder), falling back to a fresh\n // tabbable() scan when detachment hasn't run yet.\n const managed = Array.from(\n panel.querySelectorAll<HTMLElement>(\"[data-salt-original-tabindex]\"),\n );\n\n const candidates = managed.length\n ? managed\n : (tabbable(panel, { displayCheck: \"none\" }) as HTMLElement[]);\n\n const index = typeof initialFocus === \"number\" ? initialFocus : 0;\n return candidates[index] ?? candidates[0] ?? panel;\n}\n"],"names":["SidePanel","sidePanelCss","reference"],"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 type SidePanelContentProps = 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
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanelHeader.js","sources":["../src/side-panel/SidePanelHeader.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentPropsWithRef, forwardRef } from \"react\";\nimport sidePanelHeaderCss from \"./SidePanelHeader.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelHeader\");\n\nexport interface SidePanelHeaderProps extends ComponentPropsWithRef<\"div\"> {}\n\nexport const SidePanelHeader = forwardRef<HTMLDivElement, SidePanelHeaderProps>(\n function SidePanelHeader(props, ref) {\n const { children, className, ...rest } = props;\n\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel-header\",\n css: sidePanelHeaderCss,\n window: targetWindow,\n });\n\n return (\n <div ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {children}\n </div>\n );\n },\n);\n"],"names":["SidePanelHeader","sidePanelHeaderCss"],"mappings":";;;;;;;;AAOA,MAAM,YAAA,GAAe,aAAa,qBAAqB,CAAA;AAIhD,MAAM,eAAA,GAAkB,UAAA;AAAA,EAC7B,SAASA,gBAAAA,CAAgB,KAAA,EAAO,GAAA,EAAK;AACnC,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,GAAG,MAAK,GAAI,KAAA;AAEzC,IAAA,MAAM,eAAe,SAAA,EAAU;AAE/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,wBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA,EAAI,GAAG,IAAA,EAC5D,QAAA,EACH,CAAA;AAAA,EAEJ;AACF;;;;"}
1
+ {"version":3,"file":"SidePanelHeader.js","sources":["../src/side-panel/SidePanelHeader.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentPropsWithRef, forwardRef } from \"react\";\nimport sidePanelHeaderCss from \"./SidePanelHeader.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelHeader\");\n\nexport type SidePanelHeaderProps = ComponentPropsWithRef<\"div\">;\n\nexport const SidePanelHeader = forwardRef<HTMLDivElement, SidePanelHeaderProps>(\n function SidePanelHeader(props, ref) {\n const { children, className, ...rest } = props;\n\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel-header\",\n css: sidePanelHeaderCss,\n window: targetWindow,\n });\n\n return (\n <div ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {children}\n </div>\n );\n },\n);\n"],"names":["SidePanelHeader","sidePanelHeaderCss"],"mappings":";;;;;;;;AAOA,MAAM,YAAA,GAAe,aAAa,qBAAqB,CAAA;AAIhD,MAAM,eAAA,GAAkB,UAAA;AAAA,EAC7B,SAASA,gBAAAA,CAAgB,KAAA,EAAO,GAAA,EAAK;AACnC,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,GAAG,MAAK,GAAI,KAAA;AAEzC,IAAA,MAAM,eAAe,SAAA,EAAU;AAE/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,wBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA,EAAI,GAAG,IAAA,EAC5D,QAAA,EACH,CAAA;AAAA,EAEJ;AACF;;;;"}
@@ -1,8 +1,9 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useFloatingRootContext } from '@floating-ui/react';
3
3
  import { useControlled } from '@salt-ds/core';
4
- import { useCallback, useState, useEffect, useMemo } from 'react';
4
+ import { useCallback, useState, useMemo, useEffect } 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,13 +24,14 @@ 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 elements = useMemo(
28
+ () => ({ reference, floating }),
29
+ [reference, floating]
30
+ );
26
31
  const floatingRootContext = useFloatingRootContext({
27
32
  open: openState,
28
33
  onOpenChange: handleOpenChange,
29
- elements: {
30
- reference,
31
- floating
32
- }
34
+ elements
33
35
  });
34
36
  useEffect(() => {
35
37
  if (!openState || !floating) {
@@ -48,6 +50,11 @@ function SidePanelProvider(props) {
48
50
  floating.removeEventListener("keydown", onKeyDown);
49
51
  };
50
52
  }, [floating, openState, handleOpenChange]);
53
+ useSidePanelTabOrder({
54
+ floating,
55
+ open: openState,
56
+ reference
57
+ });
51
58
  const context = useMemo(
52
59
  () => ({
53
60
  openState,
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanelProvider.js","sources":["../src/side-panel/SidePanelProvider.tsx"],"sourcesContent":["import { useFloatingRootContext } from \"@floating-ui/react\";\nimport { useControlled } from \"@salt-ds/core\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { SidePanelContext } from \"./internal\";\n\nexport interface SidePanelProviderProps {\n /**\n * Whether the panel is open.\n */\n open?: boolean;\n /**\n * Default open state when initially rendered.\n */\n defaultOpen?: boolean;\n /**\n * Callback when open state changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * SidePanelProvider children, should include SidePanel and SidePanelTrigger.\n */\n children: ReactNode;\n}\n\nexport function SidePanelProvider(props: SidePanelProviderProps) {\n const { children, open: openProp, defaultOpen, onOpenChange } = props;\n\n const [openState, setOpenState] = useControlled({\n default: Boolean(defaultOpen),\n controlled: openProp,\n name: \"SidePanelProvider\",\n state: \"open\",\n });\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setOpenState(newOpen);\n onOpenChange?.(newOpen);\n },\n [onOpenChange],\n );\n\n const [reference, setReference] = useState<HTMLElement | null>(null);\n const [floating, setFloating] = useState<HTMLDivElement | null>(null);\n const [panelId, setPanelId] = useState<string | undefined>(undefined);\n const [titleId, setTitleId] = useState<string | undefined>(undefined);\n\n const floatingRootContext = useFloatingRootContext({\n open: openState,\n onOpenChange: handleOpenChange,\n elements: {\n reference,\n floating,\n },\n });\n\n useEffect(() => {\n if (!openState || !floating) {\n return;\n }\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n handleOpenChange(false);\n };\n\n floating.addEventListener(\"keydown\", onKeyDown);\n return () => {\n floating.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [floating, openState, handleOpenChange]);\n\n const context = useMemo(\n () => ({\n openState,\n floatingRootContext,\n setFloating,\n setReference,\n setOpen: handleOpenChange,\n panelId,\n setPanelId,\n titleId,\n setTitleId,\n }),\n [openState, floatingRootContext, handleOpenChange, panelId, titleId],\n );\n\n return (\n <SidePanelContext.Provider value={context}>\n {children}\n </SidePanelContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;;;AA8BO,SAAS,kBAAkB,KAAA,EAA+B;AAC/D,EAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,QAAA,EAAU,WAAA,EAAa,cAAa,GAAI,KAAA;AAEhE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,aAAA,CAAc;AAAA,IAC9C,OAAA,EAAS,QAAQ,WAAW,CAAA;AAAA,IAC5B,UAAA,EAAY,QAAA;AAAA,IACZ,IAAA,EAAM,mBAAA;AAAA,IACN,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,MAAM,gBAAA,GAAmB,WAAA;AAAA,IACvB,CAAC,OAAA,KAAqB;AACpB,MAAA,YAAA,CAAa,OAAO,CAAA;AACpB,MAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,OAAA,CAAA;AAAA,IACjB,CAAA;AAAA,IACA,CAAC,YAAY;AAAA,GACf;AAEA,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAA6B,IAAI,CAAA;AACnE,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAgC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAA6B,MAAS,CAAA;AACpE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAA6B,MAAS,CAAA;AAEpE,EAAA,MAAM,sBAAsB,sBAAA,CAAuB;AAAA,IACjD,IAAA,EAAM,SAAA;AAAA,IACN,YAAA,EAAc,gBAAA;AAAA,IACd,QAAA,EAAU;AAAA,MACR,SAAA;AAAA,MACA;AAAA;AACF,GACD,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAyB;AAC1C,MAAA,IAAI,KAAA,CAAM,QAAQ,QAAA,EAAU;AAC1B,QAAA;AAAA,MACF;AAEA,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,MAAA,gBAAA,CAAiB,KAAK,CAAA;AAAA,IACxB,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,SAAS,CAAA;AAAA,IACnD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,SAAA,EAAW,gBAAgB,CAAC,CAAA;AAE1C,EAAA,MAAM,OAAA,GAAU,OAAA;AAAA,IACd,OAAO;AAAA,MACL,SAAA;AAAA,MACA,mBAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,OAAA,EAAS,gBAAA;AAAA,MACT,OAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,SAAA,EAAW,mBAAA,EAAqB,gBAAA,EAAkB,SAAS,OAAO;AAAA,GACrE;AAEA,EAAA,2BACG,gBAAA,CAAiB,QAAA,EAAjB,EAA0B,KAAA,EAAO,SAC/B,QAAA,EACH,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"SidePanelProvider.js","sources":["../src/side-panel/SidePanelProvider.tsx"],"sourcesContent":["import { useFloatingRootContext } from \"@floating-ui/react\";\nimport { useControlled } from \"@salt-ds/core\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { SidePanelContext, useSidePanelTabOrder } from \"./internal\";\n\nexport interface SidePanelProviderProps {\n /**\n * Whether the panel is open.\n */\n open?: boolean;\n /**\n * Default open state when initially rendered.\n */\n defaultOpen?: boolean;\n /**\n * Callback when open state changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * SidePanelProvider children, should include SidePanel and SidePanelTrigger.\n */\n children: ReactNode;\n}\n\nexport function SidePanelProvider(props: SidePanelProviderProps) {\n const { children, open: openProp, defaultOpen, onOpenChange } = props;\n\n const [openState, setOpenState] = useControlled({\n default: Boolean(defaultOpen),\n controlled: openProp,\n name: \"SidePanelProvider\",\n state: \"open\",\n });\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setOpenState(newOpen);\n onOpenChange?.(newOpen);\n },\n [onOpenChange],\n );\n\n const [reference, setReference] = useState<HTMLElement | null>(null);\n const [floating, setFloating] = useState<HTMLDivElement | null>(null);\n const [panelId, setPanelId] = useState<string | undefined>(undefined);\n const [titleId, setTitleId] = useState<string | undefined>(undefined);\n\n // Memoise so floating-ui's root context isn't recreated every render.\n const elements = useMemo(\n () => ({ reference, floating }),\n [reference, floating],\n );\n\n const floatingRootContext = useFloatingRootContext({\n open: openState,\n onOpenChange: handleOpenChange,\n elements,\n });\n\n useEffect(() => {\n if (!openState || !floating) {\n return;\n }\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n handleOpenChange(false);\n };\n\n floating.addEventListener(\"keydown\", onKeyDown);\n return () => {\n floating.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [floating, openState, handleOpenChange]);\n\n useSidePanelTabOrder({\n floating,\n open: openState,\n reference,\n });\n\n const context = useMemo(\n () => ({\n openState,\n floatingRootContext,\n setFloating,\n setReference,\n setOpen: handleOpenChange,\n panelId,\n setPanelId,\n titleId,\n setTitleId,\n }),\n [openState, floatingRootContext, handleOpenChange, panelId, titleId],\n );\n\n return (\n <SidePanelContext.Provider value={context}>\n {children}\n </SidePanelContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;;;;AA8BO,SAAS,kBAAkB,KAAA,EAA+B;AAC/D,EAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,QAAA,EAAU,WAAA,EAAa,cAAa,GAAI,KAAA;AAEhE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,aAAA,CAAc;AAAA,IAC9C,OAAA,EAAS,QAAQ,WAAW,CAAA;AAAA,IAC5B,UAAA,EAAY,QAAA;AAAA,IACZ,IAAA,EAAM,mBAAA;AAAA,IACN,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,MAAM,gBAAA,GAAmB,WAAA;AAAA,IACvB,CAAC,OAAA,KAAqB;AACpB,MAAA,YAAA,CAAa,OAAO,CAAA;AACpB,MAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,OAAA,CAAA;AAAA,IACjB,CAAA;AAAA,IACA,CAAC,YAAY;AAAA,GACf;AAEA,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAA6B,IAAI,CAAA;AACnE,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAgC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAA6B,MAAS,CAAA;AACpE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAA6B,MAAS,CAAA;AAGpE,EAAA,MAAM,QAAA,GAAW,OAAA;AAAA,IACf,OAAO,EAAE,SAAA,EAAW,QAAA,EAAS,CAAA;AAAA,IAC7B,CAAC,WAAW,QAAQ;AAAA,GACtB;AAEA,EAAA,MAAM,sBAAsB,sBAAA,CAAuB;AAAA,IACjD,IAAA,EAAM,SAAA;AAAA,IACN,YAAA,EAAc,gBAAA;AAAA,IACd;AAAA,GACD,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAyB;AAC1C,MAAA,IAAI,KAAA,CAAM,QAAQ,QAAA,EAAU;AAC1B,QAAA;AAAA,MACF;AAEA,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,MAAA,gBAAA,CAAiB,KAAK,CAAA;AAAA,IACxB,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,SAAS,CAAA;AAAA,IACnD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,SAAA,EAAW,gBAAgB,CAAC,CAAA;AAE1C,EAAA,oBAAA,CAAqB;AAAA,IACnB,QAAA;AAAA,IACA,IAAA,EAAM,SAAA;AAAA,IACN;AAAA,GACD,CAAA;AAED,EAAA,MAAM,OAAA,GAAU,OAAA;AAAA,IACd,OAAO;AAAA,MACL,SAAA;AAAA,MACA,mBAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,OAAA,EAAS,gBAAA;AAAA,MACT,OAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,SAAA,EAAW,mBAAA,EAAqB,gBAAA,EAAkB,SAAS,OAAO;AAAA,GACrE;AAEA,EAAA,2BACG,gBAAA,CAAiB,QAAA,EAAjB,EAA0B,KAAA,EAAO,SAC/B,QAAA,EACH,CAAA;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltSidePanelTitle {\n flex: 1;\n min-width: 0;\n}\n";
1
+ var css_248z = ".saltSidePanelTitle {\n flex: 1;\n min-width: 0;\n min-height: var(--salt-size-base);\n display: flex;\n align-items: center;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=SidePanelTitle.css.js.map
@@ -5,6 +5,7 @@ import { useWindow } from '@salt-ds/window';
5
5
  import { clsx } from 'clsx';
6
6
  import { forwardRef } from 'react';
7
7
  import { useSidePanelContext } from './internal/SidePanelContext.js';
8
+ import 'tabbable';
8
9
  import css_248z from './SidePanelTitle.css.js';
9
10
 
10
11
  const withBaseName = makePrefixer("saltSidePanelTitle");
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanelTitle.js","sources":["../src/side-panel/SidePanelTitle.tsx"],"sourcesContent":["import {\n makePrefixer,\n Text,\n type TextProps,\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 { forwardRef } from \"react\";\nimport { useSidePanelContext } from \"./internal\";\nimport sidePanelTitleCss from \"./SidePanelTitle.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelTitle\");\n\nexport interface SidePanelTitleProps extends TextProps<\"div\"> {}\n\nexport const SidePanelTitle = forwardRef<HTMLDivElement, SidePanelTitleProps>(\n function SidePanelTitle(props, ref) {\n const { children, className, id, styleAs = \"h2\", ...rest } = props;\n\n const { setTitleId } = useSidePanelContext();\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel-title\",\n css: sidePanelTitleCss,\n window: targetWindow,\n });\n\n const titleId = useId(id);\n\n useIsomorphicLayoutEffect(() => {\n if (titleId) {\n setTitleId(titleId);\n }\n\n return () => {\n setTitleId(undefined);\n };\n }, [titleId, setTitleId]);\n\n return (\n <Text\n ref={ref}\n id={titleId}\n styleAs={styleAs}\n className={clsx(withBaseName(), className)}\n {...rest}\n >\n {children}\n </Text>\n );\n },\n);\n"],"names":["SidePanelTitle","sidePanelTitleCss"],"mappings":";;;;;;;;;AAcA,MAAM,YAAA,GAAe,aAAa,oBAAoB,CAAA;AAI/C,MAAM,cAAA,GAAiB,UAAA;AAAA,EAC5B,SAASA,eAAAA,CAAe,KAAA,EAAO,GAAA,EAAK;AAClC,IAAA,MAAM,EAAE,UAAU,SAAA,EAAW,EAAA,EAAI,UAAU,IAAA,EAAM,GAAG,MAAK,GAAI,KAAA;AAE7D,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,mBAAA,EAAoB;AAC3C,IAAA,MAAM,eAAe,SAAA,EAAU;AAE/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,uBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,MAAM,OAAA,GAAU,MAAM,EAAE,CAAA;AAExB,IAAA,yBAAA,CAA0B,MAAM;AAC9B,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,UAAA,CAAW,OAAO,CAAA;AAAA,MACpB;AAEA,MAAA,OAAO,MAAM;AACX,QAAA,UAAA,CAAW,MAAS,CAAA;AAAA,MACtB,CAAA;AAAA,IACF,CAAA,EAAG,CAAC,OAAA,EAAS,UAAU,CAAC,CAAA;AAExB,IAAA,uBACE,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,EAAA,EAAI,OAAA;AAAA,QACJ,OAAA;AAAA,QACA,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACxC,GAAG,IAAA;AAAA,QAEH;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;;;;"}
1
+ {"version":3,"file":"SidePanelTitle.js","sources":["../src/side-panel/SidePanelTitle.tsx"],"sourcesContent":["import {\n makePrefixer,\n Text,\n type TextProps,\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 { forwardRef } from \"react\";\nimport { useSidePanelContext } from \"./internal\";\nimport sidePanelTitleCss from \"./SidePanelTitle.css\";\n\nconst withBaseName = makePrefixer(\"saltSidePanelTitle\");\n\nexport type SidePanelTitleProps = TextProps<\"div\">;\n\nexport const SidePanelTitle = forwardRef<HTMLDivElement, SidePanelTitleProps>(\n function SidePanelTitle(props, ref) {\n const { children, className, id, styleAs = \"h2\", ...rest } = props;\n\n const { setTitleId } = useSidePanelContext();\n const targetWindow = useWindow();\n\n useComponentCssInjection({\n testId: \"salt-side-panel-title\",\n css: sidePanelTitleCss,\n window: targetWindow,\n });\n\n const titleId = useId(id);\n\n useIsomorphicLayoutEffect(() => {\n if (titleId) {\n setTitleId(titleId);\n }\n\n return () => {\n setTitleId(undefined);\n };\n }, [titleId, setTitleId]);\n\n return (\n <Text\n ref={ref}\n id={titleId}\n styleAs={styleAs}\n className={clsx(withBaseName(), className)}\n {...rest}\n >\n {children}\n </Text>\n );\n },\n);\n"],"names":["SidePanelTitle","sidePanelTitleCss"],"mappings":";;;;;;;;;;AAcA,MAAM,YAAA,GAAe,aAAa,oBAAoB,CAAA;AAI/C,MAAM,cAAA,GAAiB,UAAA;AAAA,EAC5B,SAASA,eAAAA,CAAe,KAAA,EAAO,GAAA,EAAK;AAClC,IAAA,MAAM,EAAE,UAAU,SAAA,EAAW,EAAA,EAAI,UAAU,IAAA,EAAM,GAAG,MAAK,GAAI,KAAA;AAE7D,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,mBAAA,EAAoB;AAC3C,IAAA,MAAM,eAAe,SAAA,EAAU;AAE/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,uBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,MAAM,OAAA,GAAU,MAAM,EAAE,CAAA;AAExB,IAAA,yBAAA,CAA0B,MAAM;AAC9B,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,UAAA,CAAW,OAAO,CAAA;AAAA,MACpB;AAEA,MAAA,OAAO,MAAM;AACX,QAAA,UAAA,CAAW,MAAS,CAAA;AAAA,MACtB,CAAA;AAAA,IACF,CAAA,EAAG,CAAC,OAAA,EAAS,UAAU,CAAC,CAAA;AAExB,IAAA,uBACE,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,EAAA,EAAI,OAAA;AAAA,QACJ,OAAA;AAAA,QACA,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACxC,GAAG,IAAA;AAAA,QAEH;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;;;;"}
@@ -1,14 +1,14 @@
1
1
  import { jsx, Fragment } from 'react/jsx-runtime';
2
- import { useForkRef, mergeProps } from '@salt-ds/core';
2
+ import { useForkRef, getRefFromChildren, mergeProps } from '@salt-ds/core';
3
3
  import { forwardRef, isValidElement, cloneElement } from 'react';
4
4
  import { useSidePanelContext } from './internal/SidePanelContext.js';
5
+ import 'tabbable';
5
6
 
6
7
  const SidePanelTrigger = forwardRef(function SidePanelTrigger2(props, ref) {
7
8
  const { children, onClick, ...rest } = props;
8
9
  const { setReference, openState, setOpen, panelId } = useSidePanelContext();
9
- const childRef = children == null ? void 0 : children.ref;
10
10
  const combinedRef = useForkRef(setReference, ref);
11
- const handleRef = useForkRef(combinedRef, childRef);
11
+ const handleRef = useForkRef(combinedRef, getRefFromChildren(children));
12
12
  const handleClick = (event) => {
13
13
  onClick == null ? void 0 : onClick(event);
14
14
  setOpen(!openState);
@@ -20,8 +20,8 @@ const SidePanelTrigger = forwardRef(function SidePanelTrigger2(props, ref) {
20
20
  {
21
21
  "aria-expanded": openState,
22
22
  "aria-controls": openState ? panelId : void 0,
23
- ...rest,
24
- onClick: handleClick
23
+ onClick: handleClick,
24
+ ...rest
25
25
  },
26
26
  children.props
27
27
  );
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanelTrigger.js","sources":["../src/side-panel/SidePanelTrigger.tsx"],"sourcesContent":["import { mergeProps, useForkRef } from \"@salt-ds/core\";\nimport {\n type ComponentPropsWithoutRef,\n cloneElement,\n forwardRef,\n isValidElement,\n type MouseEvent,\n type ReactNode,\n} from \"react\";\nimport { useSidePanelContext } from \"./internal\";\n\nexport interface SidePanelTriggerProps\n extends ComponentPropsWithoutRef<\"button\"> {\n children?: ReactNode;\n}\n\nexport const SidePanelTrigger = forwardRef<\n HTMLButtonElement,\n SidePanelTriggerProps\n>(function SidePanelTrigger(props, ref) {\n const { children, onClick, ...rest } = props;\n const { setReference, openState, setOpen, panelId } = useSidePanelContext();\n\n const childRef = (children as { ref?: React.Ref<HTMLButtonElement> })?.ref;\n const combinedRef = useForkRef(setReference, ref);\n const handleRef = useForkRef(combinedRef, childRef);\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n setOpen(!openState);\n };\n\n if (!children || !isValidElement(children)) {\n return <>{children}</>;\n }\n\n const mergedProps = mergeProps(\n {\n \"aria-expanded\": openState,\n \"aria-controls\": openState ? panelId : undefined,\n ...rest,\n onClick: handleClick,\n },\n children.props,\n );\n\n return cloneElement(children, {\n ...mergedProps,\n ref: handleRef,\n });\n});\n"],"names":["SidePanelTrigger"],"mappings":";;;;;AAgBO,MAAM,gBAAA,GAAmB,UAAA,CAG9B,SAASA,iBAAAA,CAAiB,OAAO,GAAA,EAAK;AACtC,EAAA,MAAM,EAAE,QAAA,EAAU,OAAA,EAAS,GAAG,MAAK,GAAI,KAAA;AACvC,EAAA,MAAM,EAAE,YAAA,EAAc,SAAA,EAAW,OAAA,EAAS,OAAA,KAAY,mBAAA,EAAoB;AAE1E,EAAA,MAAM,WAAY,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAqD,GAAA;AACvE,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,YAAA,EAAc,GAAG,CAAA;AAChD,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,WAAA,EAAa,QAAQ,CAAA;AAElD,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAyC;AAC5D,IAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAU,KAAA,CAAA;AACV,IAAA,OAAA,CAAQ,CAAC,SAAS,CAAA;AAAA,EACpB,CAAA;AAEA,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,cAAA,CAAe,QAAQ,CAAA,EAAG;AAC1C,IAAA,uCAAU,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,MAAM,WAAA,GAAc,UAAA;AAAA,IAClB;AAAA,MACE,eAAA,EAAiB,SAAA;AAAA,MACjB,eAAA,EAAiB,YAAY,OAAA,GAAU,MAAA;AAAA,MACvC,GAAG,IAAA;AAAA,MACH,OAAA,EAAS;AAAA,KACX;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AAEA,EAAA,OAAO,aAAa,QAAA,EAAU;AAAA,IAC5B,GAAG,WAAA;AAAA,IACH,GAAA,EAAK;AAAA,GACN,CAAA;AACH,CAAC;;;;"}
1
+ {"version":3,"file":"SidePanelTrigger.js","sources":["../src/side-panel/SidePanelTrigger.tsx"],"sourcesContent":["import { getRefFromChildren, mergeProps, useForkRef } from \"@salt-ds/core\";\nimport {\n type ComponentPropsWithoutRef,\n cloneElement,\n forwardRef,\n isValidElement,\n type MouseEvent,\n} from \"react\";\nimport { useSidePanelContext } from \"./internal\";\n\nexport type SidePanelTriggerProps = ComponentPropsWithoutRef<\"button\">;\n\nexport const SidePanelTrigger = forwardRef<\n HTMLButtonElement,\n SidePanelTriggerProps\n>(function SidePanelTrigger(props, ref) {\n const { children, onClick, ...rest } = props;\n const { setReference, openState, setOpen, panelId } = useSidePanelContext();\n\n const combinedRef = useForkRef(setReference, ref);\n const handleRef = useForkRef(combinedRef, getRefFromChildren(children));\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n setOpen(!openState);\n };\n\n if (!children || !isValidElement(children)) {\n return <>{children}</>;\n }\n\n const mergedProps = mergeProps(\n {\n \"aria-expanded\": openState,\n \"aria-controls\": openState ? panelId : undefined,\n onClick: handleClick,\n ...rest,\n },\n children.props,\n );\n\n return cloneElement(children, {\n ...mergedProps,\n ref: handleRef,\n });\n});\n"],"names":["SidePanelTrigger"],"mappings":";;;;;;AAYO,MAAM,gBAAA,GAAmB,UAAA,CAG9B,SAASA,iBAAAA,CAAiB,OAAO,GAAA,EAAK;AACtC,EAAA,MAAM,EAAE,QAAA,EAAU,OAAA,EAAS,GAAG,MAAK,GAAI,KAAA;AACvC,EAAA,MAAM,EAAE,YAAA,EAAc,SAAA,EAAW,OAAA,EAAS,OAAA,KAAY,mBAAA,EAAoB;AAE1E,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,YAAA,EAAc,GAAG,CAAA;AAChD,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,WAAA,EAAa,kBAAA,CAAmB,QAAQ,CAAC,CAAA;AAEtE,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAyC;AAC5D,IAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAU,KAAA,CAAA;AACV,IAAA,OAAA,CAAQ,CAAC,SAAS,CAAA;AAAA,EACpB,CAAA;AAEA,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,cAAA,CAAe,QAAQ,CAAA,EAAG;AAC1C,IAAA,uCAAU,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,MAAM,WAAA,GAAc,UAAA;AAAA,IAClB;AAAA,MACE,eAAA,EAAiB,SAAA;AAAA,MACjB,eAAA,EAAiB,YAAY,OAAA,GAAU,MAAA;AAAA,MACvC,OAAA,EAAS,WAAA;AAAA,MACT,GAAG;AAAA,KACL;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AAEA,EAAA,OAAO,aAAa,QAAA,EAAU;AAAA,IAC5B,GAAG,WAAA;AAAA,IACH,GAAA,EAAK;AAAA,GACN,CAAA;AACH,CAAC;;;;"}
@@ -17,7 +17,8 @@ const SidePanelContext = createContext(
17
17
  },
18
18
  titleId: void 0,
19
19
  setTitleId: () => {
20
- }
20
+ },
21
+ position: void 0
21
22
  }
22
23
  );
23
24
  function useSidePanelContext() {
@@ -1 +1 @@
1
- {"version":3,"file":"SidePanelContext.js","sources":["../src/side-panel/internal/SidePanelContext.ts"],"sourcesContent":["import type { FloatingRootContext } from \"@floating-ui/react\";\nimport { createContext } from \"@salt-ds/core\";\nimport { type Dispatch, type SetStateAction, useContext } from \"react\";\n\nexport interface SidePanelContextValue {\n /**\n * Whether the side panel is currently open.\n */\n openState: boolean;\n /**\n * The floating-ui root context shared between the trigger and the panel.\n * Coordinates interactions (click, dismiss, role) across both elements.\n */\n floatingRootContext: FloatingRootContext;\n /**\n * Ref setter for the panel element.\n * Registers the panel DOM node with floating-ui.\n */\n setFloating: Dispatch<SetStateAction<HTMLDivElement | null>>;\n /**\n * Ref setter for the reference (trigger) element.\n * Registers the trigger DOM node with floating-ui for focus return.\n */\n setReference: Dispatch<SetStateAction<HTMLElement | null>>;\n /**\n * Sets the open state of the panel.\n * Called by the close button in SidePanelHeader, or any consumer that needs to close the panel.\n */\n setOpen: (open: boolean) => void;\n /**\n * Side panel id used for aria-controls on the trigger.\n */\n panelId?: string;\n /**\n * Registers or clears the side panel id used for aria-controls/id linkage.\n */\n setPanelId: Dispatch<SetStateAction<string | undefined>>;\n /**\n * The auto-generated id placed on SidePanelTitle.\n * Used for aria-labelledby on the panel region and the scrollable body.\n */\n titleId?: string;\n /**\n * Registers the title id from SidePanelTitle back to the context\n * so that SidePanel and SidePanelContent can use it for aria-labelledby.\n */\n setTitleId: Dispatch<SetStateAction<string | undefined>>;\n}\n\nexport const SidePanelContext = createContext<SidePanelContextValue>(\n \"SidePanelContext\",\n {\n openState: false,\n floatingRootContext: {} as FloatingRootContext,\n setFloating: () => {},\n setReference: () => {},\n setOpen: () => {},\n panelId: undefined,\n setPanelId: () => {},\n titleId: undefined,\n setTitleId: () => {},\n },\n);\n\nexport function useSidePanelContext() {\n return useContext(SidePanelContext);\n}\n"],"names":[],"mappings":";;;AAiDO,MAAM,gBAAA,GAAmB,aAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AAAA,IACE,SAAA,EAAW,KAAA;AAAA,IACX,qBAAqB,EAAC;AAAA,IACtB,aAAa,MAAM;AAAA,IAAC,CAAA;AAAA,IACpB,cAAc,MAAM;AAAA,IAAC,CAAA;AAAA,IACrB,SAAS,MAAM;AAAA,IAAC,CAAA;AAAA,IAChB,OAAA,EAAS,MAAA;AAAA,IACT,YAAY,MAAM;AAAA,IAAC,CAAA;AAAA,IACnB,OAAA,EAAS,MAAA;AAAA,IACT,YAAY,MAAM;AAAA,IAAC;AAAA;AAEvB;AAEO,SAAS,mBAAA,GAAsB;AACpC,EAAA,OAAO,WAAW,gBAAgB,CAAA;AACpC;;;;"}
1
+ {"version":3,"file":"SidePanelContext.js","sources":["../src/side-panel/internal/SidePanelContext.ts"],"sourcesContent":["import type { FloatingRootContext } from \"@floating-ui/react\";\nimport { createContext } from \"@salt-ds/core\";\nimport { type Dispatch, type SetStateAction, useContext } from \"react\";\n\nexport interface SidePanelContextValue {\n /**\n * Whether the side panel is currently open.\n */\n openState: boolean;\n /**\n * The floating-ui root context shared between the trigger and the panel.\n * Coordinates interactions (click, dismiss, role) across both elements.\n */\n floatingRootContext: FloatingRootContext;\n /**\n * Ref setter for the panel element.\n * Registers the panel DOM node with floating-ui.\n */\n setFloating: Dispatch<SetStateAction<HTMLDivElement | null>>;\n /**\n * Ref setter for the reference (trigger) element.\n * Registers the trigger DOM node with floating-ui for focus return.\n */\n setReference: Dispatch<SetStateAction<HTMLElement | null>>;\n /**\n * Sets the open state of the panel.\n * Called by the close button in SidePanelHeader, or any consumer that needs to close the panel.\n */\n setOpen: (open: boolean) => void;\n /**\n * Side panel id used for aria-controls on the trigger.\n */\n panelId?: string;\n /**\n * Registers or clears the side panel id used for aria-controls/id linkage.\n */\n setPanelId: Dispatch<SetStateAction<string | undefined>>;\n /**\n * The auto-generated id placed on SidePanelTitle.\n * Used for aria-labelledby on the panel region and the scrollable body.\n */\n titleId?: string;\n /**\n * Registers the title id from SidePanelTitle back to the context\n * so that SidePanel and SidePanelContent can use it for aria-labelledby.\n */\n setTitleId: Dispatch<SetStateAction<string | undefined>>;\n /**\n * Edge the panel is anchored to. Set by SidePanel for its own subtree.\n */\n position?: \"right\" | \"left\";\n}\n\nexport const SidePanelContext = createContext<SidePanelContextValue>(\n \"SidePanelContext\",\n {\n openState: false,\n floatingRootContext: {} as FloatingRootContext,\n setFloating: () => {},\n setReference: () => {},\n setOpen: () => {},\n panelId: undefined,\n setPanelId: () => {},\n titleId: undefined,\n setTitleId: () => {},\n position: undefined,\n },\n);\n\nexport function useSidePanelContext() {\n return useContext(SidePanelContext);\n}\n"],"names":[],"mappings":";;;AAqDO,MAAM,gBAAA,GAAmB,aAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AAAA,IACE,SAAA,EAAW,KAAA;AAAA,IACX,qBAAqB,EAAC;AAAA,IACtB,aAAa,MAAM;AAAA,IAAC,CAAA;AAAA,IACpB,cAAc,MAAM;AAAA,IAAC,CAAA;AAAA,IACrB,SAAS,MAAM;AAAA,IAAC,CAAA;AAAA,IAChB,OAAA,EAAS,MAAA;AAAA,IACT,YAAY,MAAM;AAAA,IAAC,CAAA;AAAA,IACnB,OAAA,EAAS,MAAA;AAAA,IACT,YAAY,MAAM;AAAA,IAAC,CAAA;AAAA,IACnB,QAAA,EAAU;AAAA;AAEd;AAEO,SAAS,mBAAA,GAAsB;AACpC,EAAA,OAAO,WAAW,gBAAgB,CAAA;AACpC;;;;"}
@@ -0,0 +1,48 @@
1
+ import { useState, useEffect } from 'react';
2
+
3
+ const observedAttributes = ["class", "hidden", "style"];
4
+ function useIsScrollable(ref) {
5
+ const [isScrollable, setIsScrollable] = useState(false);
6
+ useEffect(() => {
7
+ const element = ref.current;
8
+ const win = element == null ? void 0 : element.ownerDocument.defaultView;
9
+ if (!element || !win) {
10
+ return;
11
+ }
12
+ let animationFrame;
13
+ const checkScrollable = () => {
14
+ animationFrame = void 0;
15
+ const nextIsScrollable = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
16
+ setIsScrollable(
17
+ (currentIsScrollable) => currentIsScrollable === nextIsScrollable ? currentIsScrollable : nextIsScrollable
18
+ );
19
+ };
20
+ const scheduleCheck = () => {
21
+ if (animationFrame === void 0) {
22
+ animationFrame = win.requestAnimationFrame(checkScrollable);
23
+ }
24
+ };
25
+ scheduleCheck();
26
+ const resizeObserver = win.ResizeObserver ? new win.ResizeObserver(scheduleCheck) : void 0;
27
+ resizeObserver == null ? void 0 : resizeObserver.observe(element);
28
+ const mutationObserver = win.MutationObserver ? new win.MutationObserver(scheduleCheck) : void 0;
29
+ mutationObserver == null ? void 0 : mutationObserver.observe(element, {
30
+ attributeFilter: observedAttributes,
31
+ attributes: true,
32
+ characterData: true,
33
+ childList: true,
34
+ subtree: true
35
+ });
36
+ return () => {
37
+ if (animationFrame !== void 0) {
38
+ win.cancelAnimationFrame(animationFrame);
39
+ }
40
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
41
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
42
+ };
43
+ }, [ref]);
44
+ return isScrollable;
45
+ }
46
+
47
+ export { useIsScrollable };
48
+ //# sourceMappingURL=useIsScrollable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsScrollable.js","sources":["../src/side-panel/internal/useIsScrollable.ts"],"sourcesContent":["import { type RefObject, useEffect, useState } from \"react\";\n\nconst observedAttributes = [\"class\", \"hidden\", \"style\"];\n\nexport function useIsScrollable(ref: RefObject<HTMLElement>) {\n const [isScrollable, setIsScrollable] = useState(false);\n\n useEffect(() => {\n const element = ref.current;\n const win = element?.ownerDocument.defaultView;\n if (!element || !win) {\n return;\n }\n\n let animationFrame: number | undefined;\n\n const checkScrollable = () => {\n animationFrame = undefined;\n const nextIsScrollable =\n element.scrollHeight > element.clientHeight ||\n element.scrollWidth > element.clientWidth;\n\n setIsScrollable((currentIsScrollable) =>\n currentIsScrollable === nextIsScrollable\n ? currentIsScrollable\n : nextIsScrollable,\n );\n };\n\n const scheduleCheck = () => {\n if (animationFrame === undefined) {\n animationFrame = win.requestAnimationFrame(checkScrollable);\n }\n };\n\n scheduleCheck();\n\n const resizeObserver = win.ResizeObserver\n ? new win.ResizeObserver(scheduleCheck)\n : undefined;\n resizeObserver?.observe(element);\n\n const mutationObserver = win.MutationObserver\n ? new win.MutationObserver(scheduleCheck)\n : undefined;\n mutationObserver?.observe(element, {\n attributeFilter: observedAttributes,\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n\n return () => {\n if (animationFrame !== undefined) {\n win.cancelAnimationFrame(animationFrame);\n }\n resizeObserver?.disconnect();\n mutationObserver?.disconnect();\n };\n }, [ref]);\n\n return isScrollable;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,kBAAA,GAAqB,CAAC,OAAA,EAAS,QAAA,EAAU,OAAO,CAAA;AAE/C,SAAS,gBAAgB,GAAA,EAA6B;AAC3D,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,KAAK,CAAA;AAEtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,UAAU,GAAA,CAAI,OAAA;AACpB,IAAA,MAAM,GAAA,GAAM,mCAAS,aAAA,CAAc,WAAA;AACnC,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,GAAA,EAAK;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,cAAA;AAEJ,IAAA,MAAM,kBAAkB,MAAM;AAC5B,MAAA,cAAA,GAAiB,MAAA;AACjB,MAAA,MAAM,mBACJ,OAAA,CAAQ,YAAA,GAAe,QAAQ,YAAA,IAC/B,OAAA,CAAQ,cAAc,OAAA,CAAQ,WAAA;AAEhC,MAAA,eAAA;AAAA,QAAgB,CAAC,mBAAA,KACf,mBAAA,KAAwB,gBAAA,GACpB,mBAAA,GACA;AAAA,OACN;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,gBAAgB,MAAM;AAC1B,MAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,QAAA,cAAA,GAAiB,GAAA,CAAI,sBAAsB,eAAe,CAAA;AAAA,MAC5D;AAAA,IACF,CAAA;AAEA,IAAA,aAAA,EAAc;AAEd,IAAA,MAAM,iBAAiB,GAAA,CAAI,cAAA,GACvB,IAAI,GAAA,CAAI,cAAA,CAAe,aAAa,CAAA,GACpC,MAAA;AACJ,IAAA,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAgB,OAAA,CAAQ,OAAA,CAAA;AAExB,IAAA,MAAM,mBAAmB,GAAA,CAAI,gBAAA,GACzB,IAAI,GAAA,CAAI,gBAAA,CAAiB,aAAa,CAAA,GACtC,MAAA;AACJ,IAAA,gBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,gBAAA,CAAkB,QAAQ,OAAA,EAAS;AAAA,MACjC,eAAA,EAAiB,kBAAA;AAAA,MACjB,UAAA,EAAY,IAAA;AAAA,MACZ,aAAA,EAAe,IAAA;AAAA,MACf,SAAA,EAAW,IAAA;AAAA,MACX,OAAA,EAAS;AAAA,KACX,CAAA;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,QAAA,GAAA,CAAI,qBAAqB,cAAc,CAAA;AAAA,MACzC;AACA,MAAA,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAgB,UAAA,EAAA;AAChB,MAAA,gBAAA,IAAA,IAAA,GAAA,MAAA,GAAA,gBAAA,CAAkB,UAAA,EAAA;AAAA,IACpB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,OAAO,YAAA;AACT;;;;"}