@salt-ds/core 1.72.0 → 1.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/CHANGELOG.md +178 -0
  2. package/css/salt-core.css +533 -147
  3. package/dist-cjs/accordion/AccordionHeader.css.js +1 -1
  4. package/dist-cjs/border-layout/BorderLayout.js.map +1 -1
  5. package/dist-cjs/breadcrumbs/Breadcrumb.js +5 -6
  6. package/dist-cjs/breadcrumbs/Breadcrumb.js.map +1 -1
  7. package/dist-cjs/button/Button.css.js +1 -1
  8. package/dist-cjs/card/CardContent.css.js +1 -1
  9. package/dist-cjs/card/hasCardSection.js +11 -3
  10. package/dist-cjs/card/hasCardSection.js.map +1 -1
  11. package/dist-cjs/checkbox/CheckboxIcon.js.map +1 -1
  12. package/dist-cjs/collapsible/CollapsiblePanel.css.js +1 -1
  13. package/dist-cjs/collapsible/CollapsiblePanel.js +15 -15
  14. package/dist-cjs/collapsible/CollapsiblePanel.js.map +1 -1
  15. package/dist-cjs/combo-box/ComboBox.js.map +1 -1
  16. package/dist-cjs/dialog/DialogHeader.js +2 -0
  17. package/dist-cjs/dialog/DialogHeader.js.map +1 -1
  18. package/dist-cjs/drawer/Drawer.css.js +1 -1
  19. package/dist-cjs/drawer/Drawer.js +54 -6
  20. package/dist-cjs/drawer/Drawer.js.map +1 -1
  21. package/dist-cjs/drawer/DrawerContext.js +2 -0
  22. package/dist-cjs/drawer/DrawerContext.js.map +1 -1
  23. package/dist-cjs/drawer/DrawerFooter.css.js +1 -1
  24. package/dist-cjs/drawer/DrawerHeader.css.js +1 -1
  25. package/dist-cjs/drawer/DrawerHeader.js +8 -3
  26. package/dist-cjs/drawer/DrawerHeader.js.map +1 -1
  27. package/dist-cjs/drawer/internal/DrawerResizeGuide.css.js +6 -0
  28. package/dist-cjs/drawer/internal/DrawerResizeGuide.css.js.map +1 -0
  29. package/dist-cjs/drawer/internal/DrawerResizeGuide.js +44 -0
  30. package/dist-cjs/drawer/internal/DrawerResizeGuide.js.map +1 -0
  31. package/dist-cjs/drawer/internal/DrawerResizeHandle.css.js +6 -0
  32. package/dist-cjs/drawer/internal/DrawerResizeHandle.css.js.map +1 -0
  33. package/dist-cjs/drawer/internal/DrawerResizeHandle.js +43 -0
  34. package/dist-cjs/drawer/internal/DrawerResizeHandle.js.map +1 -0
  35. package/dist-cjs/drawer/internal/useDrawerResize.js +519 -0
  36. package/dist-cjs/drawer/internal/useDrawerResize.js.map +1 -0
  37. package/dist-cjs/dropdown/Dropdown.css.js +1 -1
  38. package/dist-cjs/dropdown/Dropdown.js +1 -1
  39. package/dist-cjs/dropdown/Dropdown.js.map +1 -1
  40. package/dist-cjs/form-field/FormField.js +2 -2
  41. package/dist-cjs/form-field/FormField.js.map +1 -1
  42. package/dist-cjs/form-field/FormFieldHelperText.js +2 -0
  43. package/dist-cjs/form-field/FormFieldHelperText.js.map +1 -1
  44. package/dist-cjs/form-field/FormFieldLabel.css.js +1 -1
  45. package/dist-cjs/form-field/FormFieldLabel.js +2 -0
  46. package/dist-cjs/form-field/FormFieldLabel.js.map +1 -1
  47. package/dist-cjs/form-field-context/FormFieldContext.js.map +1 -1
  48. package/dist-cjs/index.js +11 -0
  49. package/dist-cjs/index.js.map +1 -1
  50. package/dist-cjs/input/Input.css.js +1 -1
  51. package/dist-cjs/link/Link.js +2 -0
  52. package/dist-cjs/link/Link.js.map +1 -1
  53. package/dist-cjs/link/LinkAction.js +3 -2
  54. package/dist-cjs/link/LinkAction.js.map +1 -1
  55. package/dist-cjs/link-button/LinkButton.css.js +1 -1
  56. package/dist-cjs/link-button/LinkButton.js +3 -2
  57. package/dist-cjs/link-button/LinkButton.js.map +1 -1
  58. package/dist-cjs/list-box/ListBox.js +1 -1
  59. package/dist-cjs/list-box/ListBox.js.map +1 -1
  60. package/dist-cjs/list-control/ListControlContext.js.map +1 -1
  61. package/dist-cjs/list-control/ListControlOptionContext.js.map +1 -1
  62. package/dist-cjs/mega-menu/MegaMenuGroupHeading.css.js +1 -1
  63. package/dist-cjs/mega-menu/MegaMenuListItem.css.js +1 -1
  64. package/dist-cjs/menu/MenuAlignmentContext.js +55 -0
  65. package/dist-cjs/menu/MenuAlignmentContext.js.map +1 -0
  66. package/dist-cjs/menu/MenuBase.js +9 -3
  67. package/dist-cjs/menu/MenuBase.js.map +1 -1
  68. package/dist-cjs/menu/MenuGroup.css.js +1 -1
  69. package/dist-cjs/menu/MenuGroup.js +42 -3
  70. package/dist-cjs/menu/MenuGroup.js.map +1 -1
  71. package/dist-cjs/menu/MenuGroupContext.js +27 -0
  72. package/dist-cjs/menu/MenuGroupContext.js.map +1 -0
  73. package/dist-cjs/menu/MenuItem.css.js +1 -1
  74. package/dist-cjs/menu/MenuItem.js +176 -50
  75. package/dist-cjs/menu/MenuItem.js.map +1 -1
  76. package/dist-cjs/menu/MenuPanel.js +12 -3
  77. package/dist-cjs/menu/MenuPanel.js.map +1 -1
  78. package/dist-cjs/menu/MenuPanelContext.js +3 -1
  79. package/dist-cjs/menu/MenuPanelContext.js.map +1 -1
  80. package/dist-cjs/multiline-input/MultilineInput.css.js +1 -1
  81. package/dist-cjs/navigation-item/NavigationItem.css.js +1 -1
  82. package/dist-cjs/number-input/NumberInput.css.js +1 -1
  83. package/dist-cjs/on-solid-button/OnSolidButton.css.js +6 -0
  84. package/dist-cjs/on-solid-button/OnSolidButton.css.js.map +1 -0
  85. package/dist-cjs/on-solid-button/OnSolidButton.js +68 -0
  86. package/dist-cjs/on-solid-button/OnSolidButton.js.map +1 -0
  87. package/dist-cjs/option/Option.css.js +1 -1
  88. package/dist-cjs/option/Option.js +7 -1
  89. package/dist-cjs/option/Option.js.map +1 -1
  90. package/dist-cjs/option/OptionGroup.css.js +1 -1
  91. package/dist-cjs/overlay/OverlayHeader.js +2 -0
  92. package/dist-cjs/overlay/OverlayHeader.js.map +1 -1
  93. package/dist-cjs/overlay/OverlayPanelCloseButton.js +1 -1
  94. package/dist-cjs/overlay/OverlayPanelCloseButton.js.map +1 -1
  95. package/dist-cjs/pagination/CompactPaginator.js +2 -0
  96. package/dist-cjs/pagination/CompactPaginator.js.map +1 -1
  97. package/dist-cjs/pagination/GoToInput.js +2 -0
  98. package/dist-cjs/pagination/GoToInput.js.map +1 -1
  99. package/dist-cjs/pill/PillCheckIcon.js.map +1 -1
  100. package/dist-cjs/pill-input/PillInput.css.js +1 -1
  101. package/dist-cjs/progress/CircularProgress/CircularProgress.js +2 -0
  102. package/dist-cjs/progress/CircularProgress/CircularProgress.js.map +1 -1
  103. package/dist-cjs/progress/LinearProgress/LinearProgress.js +2 -0
  104. package/dist-cjs/progress/LinearProgress/LinearProgress.js.map +1 -1
  105. package/dist-cjs/salt-provider/ThemeApplicator.js +10 -6
  106. package/dist-cjs/salt-provider/ThemeApplicator.js.map +1 -1
  107. package/dist-cjs/side-panel/SidePanelTitle.js +2 -0
  108. package/dist-cjs/side-panel/SidePanelTitle.js.map +1 -1
  109. package/dist-cjs/side-panel/SidePanelTrigger.js.map +1 -1
  110. package/dist-cjs/side-panel/internal/useIsScrollable.js.map +1 -1
  111. package/dist-cjs/side-panel/useSidePanel.js +4 -9
  112. package/dist-cjs/side-panel/useSidePanel.js.map +1 -1
  113. package/dist-cjs/skip-link/internal/useManageFocusOnTarget.js +2 -2
  114. package/dist-cjs/skip-link/internal/useManageFocusOnTarget.js.map +1 -1
  115. package/dist-cjs/slider/internal/SliderThumb.js.map +1 -1
  116. package/dist-cjs/slider/internal/SliderTooltip.js +2 -0
  117. package/dist-cjs/slider/internal/SliderTooltip.js.map +1 -1
  118. package/dist-cjs/slider/internal/SliderTrack.js +2 -0
  119. package/dist-cjs/slider/internal/SliderTrack.js.map +1 -1
  120. package/dist-cjs/slider/internal/useRangeSliderThumb.js.map +1 -1
  121. package/dist-cjs/slider/internal/useSliderThumb.js.map +1 -1
  122. package/dist-cjs/slider/internal/utils.js.map +1 -1
  123. package/dist-cjs/stepper/Stepper.js +1 -1
  124. package/dist-cjs/stepper/Stepper.js.map +1 -1
  125. package/dist-cjs/stepper/internal/StepText.css.js +1 -1
  126. package/dist-cjs/stepper/internal/StepText.js +2 -0
  127. package/dist-cjs/stepper/internal/StepText.js.map +1 -1
  128. package/dist-cjs/table/Table.css.js +1 -1
  129. package/dist-cjs/tabs/Tabs.js +1 -1
  130. package/dist-cjs/tabs/Tabs.js.map +1 -1
  131. package/dist-cjs/tabs/internal/overflow/useOverflow.js.map +1 -1
  132. package/dist-cjs/tabs/internal/overflow/useRenderedTabWidth.js.map +1 -1
  133. package/dist-cjs/text/Code.js +1 -1
  134. package/dist-cjs/text/Code.js.map +1 -1
  135. package/dist-cjs/text/Editorial.js +32 -0
  136. package/dist-cjs/text/Editorial.js.map +1 -0
  137. package/dist-cjs/text/Eyebrow.js +12 -0
  138. package/dist-cjs/text/Eyebrow.js.map +1 -0
  139. package/dist-cjs/text/Text.css.js +1 -1
  140. package/dist-cjs/text/Text.js +6 -2
  141. package/dist-cjs/text/Text.js.map +1 -1
  142. package/dist-cjs/toggle-button/ToggleButton.css.js +1 -1
  143. package/dist-cjs/toggle-button/ToggleButton.js.map +1 -1
  144. package/dist-cjs/toolbar/ToolbarOverflow.js +8 -4
  145. package/dist-cjs/toolbar/ToolbarOverflow.js.map +1 -1
  146. package/dist-cjs/toolbar/toolbarUtils.js.map +1 -1
  147. package/dist-cjs/tooltip/useAriaAnnounce.js +4 -2
  148. package/dist-cjs/tooltip/useAriaAnnounce.js.map +1 -1
  149. package/dist-cjs/tooltip/useTooltip.js.map +1 -1
  150. package/dist-cjs/tree/TreeContext.js.map +1 -1
  151. package/dist-cjs/tree/TreeNodeTrigger.css.js +1 -1
  152. package/dist-cjs/tree/TreeNodeTrigger.js +0 -1
  153. package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
  154. package/dist-cjs/utils/forkRef.js +34 -0
  155. package/dist-cjs/utils/forkRef.js.map +1 -0
  156. package/dist-cjs/utils/getRefFromChildren.js.map +1 -1
  157. package/dist-cjs/utils/marginMiddleware.js.map +1 -1
  158. package/dist-cjs/utils/setRef.js.map +1 -1
  159. package/dist-cjs/utils/useFloatingUI/useFloatingUI.js.map +1 -1
  160. package/dist-cjs/utils/useForkRef.js +3 -6
  161. package/dist-cjs/utils/useForkRef.js.map +1 -1
  162. package/dist-cjs/utils/useResizeObserver.js.map +1 -1
  163. package/dist-cjs/vertical-navigation/VerticalNavigationSubMenu.css.js +1 -1
  164. package/dist-es/accordion/AccordionHeader.css.js +1 -1
  165. package/dist-es/border-layout/BorderLayout.js.map +1 -1
  166. package/dist-es/breadcrumbs/Breadcrumb.js +5 -6
  167. package/dist-es/breadcrumbs/Breadcrumb.js.map +1 -1
  168. package/dist-es/button/Button.css.js +1 -1
  169. package/dist-es/card/CardContent.css.js +1 -1
  170. package/dist-es/card/hasCardSection.js +11 -3
  171. package/dist-es/card/hasCardSection.js.map +1 -1
  172. package/dist-es/checkbox/CheckboxIcon.js.map +1 -1
  173. package/dist-es/collapsible/CollapsiblePanel.css.js +1 -1
  174. package/dist-es/collapsible/CollapsiblePanel.js +16 -16
  175. package/dist-es/collapsible/CollapsiblePanel.js.map +1 -1
  176. package/dist-es/combo-box/ComboBox.js.map +1 -1
  177. package/dist-es/dialog/DialogHeader.js +2 -0
  178. package/dist-es/dialog/DialogHeader.js.map +1 -1
  179. package/dist-es/drawer/Drawer.css.js +1 -1
  180. package/dist-es/drawer/Drawer.js +54 -6
  181. package/dist-es/drawer/Drawer.js.map +1 -1
  182. package/dist-es/drawer/DrawerContext.js +2 -0
  183. package/dist-es/drawer/DrawerContext.js.map +1 -1
  184. package/dist-es/drawer/DrawerFooter.css.js +1 -1
  185. package/dist-es/drawer/DrawerHeader.css.js +1 -1
  186. package/dist-es/drawer/DrawerHeader.js +8 -3
  187. package/dist-es/drawer/DrawerHeader.js.map +1 -1
  188. package/dist-es/drawer/internal/DrawerResizeGuide.css.js +4 -0
  189. package/dist-es/drawer/internal/DrawerResizeGuide.css.js.map +1 -0
  190. package/dist-es/drawer/internal/DrawerResizeGuide.js +42 -0
  191. package/dist-es/drawer/internal/DrawerResizeGuide.js.map +1 -0
  192. package/dist-es/drawer/internal/DrawerResizeHandle.css.js +4 -0
  193. package/dist-es/drawer/internal/DrawerResizeHandle.css.js.map +1 -0
  194. package/dist-es/drawer/internal/DrawerResizeHandle.js +41 -0
  195. package/dist-es/drawer/internal/DrawerResizeHandle.js.map +1 -0
  196. package/dist-es/drawer/internal/useDrawerResize.js +517 -0
  197. package/dist-es/drawer/internal/useDrawerResize.js.map +1 -0
  198. package/dist-es/dropdown/Dropdown.css.js +1 -1
  199. package/dist-es/dropdown/Dropdown.js +1 -1
  200. package/dist-es/dropdown/Dropdown.js.map +1 -1
  201. package/dist-es/form-field/FormField.js +2 -2
  202. package/dist-es/form-field/FormField.js.map +1 -1
  203. package/dist-es/form-field/FormFieldHelperText.js +2 -0
  204. package/dist-es/form-field/FormFieldHelperText.js.map +1 -1
  205. package/dist-es/form-field/FormFieldLabel.css.js +1 -1
  206. package/dist-es/form-field/FormFieldLabel.js +2 -0
  207. package/dist-es/form-field/FormFieldLabel.js.map +1 -1
  208. package/dist-es/form-field-context/FormFieldContext.js.map +1 -1
  209. package/dist-es/index.js +3 -0
  210. package/dist-es/index.js.map +1 -1
  211. package/dist-es/input/Input.css.js +1 -1
  212. package/dist-es/link/Link.js +2 -0
  213. package/dist-es/link/Link.js.map +1 -1
  214. package/dist-es/link/LinkAction.js +3 -2
  215. package/dist-es/link/LinkAction.js.map +1 -1
  216. package/dist-es/link-button/LinkButton.css.js +1 -1
  217. package/dist-es/link-button/LinkButton.js +3 -2
  218. package/dist-es/link-button/LinkButton.js.map +1 -1
  219. package/dist-es/list-box/ListBox.js +1 -1
  220. package/dist-es/list-box/ListBox.js.map +1 -1
  221. package/dist-es/list-control/ListControlContext.js.map +1 -1
  222. package/dist-es/list-control/ListControlOptionContext.js.map +1 -1
  223. package/dist-es/mega-menu/MegaMenuGroupHeading.css.js +1 -1
  224. package/dist-es/mega-menu/MegaMenuListItem.css.js +1 -1
  225. package/dist-es/menu/MenuAlignmentContext.js +50 -0
  226. package/dist-es/menu/MenuAlignmentContext.js.map +1 -0
  227. package/dist-es/menu/MenuBase.js +9 -3
  228. package/dist-es/menu/MenuBase.js.map +1 -1
  229. package/dist-es/menu/MenuGroup.css.js +1 -1
  230. package/dist-es/menu/MenuGroup.js +44 -5
  231. package/dist-es/menu/MenuGroup.js.map +1 -1
  232. package/dist-es/menu/MenuGroupContext.js +23 -0
  233. package/dist-es/menu/MenuGroupContext.js.map +1 -0
  234. package/dist-es/menu/MenuItem.css.js +1 -1
  235. package/dist-es/menu/MenuItem.js +177 -51
  236. package/dist-es/menu/MenuItem.js.map +1 -1
  237. package/dist-es/menu/MenuPanel.js +12 -3
  238. package/dist-es/menu/MenuPanel.js.map +1 -1
  239. package/dist-es/menu/MenuPanelContext.js +3 -1
  240. package/dist-es/menu/MenuPanelContext.js.map +1 -1
  241. package/dist-es/multiline-input/MultilineInput.css.js +1 -1
  242. package/dist-es/navigation-item/NavigationItem.css.js +1 -1
  243. package/dist-es/number-input/NumberInput.css.js +1 -1
  244. package/dist-es/on-solid-button/OnSolidButton.css.js +4 -0
  245. package/dist-es/on-solid-button/OnSolidButton.css.js.map +1 -0
  246. package/dist-es/on-solid-button/OnSolidButton.js +66 -0
  247. package/dist-es/on-solid-button/OnSolidButton.js.map +1 -0
  248. package/dist-es/option/Option.css.js +1 -1
  249. package/dist-es/option/Option.js +7 -1
  250. package/dist-es/option/Option.js.map +1 -1
  251. package/dist-es/option/OptionGroup.css.js +1 -1
  252. package/dist-es/overlay/OverlayHeader.js +2 -0
  253. package/dist-es/overlay/OverlayHeader.js.map +1 -1
  254. package/dist-es/overlay/OverlayPanelCloseButton.js +1 -1
  255. package/dist-es/overlay/OverlayPanelCloseButton.js.map +1 -1
  256. package/dist-es/pagination/CompactPaginator.js +2 -0
  257. package/dist-es/pagination/CompactPaginator.js.map +1 -1
  258. package/dist-es/pagination/GoToInput.js +2 -0
  259. package/dist-es/pagination/GoToInput.js.map +1 -1
  260. package/dist-es/pill/PillCheckIcon.js.map +1 -1
  261. package/dist-es/pill-input/PillInput.css.js +1 -1
  262. package/dist-es/progress/CircularProgress/CircularProgress.js +2 -0
  263. package/dist-es/progress/CircularProgress/CircularProgress.js.map +1 -1
  264. package/dist-es/progress/LinearProgress/LinearProgress.js +2 -0
  265. package/dist-es/progress/LinearProgress/LinearProgress.js.map +1 -1
  266. package/dist-es/salt-provider/ThemeApplicator.js +10 -6
  267. package/dist-es/salt-provider/ThemeApplicator.js.map +1 -1
  268. package/dist-es/side-panel/SidePanelTitle.js +2 -0
  269. package/dist-es/side-panel/SidePanelTitle.js.map +1 -1
  270. package/dist-es/side-panel/SidePanelTrigger.js.map +1 -1
  271. package/dist-es/side-panel/internal/useIsScrollable.js.map +1 -1
  272. package/dist-es/side-panel/useSidePanel.js +4 -9
  273. package/dist-es/side-panel/useSidePanel.js.map +1 -1
  274. package/dist-es/skip-link/internal/useManageFocusOnTarget.js +2 -2
  275. package/dist-es/skip-link/internal/useManageFocusOnTarget.js.map +1 -1
  276. package/dist-es/slider/internal/SliderThumb.js.map +1 -1
  277. package/dist-es/slider/internal/SliderTooltip.js +2 -0
  278. package/dist-es/slider/internal/SliderTooltip.js.map +1 -1
  279. package/dist-es/slider/internal/SliderTrack.js +2 -0
  280. package/dist-es/slider/internal/SliderTrack.js.map +1 -1
  281. package/dist-es/slider/internal/useRangeSliderThumb.js.map +1 -1
  282. package/dist-es/slider/internal/useSliderThumb.js.map +1 -1
  283. package/dist-es/slider/internal/utils.js.map +1 -1
  284. package/dist-es/stepper/Stepper.js +1 -1
  285. package/dist-es/stepper/Stepper.js.map +1 -1
  286. package/dist-es/stepper/internal/StepText.css.js +1 -1
  287. package/dist-es/stepper/internal/StepText.js +2 -0
  288. package/dist-es/stepper/internal/StepText.js.map +1 -1
  289. package/dist-es/table/Table.css.js +1 -1
  290. package/dist-es/tabs/Tabs.js +1 -1
  291. package/dist-es/tabs/Tabs.js.map +1 -1
  292. package/dist-es/tabs/internal/overflow/useOverflow.js.map +1 -1
  293. package/dist-es/tabs/internal/overflow/useRenderedTabWidth.js.map +1 -1
  294. package/dist-es/text/Code.js +1 -1
  295. package/dist-es/text/Code.js.map +1 -1
  296. package/dist-es/text/Editorial.js +25 -0
  297. package/dist-es/text/Editorial.js.map +1 -0
  298. package/dist-es/text/Eyebrow.js +10 -0
  299. package/dist-es/text/Eyebrow.js.map +1 -0
  300. package/dist-es/text/Text.css.js +1 -1
  301. package/dist-es/text/Text.js +6 -2
  302. package/dist-es/text/Text.js.map +1 -1
  303. package/dist-es/toggle-button/ToggleButton.css.js +1 -1
  304. package/dist-es/toggle-button/ToggleButton.js.map +1 -1
  305. package/dist-es/toolbar/ToolbarOverflow.js +8 -4
  306. package/dist-es/toolbar/ToolbarOverflow.js.map +1 -1
  307. package/dist-es/toolbar/toolbarUtils.js.map +1 -1
  308. package/dist-es/tooltip/useAriaAnnounce.js +4 -2
  309. package/dist-es/tooltip/useAriaAnnounce.js.map +1 -1
  310. package/dist-es/tooltip/useTooltip.js.map +1 -1
  311. package/dist-es/tree/TreeContext.js.map +1 -1
  312. package/dist-es/tree/TreeNodeTrigger.css.js +1 -1
  313. package/dist-es/tree/TreeNodeTrigger.js +0 -1
  314. package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
  315. package/dist-es/utils/forkRef.js +32 -0
  316. package/dist-es/utils/forkRef.js.map +1 -0
  317. package/dist-es/utils/getRefFromChildren.js.map +1 -1
  318. package/dist-es/utils/marginMiddleware.js.map +1 -1
  319. package/dist-es/utils/setRef.js.map +1 -1
  320. package/dist-es/utils/useFloatingUI/useFloatingUI.js.map +1 -1
  321. package/dist-es/utils/useForkRef.js +3 -6
  322. package/dist-es/utils/useForkRef.js.map +1 -1
  323. package/dist-es/utils/useResizeObserver.js.map +1 -1
  324. package/dist-es/vertical-navigation/VerticalNavigationSubMenu.css.js +1 -1
  325. package/dist-types/checkbox/CheckboxIcon.d.ts +2 -1
  326. package/dist-types/collapsible/CollapsiblePanel.d.ts +8 -1
  327. package/dist-types/combo-box/ComboBox.d.ts +2 -2
  328. package/dist-types/drawer/Drawer.d.ts +6 -0
  329. package/dist-types/drawer/DrawerContext.d.ts +3 -0
  330. package/dist-types/drawer/DrawerHeader.d.ts +1 -1
  331. package/dist-types/drawer/internal/DrawerResizeGuide.d.ts +7 -0
  332. package/dist-types/drawer/internal/DrawerResizeHandle.d.ts +8 -0
  333. package/dist-types/drawer/internal/index.d.ts +3 -0
  334. package/dist-types/drawer/internal/useDrawerResize.d.ts +34 -0
  335. package/dist-types/dropdown/Dropdown.d.ts +2 -2
  336. package/dist-types/form-field/FormFieldHelperText.d.ts +1 -1
  337. package/dist-types/form-field/FormFieldLabel.d.ts +1 -1
  338. package/dist-types/form-field-context/FormFieldContext.d.ts +1 -1
  339. package/dist-types/index.d.ts +1 -0
  340. package/dist-types/list-box/ListBox.d.ts +2 -2
  341. package/dist-types/list-control/ListControlContext.d.ts +1 -1
  342. package/dist-types/list-control/ListControlOptionContext.d.ts +1 -1
  343. package/dist-types/menu/MenuAlignmentContext.d.ts +14 -0
  344. package/dist-types/menu/MenuGroup.d.ts +26 -4
  345. package/dist-types/menu/MenuGroupContext.d.ts +10 -0
  346. package/dist-types/menu/MenuItem.d.ts +4 -0
  347. package/dist-types/menu/MenuPanelContext.d.ts +2 -0
  348. package/dist-types/on-solid-button/OnSolidButton.d.ts +12 -0
  349. package/dist-types/on-solid-button/index.d.ts +1 -0
  350. package/dist-types/pill/PillCheckIcon.d.ts +2 -1
  351. package/dist-types/registerClassNameInjection.d.ts +0 -2
  352. package/dist-types/salt-provider/SaltProvider.d.ts +1 -1
  353. package/dist-types/side-panel/internal/useIsScrollable.d.ts +1 -1
  354. package/dist-types/skip-link/internal/useManageFocusOnTarget.d.ts +1 -1
  355. package/dist-types/slider/internal/SliderThumb.d.ts +2 -2
  356. package/dist-types/slider/internal/SliderTrack.d.ts +2 -2
  357. package/dist-types/slider/internal/useRangeSliderThumb.d.ts +1 -1
  358. package/dist-types/slider/internal/useSliderThumb.d.ts +1 -1
  359. package/dist-types/slider/internal/utils.d.ts +1 -1
  360. package/dist-types/tabs/internal/overflow/useOverflow.d.ts +2 -2
  361. package/dist-types/tabs/internal/overflow/useRenderedTabWidth.d.ts +1 -1
  362. package/dist-types/text/Editorial.d.ts +7 -0
  363. package/dist-types/text/Eyebrow.d.ts +2 -0
  364. package/dist-types/text/Text.d.ts +9 -2
  365. package/dist-types/text/index.d.ts +2 -0
  366. package/dist-types/toggle-button/ToggleButton.d.ts +1 -1
  367. package/dist-types/tooltip/useTooltip.d.ts +12 -26
  368. package/dist-types/tree/TreeContext.d.ts +1 -1
  369. package/dist-types/utils/forkRef.d.ts +11 -0
  370. package/dist-types/utils/inferElementType.d.ts +1 -2
  371. package/dist-types/utils/marginMiddleware.d.ts +1 -1
  372. package/dist-types/utils/setRef.d.ts +4 -0
  373. package/dist-types/utils/useFloatingUI/useFloatingUI.d.ts +1 -5
  374. package/dist-types/utils/useResizeObserver.d.ts +1 -1
  375. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltMegaMenuGroupHeading {\n display: flex;\n align-items: center;\n margin: 0 0 var(--salt-spacing-50);\n padding: var(--salt-spacing-50) var(--salt-spacing-100);\n border-bottom: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--salt-separable-tertiary-borderColor);\n min-height: var(--salt-size-base);\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-label-fontSize);\n font-weight: var(--salt-text-fontWeight-strong);\n line-height: var(--salt-text-label-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n color: var(--salt-content-secondary-foreground);\n}\n";
1
+ var css_248z = ".saltMegaMenuGroupHeading {\n display: flex;\n align-items: center;\n margin: 0 0 var(--salt-spacing-50);\n padding: var(--salt-spacing-50) var(--salt-spacing-100);\n border-bottom: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--salt-separable-tertiary-borderColor);\n min-height: var(--salt-size-base);\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-label-fontSize);\n font-weight: var(--salt-text-fontWeight-bolder);\n line-height: var(--salt-text-label-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n color: var(--salt-content-secondary-foreground);\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=MegaMenuGroupHeading.css.js.map
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltMegaMenuListItem {\n list-style: none;\n display: flex;\n flex-direction: column;\n}\n\n.saltMegaMenuListItem-wrapper {\n display: flex;\n padding: var(--salt-spacing-50) var(--salt-spacing-100);\n align-items: flex-start;\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n cursor: var(--salt-cursor-hover);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n box-sizing: border-box;\n gap: var(--salt-spacing-100);\n position: relative;\n border-radius: var(--salt-palette-corner-weak, 0);\n text-decoration: none;\n border: none;\n font: inherit;\n text-align: start;\n}\n\n.saltMegaMenuListItem-wrapper > .saltIcon {\n display: flex;\n height: var(--salt-size-base);\n align-items: center;\n}\n\n.saltMegaMenuListItem-content {\n flex: 1 0;\n margin: var(--salt-spacing-75) 0;\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n}\n\n.saltMegaMenuListItem-wrapper:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-fixed-100) * -2);\n}\n\n.saltMegaMenuListItem-wrapper:hover:not(:focus-visible) {\n outline: none;\n background: var(--salt-overlayable-background-hover);\n}\n\n.saltMegaMenuListItem-wrapper:active {\n background: var(--salt-navigable-accent-background-active);\n}\n\n.saltMegaMenuListItem-wrapper:active::before {\n content: \"\";\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n border-radius: inherit;\n border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--salt-navigable-accent-borderColor-active);\n pointer-events: none;\n}\n";
1
+ var css_248z = ".saltMegaMenuListItem {\n list-style: none;\n display: flex;\n flex-direction: column;\n}\n\n.saltMegaMenuListItem-wrapper {\n display: flex;\n padding: var(--salt-spacing-50) var(--salt-spacing-100);\n align-items: flex-start;\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n cursor: var(--salt-cursor-hover);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n box-sizing: border-box;\n gap: var(--salt-spacing-100);\n position: relative;\n border-radius: var(--salt-palette-corner-weak, 0);\n text-decoration: none;\n border: none;\n font: inherit;\n text-align: start;\n}\n\n.saltMegaMenuListItem-wrapper > .saltIcon {\n display: flex;\n height: var(--salt-size-base);\n align-items: center;\n}\n\n.saltMegaMenuListItem-content {\n flex: 1 0;\n margin: var(--salt-spacing-75) 0;\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n}\n\n.saltMegaMenuListItem-wrapper:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-fixed-100) * -2);\n}\n\n.saltMegaMenuListItem-wrapper:hover:not(:focus-visible, :active) {\n outline: none;\n background: var(--salt-overlayable-background-hover);\n}\n\n.saltMegaMenuListItem-wrapper:active {\n background: var(--salt-navigable-accent-background-active);\n}\n\n.saltMegaMenuListItem-wrapper:active::before {\n content: \"\";\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n border-radius: inherit;\n border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--salt-navigable-accent-borderColor-active);\n pointer-events: none;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=MegaMenuListItem.css.js.map
@@ -0,0 +1,50 @@
1
+ import { useMemo, useState, useCallback, useContext } from 'react';
2
+ import { createContext } from '../utils/createContext.js';
3
+ import 'clsx';
4
+ import 'react/jsx-runtime';
5
+ import '../utils/useFloatingUI/useFloatingUI.js';
6
+ import '../utils/useId.js';
7
+ import '../salt-provider/SaltProvider.js';
8
+ import '../viewport/ViewportProvider.js';
9
+
10
+ const MenuAlignmentContext = createContext(
11
+ "MenuAlignmentContext",
12
+ {
13
+ reserveIconSpace: false,
14
+ reserveSelectionIconSpace: false,
15
+ registerIcon: () => () => void 0,
16
+ registerSelectionIcon: () => () => void 0
17
+ }
18
+ );
19
+ function useSlotRegistry() {
20
+ const [count, setCount] = useState(0);
21
+ const register = useCallback(() => {
22
+ setCount((current) => current + 1);
23
+ return () => setCount((current) => current - 1);
24
+ }, []);
25
+ return [count > 0, register];
26
+ }
27
+ function useMenuAlignmentScope() {
28
+ const [reserveIconSpace, registerIcon] = useSlotRegistry();
29
+ const [reserveSelectionIconSpace, registerSelectionIcon] = useSlotRegistry();
30
+ return useMemo(
31
+ () => ({
32
+ reserveIconSpace,
33
+ reserveSelectionIconSpace,
34
+ registerIcon,
35
+ registerSelectionIcon
36
+ }),
37
+ [
38
+ reserveIconSpace,
39
+ reserveSelectionIconSpace,
40
+ registerIcon,
41
+ registerSelectionIcon
42
+ ]
43
+ );
44
+ }
45
+ function useMenuAlignment() {
46
+ return useContext(MenuAlignmentContext);
47
+ }
48
+
49
+ export { MenuAlignmentContext, useMenuAlignment, useMenuAlignmentScope, useSlotRegistry };
50
+ //# sourceMappingURL=MenuAlignmentContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuAlignmentContext.js","sources":["../src/menu/MenuAlignmentContext.ts"],"sourcesContent":["import { useCallback, useContext, useMemo, useState } from \"react\";\nimport { createContext } from \"../utils\";\n\n/**\n * The leading slots that items in one alignment scope reserve for each other.\n * Each `MenuGroup` is a scope, and items outside a group share their `MenuPanel`'s scope.\n */\nexport interface MenuAlignmentContextValue {\n reserveIconSpace: boolean;\n reserveSelectionIconSpace: boolean;\n registerIcon: () => () => void;\n registerSelectionIcon: () => () => void;\n}\n\nexport const MenuAlignmentContext = createContext<MenuAlignmentContextValue>(\n \"MenuAlignmentContext\",\n {\n reserveIconSpace: false,\n reserveSelectionIconSpace: false,\n registerIcon: () => () => undefined,\n registerSelectionIcon: () => () => undefined,\n },\n);\n\nexport function useSlotRegistry() {\n const [count, setCount] = useState(0);\n const register = useCallback(() => {\n setCount((current) => current + 1);\n return () => setCount((current) => current - 1);\n }, []);\n return [count > 0, register] as const;\n}\n\nexport function useMenuAlignmentScope(): MenuAlignmentContextValue {\n const [reserveIconSpace, registerIcon] = useSlotRegistry();\n const [reserveSelectionIconSpace, registerSelectionIcon] = useSlotRegistry();\n return useMemo(\n () => ({\n reserveIconSpace,\n reserveSelectionIconSpace,\n registerIcon,\n registerSelectionIcon,\n }),\n [\n reserveIconSpace,\n reserveSelectionIconSpace,\n registerIcon,\n registerSelectionIcon,\n ],\n );\n}\n\nexport function useMenuAlignment() {\n return useContext(MenuAlignmentContext);\n}\n"],"names":[],"mappings":";;;;;;;;;AAcO,MAAM,oBAAA,GAAuB,aAAA;AAAA,EAClC,sBAAA;AAAA,EACA;AAAA,IACE,gBAAA,EAAkB,KAAA;AAAA,IAClB,yBAAA,EAA2B,KAAA;AAAA,IAC3B,YAAA,EAAc,MAAM,MAAM,MAAA;AAAA,IAC1B,qBAAA,EAAuB,MAAM,MAAM;AAAA;AAEvC;AAEO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,CAAC,CAAA;AACpC,EAAA,MAAM,QAAA,GAAW,YAAY,MAAM;AACjC,IAAA,QAAA,CAAS,CAAC,OAAA,KAAY,OAAA,GAAU,CAAC,CAAA;AACjC,IAAA,OAAO,MAAM,QAAA,CAAS,CAAC,OAAA,KAAY,UAAU,CAAC,CAAA;AAAA,EAChD,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,OAAO,CAAC,KAAA,GAAQ,CAAA,EAAG,QAAQ,CAAA;AAC7B;AAEO,SAAS,qBAAA,GAAmD;AACjE,EAAA,MAAM,CAAC,gBAAA,EAAkB,YAAY,CAAA,GAAI,eAAA,EAAgB;AACzD,EAAA,MAAM,CAAC,yBAAA,EAA2B,qBAAqB,CAAA,GAAI,eAAA,EAAgB;AAC3E,EAAA,OAAO,OAAA;AAAA,IACL,OAAO;AAAA,MACL,gBAAA;AAAA,MACA,yBAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,gBAAA;AAAA,MACA,yBAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;AAEO,SAAS,gBAAA,GAAmB;AACjC,EAAA,OAAO,WAAW,oBAAoB,CAAA;AACxC;;;;"}
@@ -9,6 +9,7 @@ import '../utils/useId.js';
9
9
  import '../salt-provider/SaltProvider.js';
10
10
  import '../viewport/ViewportProvider.js';
11
11
  import { MenuContext } from './MenuContext.js';
12
+ import { MenuGroupContext, defaultMenuGroupContextValue } from './MenuGroupContext.js';
12
13
 
13
14
  function MenuBase(props) {
14
15
  const {
@@ -40,10 +41,14 @@ function MenuBase(props) {
40
41
  const [focusInside, setFocusInside] = useState(false);
41
42
  const [triggerDisabled, setTriggerDisabled] = useState(false);
42
43
  const isNested = parentId != null;
44
+ const handleOpenChange = (newOpen) => {
45
+ if (newOpen && triggerDisabled) return;
46
+ setOpen(newOpen);
47
+ };
43
48
  const { x, y, strategy, elements, refs, context } = useFloatingUI({
44
49
  nodeId,
45
50
  open: openState,
46
- onOpenChange: setOpen,
51
+ onOpenChange: handleOpenChange,
47
52
  strategy: !getVirtualElement ? "absolute" : "fixed",
48
53
  placement: placement ?? (isNested || getVirtualElement ? "right-start" : "bottom-start"),
49
54
  middleware: [
@@ -84,7 +89,8 @@ function MenuBase(props) {
84
89
  listRef: elementsRef,
85
90
  activeIndex,
86
91
  nested: isNested,
87
- onNavigate: setActiveIndex
92
+ onNavigate: setActiveIndex,
93
+ disabledIndices: (index) => elementsRef.current[index] == null
88
94
  })
89
95
  ]
90
96
  );
@@ -127,7 +133,7 @@ function MenuBase(props) {
127
133
  triggerDisabled,
128
134
  setTriggerDisabled
129
135
  },
130
- children
136
+ children: /* @__PURE__ */ jsx(MenuGroupContext.Provider, { value: defaultMenuGroupContextValue, children })
131
137
  }
132
138
  ) });
133
139
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MenuBase.js","sources":["../src/menu/MenuBase.tsx"],"sourcesContent":["import {\n FloatingNode,\n flip,\n limitShift,\n offset,\n type ReferenceType,\n safePolygon,\n shift,\n size,\n useClick,\n useDismiss,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useRole,\n} from \"@floating-ui/react\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n type UseFloatingUIProps,\n useControlled,\n useFloatingUI,\n useIsomorphicLayoutEffect,\n} from \"../utils\";\nimport { MenuContext } from \"./MenuContext\";\n\nexport interface MenuBaseProps {\n children?: ReactNode;\n /**\n * Display or hide the component.\n */\n open?: boolean;\n /**\n * If true, the menu will be open by default.\n */\n defaultOpen?: boolean;\n /**\n * Callback function triggered when open state changes.\n */\n onOpenChange?: (newOpen: boolean) => void;\n /**\n * Set the placement of the Menu component relative to the trigger element. Defaults to `bottom-start` if it's the root menu or `right-start` if it's nested.\n */\n placement?: UseFloatingUIProps[\"placement\"];\n /**\n * Function that returns a [virtual element](https://floating-ui.com/docs/virtual-elements). If this is provided, it will override MenuTrigger.\n */\n getVirtualElement?: () => ReferenceType | null;\n}\n\nexport function MenuBase(props: MenuBaseProps) {\n const {\n children,\n defaultOpen,\n open,\n onOpenChange,\n placement,\n getVirtualElement,\n } = props;\n const parentId = useFloatingParentNodeId();\n const nodeId = useFloatingNodeId();\n const tree = useFloatingTree();\n const elementsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n const [openState, setOpenState] = useControlled({\n controlled: open,\n default: Boolean(defaultOpen),\n name: \"ListControl\",\n state: \"open\",\n });\n\n const setOpen = useCallback(\n (newOpen: boolean) => {\n setOpenState(newOpen);\n onOpenChange?.(newOpen);\n },\n [onOpenChange],\n );\n\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [focusInside, setFocusInside] = useState(false);\n const [triggerDisabled, setTriggerDisabled] = useState(false);\n\n const isNested = parentId != null;\n\n const { x, y, strategy, elements, refs, context } = useFloatingUI({\n nodeId,\n open: openState,\n onOpenChange: setOpen,\n strategy: !getVirtualElement ? \"absolute\" : \"fixed\",\n placement:\n placement ??\n (isNested || getVirtualElement ? \"right-start\" : \"bottom-start\"),\n middleware: [\n // Align the nested menu by shifting it by var(--salt-spacing-fixed-100)\n offset(\n isNested ? { crossAxis: -1, mainAxis: 2 } : !getVirtualElement ? 1 : 0,\n ),\n flip({}),\n shift({ limiter: limitShift() }),\n size({\n apply({ elements, availableHeight }) {\n Object.assign(elements.floating.style, {\n maxHeight: `${availableHeight}px`,\n });\n },\n }),\n ],\n });\n\n useIsomorphicLayoutEffect(() => {\n if (getVirtualElement) {\n refs.setPositionReference(getVirtualElement());\n }\n }, [getVirtualElement, refs]);\n\n const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(\n [\n useHover(context, {\n enabled: isNested && !focusInside && !triggerDisabled,\n handleClose: safePolygon({ blockPointerEvents: true }),\n }),\n useClick(context, {\n event: \"mousedown\",\n toggle: !isNested,\n ignoreMouse: isNested,\n }),\n useRole(context, { role: \"menu\" }),\n useDismiss(context, { bubbles: true }),\n useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n }),\n ],\n );\n\n const getPanelPosition = () => ({\n top: y ?? 0,\n left: x ?? 0,\n position: strategy,\n width: elements.floating?.offsetWidth,\n height: elements.floating?.offsetHeight,\n });\n\n useEffect(() => {\n if (!tree) return;\n\n function handleItemClick() {\n setOpen(false);\n }\n\n tree.events.on(\"click\", handleItemClick);\n\n return () => {\n tree.events.off(\"click\", handleItemClick);\n };\n }, [tree, setOpen]);\n\n return (\n <FloatingNode id={nodeId}>\n <MenuContext.Provider\n value={{\n openState,\n getReferenceProps,\n getFloatingProps,\n refs,\n getPanelPosition,\n getItemProps,\n activeIndex,\n context,\n elementsRef,\n focusInside,\n setFocusInside,\n isNested,\n triggerDisabled,\n setTriggerDisabled,\n }}\n >\n {children}\n </MenuContext.Provider>\n </FloatingNode>\n );\n}\n"],"names":["elements"],"mappings":"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"}
1
+ {"version":3,"file":"MenuBase.js","sources":["../src/menu/MenuBase.tsx"],"sourcesContent":["import {\n FloatingNode,\n flip,\n limitShift,\n offset,\n type ReferenceType,\n safePolygon,\n shift,\n size,\n useClick,\n useDismiss,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useRole,\n} from \"@floating-ui/react\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n type UseFloatingUIProps,\n useControlled,\n useFloatingUI,\n useIsomorphicLayoutEffect,\n} from \"../utils\";\nimport { MenuContext } from \"./MenuContext\";\nimport {\n defaultMenuGroupContextValue,\n MenuGroupContext,\n} from \"./MenuGroupContext\";\n\nexport interface MenuBaseProps {\n children?: ReactNode;\n /**\n * Display or hide the component.\n */\n open?: boolean;\n /**\n * If true, the menu will be open by default.\n */\n defaultOpen?: boolean;\n /**\n * Callback function triggered when open state changes.\n */\n onOpenChange?: (newOpen: boolean) => void;\n /**\n * Set the placement of the Menu component relative to the trigger element. Defaults to `bottom-start` if it's the root menu or `right-start` if it's nested.\n */\n placement?: UseFloatingUIProps[\"placement\"];\n /**\n * Function that returns a [virtual element](https://floating-ui.com/docs/virtual-elements). If this is provided, it will override MenuTrigger.\n */\n getVirtualElement?: () => ReferenceType | null;\n}\n\nexport function MenuBase(props: MenuBaseProps) {\n const {\n children,\n defaultOpen,\n open,\n onOpenChange,\n placement,\n getVirtualElement,\n } = props;\n const parentId = useFloatingParentNodeId();\n const nodeId = useFloatingNodeId();\n const tree = useFloatingTree();\n const elementsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n const [openState, setOpenState] = useControlled({\n controlled: open,\n default: Boolean(defaultOpen),\n name: \"ListControl\",\n state: \"open\",\n });\n\n const setOpen = useCallback(\n (newOpen: boolean) => {\n setOpenState(newOpen);\n onOpenChange?.(newOpen);\n },\n [onOpenChange],\n );\n\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [focusInside, setFocusInside] = useState(false);\n const [triggerDisabled, setTriggerDisabled] = useState(false);\n\n const isNested = parentId != null;\n\n const handleOpenChange = (newOpen: boolean) => {\n if (newOpen && triggerDisabled) return;\n setOpen(newOpen);\n };\n\n const { x, y, strategy, elements, refs, context } = useFloatingUI({\n nodeId,\n open: openState,\n onOpenChange: handleOpenChange,\n strategy: !getVirtualElement ? \"absolute\" : \"fixed\",\n placement:\n placement ??\n (isNested || getVirtualElement ? \"right-start\" : \"bottom-start\"),\n middleware: [\n // Align the nested menu by shifting it by var(--salt-spacing-fixed-100)\n offset(\n isNested ? { crossAxis: -1, mainAxis: 2 } : !getVirtualElement ? 1 : 0,\n ),\n flip({}),\n shift({ limiter: limitShift() }),\n size({\n apply({ elements, availableHeight }) {\n Object.assign(elements.floating.style, {\n maxHeight: `${availableHeight}px`,\n });\n },\n }),\n ],\n });\n\n useIsomorphicLayoutEffect(() => {\n if (getVirtualElement) {\n refs.setPositionReference(getVirtualElement());\n }\n }, [getVirtualElement, refs]);\n\n const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(\n [\n useHover(context, {\n enabled: isNested && !focusInside && !triggerDisabled,\n handleClose: safePolygon({ blockPointerEvents: true }),\n }),\n useClick(context, {\n event: \"mousedown\",\n toggle: !isNested,\n ignoreMouse: isNested,\n }),\n useRole(context, { role: \"menu\" }),\n useDismiss(context, { bubbles: true }),\n useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n disabledIndices: (index) => elementsRef.current[index] == null,\n }),\n ],\n );\n\n const getPanelPosition = () => ({\n top: y ?? 0,\n left: x ?? 0,\n position: strategy,\n width: elements.floating?.offsetWidth,\n height: elements.floating?.offsetHeight,\n });\n\n useEffect(() => {\n if (!tree) return;\n\n function handleItemClick() {\n setOpen(false);\n }\n\n tree.events.on(\"click\", handleItemClick);\n\n return () => {\n tree.events.off(\"click\", handleItemClick);\n };\n }, [tree, setOpen]);\n\n return (\n <FloatingNode id={nodeId}>\n <MenuContext.Provider\n value={{\n openState,\n getReferenceProps,\n getFloatingProps,\n refs,\n getPanelPosition,\n getItemProps,\n activeIndex,\n context,\n elementsRef,\n focusInside,\n setFocusInside,\n isNested,\n triggerDisabled,\n setTriggerDisabled,\n }}\n >\n <MenuGroupContext.Provider value={defaultMenuGroupContextValue}>\n {children}\n </MenuGroupContext.Provider>\n </MenuContext.Provider>\n </FloatingNode>\n );\n}\n"],"names":["elements"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltMenuGroup-label {\n background: var(--salt-container-primary-background);\n color: var(--salt-content-secondary-foreground);\n font-size: var(--salt-text-label-fontSize);\n font-weight: var(--salt-text-label-fontWeight-strong);\n font-family: var(--salt-text-fontFamily);\n line-height: var(--salt-text-label-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding: calc(var(--salt-spacing-100) + var(--salt-spacing-25)) var(--salt-spacing-100);\n display: flex;\n box-sizing: border-box;\n}\n\n.saltMenuGroup {\n border-top: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--salt-separable-tertiary-borderColor);\n}\n\n.saltMenuGroup:first-of-type {\n border-top: 0;\n}\n";
1
+ var css_248z = ".saltMenuGroup-label {\n background: var(--salt-container-primary-background);\n color: var(--salt-content-secondary-foreground);\n font-size: var(--salt-text-label-fontSize);\n font-weight: var(--salt-text-label-fontWeight-bolder);\n font-family: var(--salt-text-fontFamily);\n line-height: var(--salt-text-label-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding: calc(var(--salt-spacing-100) + var(--salt-spacing-25)) var(--salt-spacing-100);\n display: flex;\n box-sizing: border-box;\n}\n\n.saltMenuGroup {\n border-top: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--salt-separable-tertiary-borderColor);\n}\n\n.saltMenuGroup:first-of-type {\n border-top: 0;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=MenuGroup.css.js.map
@@ -1,19 +1,30 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useComponentCssInjection } from '@salt-ds/styles';
3
3
  import { useWindow } from '@salt-ds/window';
4
4
  import { clsx } from 'clsx';
5
- import { forwardRef } from 'react';
5
+ import { forwardRef, useMemo, useCallback } from 'react';
6
6
  import { makePrefixer } from '../utils/makePrefixer.js';
7
7
  import '../utils/useFloatingUI/useFloatingUI.js';
8
8
  import { useId } from '../utils/useId.js';
9
9
  import '../salt-provider/SaltProvider.js';
10
10
  import '../viewport/ViewportProvider.js';
11
+ import { useMenuAlignmentScope, MenuAlignmentContext } from './MenuAlignmentContext.js';
11
12
  import css_248z from './MenuGroup.css.js';
13
+ import { MenuGroupContext } from './MenuGroupContext.js';
12
14
 
13
15
  const withBaseName = makePrefixer("saltMenuGroup");
16
+ const noSelection = [];
14
17
  const MenuGroup = forwardRef(
15
18
  function MenuGroup2(props, ref) {
16
- const { className, children, label, ...rest } = props;
19
+ const {
20
+ className,
21
+ children,
22
+ label,
23
+ onSelectionChange,
24
+ selected: selectedProp = noSelection,
25
+ selectionVariant,
26
+ ...rest
27
+ } = props;
17
28
  const targetWindow = useWindow();
18
29
  useComponentCssInjection({
19
30
  testId: "salt-menu-group",
@@ -21,7 +32,35 @@ const MenuGroup = forwardRef(
21
32
  window: targetWindow
22
33
  });
23
34
  const labelId = useId();
24
- return /* @__PURE__ */ jsxs(
35
+ const selected = useMemo(
36
+ () => selectionVariant === "single" ? selectedProp.slice(0, 1) : selectedProp,
37
+ [selectedProp, selectionVariant]
38
+ );
39
+ const isSelected = useCallback(
40
+ (value) => selected.includes(value),
41
+ [selected]
42
+ );
43
+ const select = useCallback(
44
+ (event, value) => {
45
+ if (selectionVariant === "single") {
46
+ if (!selected.includes(value)) {
47
+ onSelectionChange == null ? void 0 : onSelectionChange(event, [value]);
48
+ }
49
+ } else if (selectionVariant === "multiple") {
50
+ onSelectionChange == null ? void 0 : onSelectionChange(
51
+ event,
52
+ selected.includes(value) ? selected.filter((item) => item !== value) : selected.concat(value)
53
+ );
54
+ }
55
+ },
56
+ [onSelectionChange, selected, selectionVariant]
57
+ );
58
+ const contextValue = useMemo(
59
+ () => ({ isSelected, select, selectionVariant }),
60
+ [isSelected, select, selectionVariant]
61
+ );
62
+ const alignment = useMenuAlignmentScope();
63
+ return /* @__PURE__ */ jsx(MenuGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(MenuAlignmentContext.Provider, { value: alignment, children: /* @__PURE__ */ jsxs(
25
64
  "div",
26
65
  {
27
66
  "aria-labelledby": label ? labelId : void 0,
@@ -34,7 +73,7 @@ const MenuGroup = forwardRef(
34
73
  children
35
74
  ]
36
75
  }
37
- );
76
+ ) }) });
38
77
  }
39
78
  );
40
79
 
@@ -1 +1 @@
1
- {"version":3,"file":"MenuGroup.js","sources":["../src/menu/MenuGroup.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n} from \"react\";\nimport { makePrefixer, useId } from \"../utils\";\nimport menuGroupCss from \"./MenuGroup.css\";\n\nexport interface MenuGroupProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The label of the menu group.\n */\n label?: string;\n /**\n * Menus to be rendered inside the menu group.\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltMenuGroup\");\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(\n function MenuGroup(props, ref) {\n const { className, children, label, ...rest } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-menu-group\",\n css: menuGroupCss,\n window: targetWindow,\n });\n\n const labelId = useId();\n\n return (\n <div\n aria-labelledby={label ? labelId : undefined}\n className={clsx(withBaseName(), className)}\n role=\"group\"\n ref={ref}\n {...rest}\n >\n {label && (\n <div aria-hidden className={withBaseName(\"label\")} id={labelId}>\n {label}\n </div>\n )}\n {children}\n </div>\n );\n },\n);\n"],"names":["MenuGroup","menuGroupCss"],"mappings":";;;;;;;;;;;;AAsBA,MAAM,YAAA,GAAe,aAAa,eAAe,CAAA;AAE1C,MAAM,SAAA,GAAY,UAAA;AAAA,EACvB,SAASA,UAAAA,CAAU,KAAA,EAAO,GAAA,EAAK;AAC7B,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AAEhD,IAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,iBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,MAAM,UAAU,KAAA,EAAM;AAEtB,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,iBAAA,EAAiB,QAAQ,OAAA,GAAU,MAAA;AAAA,QACnC,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACzC,IAAA,EAAK,OAAA;AAAA,QACL,GAAA;AAAA,QACC,GAAG,IAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,KAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,aAAA,EAAW,IAAA,EAAC,SAAA,EAAW,aAAa,OAAO,CAAA,EAAG,EAAA,EAAI,OAAA,EACpD,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAED;AAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;;;;"}
1
+ {"version":3,"file":"MenuGroup.js","sources":["../src/menu/MenuGroup.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n type SyntheticEvent,\n useCallback,\n useMemo,\n} from \"react\";\nimport { makePrefixer, useId } from \"../utils\";\nimport {\n MenuAlignmentContext,\n useMenuAlignmentScope,\n} from \"./MenuAlignmentContext\";\nimport menuGroupCss from \"./MenuGroup.css\";\nimport { MenuGroupContext } from \"./MenuGroupContext\";\n\ninterface BaseMenuGroupProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Menus to be rendered inside the menu group.\n */\n children?: ReactNode;\n /**\n * The label of the menu group.\n */\n label?: string;\n /**\n * Selection variant of the menu group. If \"single\", the menu items inside behave like radio buttons. If \"multiple\", they behave like checkboxes. Each selectable menu item needs a `value`. When omitted, the menu items are not selectable.\n */\n selectionVariant?: \"single\" | \"multiple\";\n}\n\ninterface SelectableMenuGroupProps extends BaseMenuGroupProps {\n /**\n * Callback fired when the selection changes.\n * @param event\n * @param newSelected The new selected values.\n */\n onSelectionChange?: (event: SyntheticEvent, newSelected: string[]) => void;\n /**\n * The values of the selected menu items. Required when `selectionVariant` is \"single\" or \"multiple\". The menu's content unmounts when it closes, so keep the selection in state and update it in `onSelectionChange`.\n */\n selected: string[];\n selectionVariant: \"single\" | \"multiple\";\n}\n\ninterface NonSelectableMenuGroupProps extends BaseMenuGroupProps {\n selectionVariant?: undefined;\n}\n\nexport type MenuGroupProps =\n | SelectableMenuGroupProps\n | NonSelectableMenuGroupProps;\n\nconst withBaseName = makePrefixer(\"saltMenuGroup\");\n\nconst noSelection: string[] = [];\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(\n function MenuGroup(props, ref) {\n const {\n className,\n children,\n label,\n onSelectionChange,\n selected: selectedProp = noSelection,\n selectionVariant,\n ...rest\n } = props as BaseMenuGroupProps &\n Partial<Pick<SelectableMenuGroupProps, \"onSelectionChange\" | \"selected\">>;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-menu-group\",\n css: menuGroupCss,\n window: targetWindow,\n });\n\n const labelId = useId();\n\n const selected = useMemo(\n () =>\n selectionVariant === \"single\" ? selectedProp.slice(0, 1) : selectedProp,\n [selectedProp, selectionVariant],\n );\n\n const isSelected = useCallback(\n (value: string) => selected.includes(value),\n [selected],\n );\n\n const select = useCallback(\n (event: SyntheticEvent, value: string) => {\n if (selectionVariant === \"single\") {\n if (!selected.includes(value)) {\n onSelectionChange?.(event, [value]);\n }\n } else if (selectionVariant === \"multiple\") {\n onSelectionChange?.(\n event,\n selected.includes(value)\n ? selected.filter((item) => item !== value)\n : selected.concat(value),\n );\n }\n },\n [onSelectionChange, selected, selectionVariant],\n );\n\n const contextValue = useMemo(\n () => ({ isSelected, select, selectionVariant }),\n [isSelected, select, selectionVariant],\n );\n\n const alignment = useMenuAlignmentScope();\n\n return (\n <MenuGroupContext.Provider value={contextValue}>\n <MenuAlignmentContext.Provider value={alignment}>\n <div\n aria-labelledby={label ? labelId : undefined}\n className={clsx(withBaseName(), className)}\n role=\"group\"\n ref={ref}\n {...rest}\n >\n {label && (\n <div aria-hidden className={withBaseName(\"label\")} id={labelId}>\n {label}\n </div>\n )}\n {children}\n </div>\n </MenuAlignmentContext.Provider>\n </MenuGroupContext.Provider>\n );\n },\n);\n"],"names":["MenuGroup","menuGroupCss"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { useContext } from 'react';
2
+ import { createContext } from '../utils/createContext.js';
3
+ import 'clsx';
4
+ import 'react/jsx-runtime';
5
+ import '../utils/useFloatingUI/useFloatingUI.js';
6
+ import '../utils/useId.js';
7
+ import '../salt-provider/SaltProvider.js';
8
+ import '../viewport/ViewportProvider.js';
9
+
10
+ const defaultMenuGroupContextValue = {
11
+ isSelected: () => false,
12
+ select: () => void 0
13
+ };
14
+ const MenuGroupContext = createContext(
15
+ "MenuGroupContext",
16
+ defaultMenuGroupContextValue
17
+ );
18
+ function useMenuGroup() {
19
+ return useContext(MenuGroupContext);
20
+ }
21
+
22
+ export { MenuGroupContext, defaultMenuGroupContextValue, useMenuGroup };
23
+ //# sourceMappingURL=MenuGroupContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuGroupContext.js","sources":["../src/menu/MenuGroupContext.ts"],"sourcesContent":["import { type SyntheticEvent, useContext } from \"react\";\nimport { createContext } from \"../utils\";\nimport type { MenuGroupProps } from \"./MenuGroup\";\n\nexport interface MenuGroupContextValue {\n isSelected: (value: string) => boolean;\n select: (event: SyntheticEvent, value: string) => void;\n selectionVariant?: MenuGroupProps[\"selectionVariant\"];\n}\n\nexport const defaultMenuGroupContextValue: MenuGroupContextValue = {\n isSelected: () => false,\n select: () => undefined,\n};\n\nexport const MenuGroupContext = createContext<MenuGroupContextValue>(\n \"MenuGroupContext\",\n defaultMenuGroupContextValue,\n);\n\nexport function useMenuGroup() {\n return useContext(MenuGroupContext);\n}\n"],"names":[],"mappings":";;;;;;;;;AAUO,MAAM,4BAAA,GAAsD;AAAA,EACjE,YAAY,MAAM,KAAA;AAAA,EAClB,QAAQ,MAAM;AAChB;AAEO,MAAM,gBAAA,GAAmB,aAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AACF;AAEO,SAAS,YAAA,GAAe;AAC7B,EAAA,OAAO,WAAW,gBAAgB,CAAA;AACpC;;;;"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltMenuItem {\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n font-family: var(--salt-text-fontFamily);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding: calc(var(--salt-spacing-100) + var(--salt-spacing-25)) var(--salt-spacing-100);\n display: flex;\n gap: var(--salt-spacing-100);\n position: relative;\n cursor: var(--salt-cursor-hover);\n box-sizing: border-box;\n flex-shrink: 0;\n}\n\n.saltMenuItem:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-fixed-100) * -2);\n}\n\n.saltMenuItem:hover {\n outline: none;\n}\n\n.saltMenuItem:hover,\n.saltMenuItem:focus-visible {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltMenuItem:active {\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n.saltMenuItem[aria-disabled=\"true\"],\n.saltMenuItem[aria-disabled=\"true\"]:active {\n opacity: 0.4;\n background: var(--salt-selectable-background);\n color: var(--salt-content-primary-foreground);\n cursor: var(--salt-cursor-disabled);\n box-shadow: none;\n}\n\n.saltMenuItem-blurActive {\n z-index: var(--salt-zIndex-default);\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n/* TODO: Find a better way of doing this */\n.saltMenuItem .saltIcon:not(.saltCheckboxIcon-icon) {\n min-height: var(--salt-text-lineHeight);\n}\n\n.saltMenuItem-expandIcon.saltIcon {\n margin-left: auto;\n}\n";
1
+ var css_248z = ".saltMenuItem {\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n font-family: var(--salt-text-fontFamily);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding: calc(var(--salt-spacing-100) + var(--salt-spacing-25)) var(--salt-spacing-100);\n display: flex;\n gap: var(--salt-spacing-100);\n position: relative;\n cursor: var(--salt-cursor-hover);\n box-sizing: border-box;\n flex-shrink: 0;\n --saltMenuItem-iconColumnWidth: max(var(--salt-size-icon), 12px);\n}\n\n.saltMenuItem:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-fixed-100) * -2);\n}\n\n.saltMenuItem:hover {\n outline: none;\n}\n\n.saltMenuItem:hover,\n.saltMenuItem:focus-visible {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltMenuItem[role=\"menuitem\"]:active {\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n.saltMenuItem[aria-disabled=\"true\"],\n.saltMenuItem[aria-disabled=\"true\"]:active {\n opacity: 0.4;\n background: var(--salt-selectable-background);\n color: var(--salt-content-primary-foreground);\n cursor: var(--salt-cursor-disabled);\n box-shadow: none;\n}\n\n.saltMenuItem-blurActive {\n z-index: var(--salt-zIndex-default);\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n/* TODO: Find a better way of doing this */\n.saltMenuItem .saltIcon:not(.saltCheckboxIcon-icon) {\n min-height: var(--salt-text-lineHeight);\n}\n\n.saltMenuItem .saltMenuItem-selectionIcon {\n margin: calc((var(--salt-text-lineHeight) - var(--salt-size-selectable)) / 2) 0;\n}\n\n.saltMenuItem-selectionIconPlaceholder {\n flex-shrink: 0;\n width: var(--salt-size-selectable);\n}\n\n.saltMenuItem-iconPlaceholder {\n flex-shrink: 0;\n width: var(--saltMenuItem-iconColumnWidth);\n}\n\n/* Account for selectable and icon token size differences, so labels after an icon line up with labels after a radio or checkbox */\n.saltMenuItem-selectionAlignedIcon {\n --saltMenuItem-iconColumnWidth: max(var(--salt-size-selectable), var(--salt-size-icon), 12px);\n}\n\n.saltMenuItem-selectionAlignedIcon > .saltIcon:first-child {\n margin-inline: max(0px, calc((var(--saltMenuItem-iconColumnWidth) - var(--icon-size)) / 2));\n}\n\n.saltMenuItem-expandIcon.saltIcon {\n margin-left: auto;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=MenuItem.css.js.map
@@ -3,20 +3,53 @@ import { useListItem, useFloatingTree } from '@floating-ui/react';
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, useEffect } from 'react';
6
+ import { forwardRef, useRef, useState, useEffect } from 'react';
7
+ import '../checkbox/Checkbox.js';
8
+ import '../checkbox/CheckboxGroup.js';
9
+ import { CheckboxIcon } from '../checkbox/CheckboxIcon.js';
10
+ import '../radio-button/RadioButton.js';
11
+ import '../radio-button/RadioButtonGroup.js';
12
+ import { RadioButtonIcon } from '../radio-button/RadioButtonIcon.js';
7
13
  import { useIcon } from '../semantic-icon-provider/SemanticIconProvider.js';
8
14
  import { makePrefixer } from '../utils/makePrefixer.js';
15
+ import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect.js';
9
16
  import '../utils/useFloatingUI/useFloatingUI.js';
10
17
  import { useForkRef } from '../utils/useForkRef.js';
11
18
  import '../utils/useId.js';
12
19
  import '../salt-provider/SaltProvider.js';
13
20
  import '../viewport/ViewportProvider.js';
21
+ import { useMenuAlignment } from './MenuAlignmentContext.js';
14
22
  import { useMenuContext } from './MenuContext.js';
23
+ import { useMenuGroup } from './MenuGroupContext.js';
15
24
  import css_248z from './MenuItem.css.js';
16
25
  import { useMenuPanelContext } from './MenuPanelContext.js';
17
26
  import { useIsMenuTrigger } from './MenuTriggerContext.js';
18
27
 
19
28
  const withBaseName = makePrefixer("saltMenuItem");
29
+ const leadingSlotClassNames = [
30
+ withBaseName("selectionIcon"),
31
+ withBaseName("selectionIconPlaceholder"),
32
+ withBaseName("iconPlaceholder")
33
+ ];
34
+ function hasLeadingIcon(item) {
35
+ var _a;
36
+ for (const node of Array.from((item == null ? void 0 : item.childNodes) ?? [])) {
37
+ if (node.nodeType === node.TEXT_NODE) {
38
+ if ((_a = node.textContent) == null ? void 0 : _a.trim()) {
39
+ return false;
40
+ }
41
+ } else if (node.nodeType === node.ELEMENT_NODE) {
42
+ const { classList } = node;
43
+ if (!leadingSlotClassNames.some(
44
+ (className) => classList.contains(className)
45
+ )) {
46
+ return classList.contains("saltIcon");
47
+ }
48
+ }
49
+ }
50
+ return false;
51
+ }
52
+ let missingValueWarningShown = false;
20
53
  const MenuItem = forwardRef(
21
54
  function MenuItem2(props, ref) {
22
55
  const {
@@ -26,12 +59,26 @@ const MenuItem = forwardRef(
26
59
  onClick,
27
60
  onFocus,
28
61
  onKeyDown,
62
+ value,
29
63
  ...rest
30
64
  } = props;
31
65
  const { triggersSubmenu, blurActive } = useIsMenuTrigger();
32
66
  const { setTriggerDisabled } = useMenuContext();
33
67
  const { ExpandGroupIcon } = useIcon();
34
- const { activeIndex, getItemProps, setFocusInside } = useMenuPanelContext();
68
+ const {
69
+ activeIndex,
70
+ getItemProps,
71
+ setFocusInside,
72
+ hasSelectionIcon,
73
+ registerPanelSelectionIcon
74
+ } = useMenuPanelContext();
75
+ const {
76
+ reserveIconSpace,
77
+ reserveSelectionIconSpace,
78
+ registerIcon,
79
+ registerSelectionIcon
80
+ } = useMenuAlignment();
81
+ const { isSelected, select, selectionVariant } = useMenuGroup();
35
82
  const item = useListItem();
36
83
  const tree = useFloatingTree();
37
84
  const active = item.index === activeIndex;
@@ -41,57 +88,136 @@ const MenuItem = forwardRef(
41
88
  css: css_248z,
42
89
  window: targetWindow
43
90
  });
44
- const handleRef = useForkRef(ref, item.ref);
91
+ const itemRef = useRef(null);
92
+ const listItemRef = useForkRef(item.ref, itemRef);
93
+ const handleRef = useForkRef(ref, listItemRef);
94
+ const activationKeyRef = useRef(null);
95
+ const [hasIcon, setHasIcon] = useState(false);
96
+ const insideSelectableGroup = selectionVariant !== void 0 && !triggersSubmenu;
97
+ const selectable = insideSelectableGroup && value !== void 0;
98
+ const selected = selectable && isSelected(value);
99
+ const alignIconWithSelectionIcon = hasSelectionIcon && !selectable && !reserveSelectionIconSpace && (hasIcon || reserveIconSpace);
100
+ useIsomorphicLayoutEffect(() => {
101
+ setHasIcon(hasLeadingIcon(itemRef.current));
102
+ });
103
+ useIsomorphicLayoutEffect(
104
+ () => hasIcon ? registerIcon() : void 0,
105
+ [hasIcon, registerIcon]
106
+ );
107
+ useIsomorphicLayoutEffect(() => {
108
+ if (!selectable) {
109
+ return void 0;
110
+ }
111
+ const unregisterFromGroup = registerSelectionIcon();
112
+ const unregisterFromPanel = registerPanelSelectionIcon();
113
+ return () => {
114
+ unregisterFromGroup();
115
+ unregisterFromPanel();
116
+ };
117
+ }, [selectable, registerSelectionIcon, registerPanelSelectionIcon]);
45
118
  useEffect(() => {
46
- setTriggerDisabled(!!disabled);
47
- }, [disabled, setTriggerDisabled]);
48
- return /* @__PURE__ */ jsxs(
49
- "div",
50
- {
51
- className: clsx(
52
- withBaseName(),
53
- {
54
- [withBaseName("blurActive")]: blurActive
55
- },
56
- className
57
- ),
58
- role: "menuitem",
59
- "aria-disabled": disabled || void 0,
60
- ...getItemProps({
61
- tabIndex: disabled ? void 0 : active ? 0 : -1,
62
- onKeyDown(event) {
63
- const element = event.currentTarget;
64
- onKeyDown == null ? void 0 : onKeyDown(event);
65
- if ((event.key === " " || event.key === "Enter") && !triggersSubmenu && !disabled) {
66
- event.preventDefault();
67
- const { view, ...eventInit } = event;
68
- queueMicrotask(() => {
69
- element.dispatchEvent(
70
- new window.MouseEvent("click", eventInit)
71
- );
72
- });
73
- }
74
- },
75
- onClick(event) {
76
- if (!disabled) {
77
- onClick == null ? void 0 : onClick(event);
78
- if (!triggersSubmenu) {
79
- tree == null ? void 0 : tree.events.emit("click");
80
- }
81
- }
82
- },
83
- onFocus(event) {
84
- onFocus == null ? void 0 : onFocus(event);
85
- setFocusInside(true);
86
- },
87
- ...rest
88
- }),
89
- ref: handleRef,
90
- children: [
91
- children,
92
- triggersSubmenu && /* @__PURE__ */ jsx(ExpandGroupIcon, { className: withBaseName("expandIcon"), "aria-hidden": true })
93
- ]
119
+ if (triggersSubmenu) {
120
+ setTriggerDisabled(!!disabled);
121
+ }
122
+ }, [disabled, setTriggerDisabled, triggersSubmenu]);
123
+ useEffect(() => {
124
+ if (process.env.NODE_ENV !== "production") {
125
+ if (insideSelectableGroup && value === void 0 && !missingValueWarningShown) {
126
+ missingValueWarningShown = true;
127
+ console.warn(
128
+ "Salt: MenuItem requires a `value` to be selectable inside a MenuGroup with `selectionVariant` set. It will behave as a regular menu item."
129
+ );
130
+ }
94
131
  }
132
+ }, [insideSelectableGroup, value]);
133
+ const shouldCloseMenu = () => !selectable || activationKeyRef.current === "Enter";
134
+ let role = "menuitem";
135
+ if (selectable) {
136
+ role = selectionVariant === "single" ? "menuitemradio" : "menuitemcheckbox";
137
+ }
138
+ return (
139
+ // biome-ignore lint/a11y/useAriaPropsSupportedByRole: Biome can't detect the role provided by the role variable. aria-checked is only used when the role is appropriate.
140
+ /* @__PURE__ */ jsxs(
141
+ "div",
142
+ {
143
+ className: clsx(
144
+ withBaseName(),
145
+ {
146
+ [withBaseName("blurActive")]: blurActive,
147
+ [withBaseName("selectionAlignedIcon")]: alignIconWithSelectionIcon
148
+ },
149
+ className
150
+ ),
151
+ role,
152
+ "aria-checked": selectable ? selected : void 0,
153
+ "aria-disabled": disabled || void 0,
154
+ ...getItemProps({
155
+ tabIndex: active ? 0 : -1,
156
+ onKeyDown(event) {
157
+ const element = event.currentTarget;
158
+ const { key } = event;
159
+ onKeyDown == null ? void 0 : onKeyDown(event);
160
+ if ((key === " " || key === "Enter") && !triggersSubmenu) {
161
+ event.preventDefault();
162
+ if (disabled || event.repeat) {
163
+ return;
164
+ }
165
+ const { view, ...eventInit } = event;
166
+ queueMicrotask(() => {
167
+ activationKeyRef.current = key;
168
+ element.dispatchEvent(
169
+ new window.MouseEvent("click", eventInit)
170
+ );
171
+ activationKeyRef.current = null;
172
+ });
173
+ }
174
+ },
175
+ onClick(event) {
176
+ if (!disabled) {
177
+ onClick == null ? void 0 : onClick(event);
178
+ if (selectable) {
179
+ select(event, value);
180
+ }
181
+ if (!triggersSubmenu && shouldCloseMenu()) {
182
+ tree == null ? void 0 : tree.events.emit("click");
183
+ }
184
+ }
185
+ },
186
+ onFocus(event) {
187
+ onFocus == null ? void 0 : onFocus(event);
188
+ setFocusInside(true);
189
+ },
190
+ ...rest
191
+ }),
192
+ ref: handleRef,
193
+ children: [
194
+ selectable && selectionVariant === "single" && /* @__PURE__ */ jsx(
195
+ RadioButtonIcon,
196
+ {
197
+ checked: selected,
198
+ className: withBaseName("selectionIcon")
199
+ }
200
+ ),
201
+ selectable && selectionVariant === "multiple" && /* @__PURE__ */ jsx(
202
+ CheckboxIcon,
203
+ {
204
+ checked: selected,
205
+ className: withBaseName("selectionIcon")
206
+ }
207
+ ),
208
+ reserveSelectionIconSpace && !selectable && /* @__PURE__ */ jsx(
209
+ "span",
210
+ {
211
+ "aria-hidden": true,
212
+ className: withBaseName("selectionIconPlaceholder")
213
+ }
214
+ ),
215
+ reserveIconSpace && !hasIcon && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: withBaseName("iconPlaceholder") }),
216
+ children,
217
+ triggersSubmenu && /* @__PURE__ */ jsx(ExpandGroupIcon, { className: withBaseName("expandIcon"), "aria-hidden": true })
218
+ ]
219
+ }
220
+ )
95
221
  );
96
222
  }
97
223
  );