@salt-ds/core 1.59.1 → 1.61.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 (233) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/css/salt-core.css +366 -1
  3. package/dist-cjs/aria-announcer/AriaAnnounce.js +15 -3
  4. package/dist-cjs/aria-announcer/AriaAnnounce.js.map +1 -1
  5. package/dist-cjs/aria-announcer/AriaAnnouncerContext.js.map +1 -1
  6. package/dist-cjs/aria-announcer/AriaAnnouncerProvider.js +65 -43
  7. package/dist-cjs/aria-announcer/AriaAnnouncerProvider.js.map +1 -1
  8. package/dist-cjs/aria-announcer/announcementRegistry.js +31 -0
  9. package/dist-cjs/aria-announcer/announcementRegistry.js.map +1 -0
  10. package/dist-cjs/aria-announcer/useAriaAnnouncer.js +44 -16
  11. package/dist-cjs/aria-announcer/useAriaAnnouncer.js.map +1 -1
  12. package/dist-cjs/index.js +17 -1
  13. package/dist-cjs/index.js.map +1 -1
  14. package/dist-cjs/navigation-item/NavigationItem.js +2 -0
  15. package/dist-cjs/navigation-item/NavigationItem.js.map +1 -1
  16. package/dist-cjs/pagination/Pagination.js +1 -0
  17. package/dist-cjs/pagination/Pagination.js.map +1 -1
  18. package/dist-cjs/rating/Rating.css.js +6 -0
  19. package/dist-cjs/rating/Rating.css.js.map +1 -0
  20. package/dist-cjs/rating/Rating.js +140 -0
  21. package/dist-cjs/rating/Rating.js.map +1 -0
  22. package/dist-cjs/rating/RatingItem.css.js +6 -0
  23. package/dist-cjs/rating/RatingItem.css.js.map +1 -0
  24. package/dist-cjs/rating/RatingItem.js +75 -0
  25. package/dist-cjs/rating/RatingItem.js.map +1 -0
  26. package/dist-cjs/salt-provider/SaltProvider.js +3 -1
  27. package/dist-cjs/salt-provider/SaltProvider.js.map +1 -1
  28. package/dist-cjs/semantic-icon-provider/SemanticIconProvider.js +22 -20
  29. package/dist-cjs/semantic-icon-provider/SemanticIconProvider.js.map +1 -1
  30. package/dist-cjs/spinner/Spinner.js +1 -0
  31. package/dist-cjs/spinner/Spinner.js.map +1 -1
  32. package/dist-cjs/tabs/Tab.css.js +6 -0
  33. package/dist-cjs/tabs/Tab.css.js.map +1 -0
  34. package/dist-cjs/tabs/Tab.js +211 -0
  35. package/dist-cjs/tabs/Tab.js.map +1 -0
  36. package/dist-cjs/tabs/TabAction.js +63 -0
  37. package/dist-cjs/tabs/TabAction.js.map +1 -0
  38. package/dist-cjs/tabs/TabBar.css.js +6 -0
  39. package/dist-cjs/tabs/TabBar.css.js.map +1 -0
  40. package/dist-cjs/tabs/TabBar.js +45 -0
  41. package/dist-cjs/tabs/TabBar.js.map +1 -0
  42. package/dist-cjs/tabs/TabList.css.js +6 -0
  43. package/dist-cjs/tabs/TabList.css.js.map +1 -0
  44. package/dist-cjs/tabs/TabList.js +281 -0
  45. package/dist-cjs/tabs/TabList.js.map +1 -0
  46. package/dist-cjs/tabs/TabPanel.css.js +6 -0
  47. package/dist-cjs/tabs/TabPanel.css.js.map +1 -0
  48. package/dist-cjs/tabs/TabPanel.js +98 -0
  49. package/dist-cjs/tabs/TabPanel.js.map +1 -0
  50. package/dist-cjs/tabs/TabTrigger.css.js +6 -0
  51. package/dist-cjs/tabs/TabTrigger.css.js.map +1 -0
  52. package/dist-cjs/tabs/TabTrigger.js +188 -0
  53. package/dist-cjs/tabs/TabTrigger.js.map +1 -0
  54. package/dist-cjs/tabs/Tabs.css.js +6 -0
  55. package/dist-cjs/tabs/Tabs.css.js.map +1 -0
  56. package/dist-cjs/tabs/Tabs.js +200 -0
  57. package/dist-cjs/tabs/Tabs.js.map +1 -0
  58. package/dist-cjs/tabs/internal/contexts/TabContext.js +26 -0
  59. package/dist-cjs/tabs/internal/contexts/TabContext.js.map +1 -0
  60. package/dist-cjs/tabs/internal/contexts/TabListLayoutContext.js +19 -0
  61. package/dist-cjs/tabs/internal/contexts/TabListLayoutContext.js.map +1 -0
  62. package/dist-cjs/tabs/internal/contexts/TabSlotRegistryContext.js +22 -0
  63. package/dist-cjs/tabs/internal/contexts/TabSlotRegistryContext.js.map +1 -0
  64. package/dist-cjs/tabs/internal/contexts/TabsContext.js +50 -0
  65. package/dist-cjs/tabs/internal/contexts/TabsContext.js.map +1 -0
  66. package/dist-cjs/tabs/internal/hooks/useFocusWithRetry.js +64 -0
  67. package/dist-cjs/tabs/internal/hooks/useFocusWithRetry.js.map +1 -0
  68. package/dist-cjs/tabs/internal/hooks/useTabListRecovery.js +76 -0
  69. package/dist-cjs/tabs/internal/hooks/useTabListRecovery.js.map +1 -0
  70. package/dist-cjs/tabs/internal/hooks/useTabRemovalHandler.js +165 -0
  71. package/dist-cjs/tabs/internal/hooks/useTabRemovalHandler.js.map +1 -0
  72. package/dist-cjs/tabs/internal/hooks/useTabSelectionFocus.js +87 -0
  73. package/dist-cjs/tabs/internal/hooks/useTabSelectionFocus.js.map +1 -0
  74. package/dist-cjs/tabs/internal/overflow/TabOverflowList.css.js +6 -0
  75. package/dist-cjs/tabs/internal/overflow/TabOverflowList.css.js.map +1 -0
  76. package/dist-cjs/tabs/internal/overflow/TabOverflowList.js +245 -0
  77. package/dist-cjs/tabs/internal/overflow/TabOverflowList.js.map +1 -0
  78. package/dist-cjs/tabs/internal/overflow/TabSlot.js +30 -0
  79. package/dist-cjs/tabs/internal/overflow/TabSlot.js.map +1 -0
  80. package/dist-cjs/tabs/internal/overflow/overflowMath.js +86 -0
  81. package/dist-cjs/tabs/internal/overflow/overflowMath.js.map +1 -0
  82. package/dist-cjs/tabs/internal/overflow/useOverflow.js +273 -0
  83. package/dist-cjs/tabs/internal/overflow/useOverflow.js.map +1 -0
  84. package/dist-cjs/tabs/internal/overflow/useOverflowLayoutState.js +99 -0
  85. package/dist-cjs/tabs/internal/overflow/useOverflowLayoutState.js.map +1 -0
  86. package/dist-cjs/tabs/internal/overflow/useOverflowSelectionState.js +68 -0
  87. package/dist-cjs/tabs/internal/overflow/useOverflowSelectionState.js.map +1 -0
  88. package/dist-cjs/tabs/internal/overflow/useRenderedTabWidth.js +92 -0
  89. package/dist-cjs/tabs/internal/overflow/useRenderedTabWidth.js.map +1 -0
  90. package/dist-cjs/tabs/internal/overflow/widthMeasurement.js +42 -0
  91. package/dist-cjs/tabs/internal/overflow/widthMeasurement.js.map +1 -0
  92. package/dist-cjs/tabs/internal/registry/useCollection.js +197 -0
  93. package/dist-cjs/tabs/internal/registry/useCollection.js.map +1 -0
  94. package/dist-cjs/tabs/internal/registry/useRenderedTabsRegistry.js +206 -0
  95. package/dist-cjs/tabs/internal/registry/useRenderedTabsRegistry.js.map +1 -0
  96. package/dist-cjs/tabs/internal/utils/domUtils.js +13 -0
  97. package/dist-cjs/tabs/internal/utils/domUtils.js.map +1 -0
  98. package/dist-cjs/tooltip/useAriaAnnounce.js +1 -0
  99. package/dist-cjs/tooltip/useAriaAnnounce.js.map +1 -1
  100. package/dist-es/aria-announcer/AriaAnnounce.js +15 -3
  101. package/dist-es/aria-announcer/AriaAnnounce.js.map +1 -1
  102. package/dist-es/aria-announcer/AriaAnnouncerContext.js.map +1 -1
  103. package/dist-es/aria-announcer/AriaAnnouncerProvider.js +67 -45
  104. package/dist-es/aria-announcer/AriaAnnouncerProvider.js.map +1 -1
  105. package/dist-es/aria-announcer/announcementRegistry.js +28 -0
  106. package/dist-es/aria-announcer/announcementRegistry.js.map +1 -0
  107. package/dist-es/aria-announcer/useAriaAnnouncer.js +45 -17
  108. package/dist-es/aria-announcer/useAriaAnnouncer.js.map +1 -1
  109. package/dist-es/index.js +9 -1
  110. package/dist-es/index.js.map +1 -1
  111. package/dist-es/navigation-item/NavigationItem.js +2 -0
  112. package/dist-es/navigation-item/NavigationItem.js.map +1 -1
  113. package/dist-es/pagination/Pagination.js +1 -0
  114. package/dist-es/pagination/Pagination.js.map +1 -1
  115. package/dist-es/rating/Rating.css.js +4 -0
  116. package/dist-es/rating/Rating.css.js.map +1 -0
  117. package/dist-es/rating/Rating.js +138 -0
  118. package/dist-es/rating/Rating.js.map +1 -0
  119. package/dist-es/rating/RatingItem.css.js +4 -0
  120. package/dist-es/rating/RatingItem.css.js.map +1 -0
  121. package/dist-es/rating/RatingItem.js +73 -0
  122. package/dist-es/rating/RatingItem.js.map +1 -0
  123. package/dist-es/salt-provider/SaltProvider.js +3 -1
  124. package/dist-es/salt-provider/SaltProvider.js.map +1 -1
  125. package/dist-es/semantic-icon-provider/SemanticIconProvider.js +23 -21
  126. package/dist-es/semantic-icon-provider/SemanticIconProvider.js.map +1 -1
  127. package/dist-es/spinner/Spinner.js +1 -0
  128. package/dist-es/spinner/Spinner.js.map +1 -1
  129. package/dist-es/tabs/Tab.css.js +4 -0
  130. package/dist-es/tabs/Tab.css.js.map +1 -0
  131. package/dist-es/tabs/Tab.js +209 -0
  132. package/dist-es/tabs/Tab.js.map +1 -0
  133. package/dist-es/tabs/TabAction.js +61 -0
  134. package/dist-es/tabs/TabAction.js.map +1 -0
  135. package/dist-es/tabs/TabBar.css.js +4 -0
  136. package/dist-es/tabs/TabBar.css.js.map +1 -0
  137. package/dist-es/tabs/TabBar.js +43 -0
  138. package/dist-es/tabs/TabBar.js.map +1 -0
  139. package/dist-es/tabs/TabList.css.js +4 -0
  140. package/dist-es/tabs/TabList.css.js.map +1 -0
  141. package/dist-es/tabs/TabList.js +279 -0
  142. package/dist-es/tabs/TabList.js.map +1 -0
  143. package/dist-es/tabs/TabPanel.css.js +4 -0
  144. package/dist-es/tabs/TabPanel.css.js.map +1 -0
  145. package/dist-es/tabs/TabPanel.js +96 -0
  146. package/dist-es/tabs/TabPanel.js.map +1 -0
  147. package/dist-es/tabs/TabTrigger.css.js +4 -0
  148. package/dist-es/tabs/TabTrigger.css.js.map +1 -0
  149. package/dist-es/tabs/TabTrigger.js +186 -0
  150. package/dist-es/tabs/TabTrigger.js.map +1 -0
  151. package/dist-es/tabs/Tabs.css.js +4 -0
  152. package/dist-es/tabs/Tabs.css.js.map +1 -0
  153. package/dist-es/tabs/Tabs.js +198 -0
  154. package/dist-es/tabs/Tabs.js.map +1 -0
  155. package/dist-es/tabs/internal/contexts/TabContext.js +23 -0
  156. package/dist-es/tabs/internal/contexts/TabContext.js.map +1 -0
  157. package/dist-es/tabs/internal/contexts/TabListLayoutContext.js +16 -0
  158. package/dist-es/tabs/internal/contexts/TabListLayoutContext.js.map +1 -0
  159. package/dist-es/tabs/internal/contexts/TabSlotRegistryContext.js +19 -0
  160. package/dist-es/tabs/internal/contexts/TabSlotRegistryContext.js.map +1 -0
  161. package/dist-es/tabs/internal/contexts/TabsContext.js +47 -0
  162. package/dist-es/tabs/internal/contexts/TabsContext.js.map +1 -0
  163. package/dist-es/tabs/internal/hooks/useFocusWithRetry.js +62 -0
  164. package/dist-es/tabs/internal/hooks/useFocusWithRetry.js.map +1 -0
  165. package/dist-es/tabs/internal/hooks/useTabListRecovery.js +74 -0
  166. package/dist-es/tabs/internal/hooks/useTabListRecovery.js.map +1 -0
  167. package/dist-es/tabs/internal/hooks/useTabRemovalHandler.js +163 -0
  168. package/dist-es/tabs/internal/hooks/useTabRemovalHandler.js.map +1 -0
  169. package/dist-es/tabs/internal/hooks/useTabSelectionFocus.js +85 -0
  170. package/dist-es/tabs/internal/hooks/useTabSelectionFocus.js.map +1 -0
  171. package/dist-es/tabs/internal/overflow/TabOverflowList.css.js +4 -0
  172. package/dist-es/tabs/internal/overflow/TabOverflowList.css.js.map +1 -0
  173. package/dist-es/tabs/internal/overflow/TabOverflowList.js +243 -0
  174. package/dist-es/tabs/internal/overflow/TabOverflowList.js.map +1 -0
  175. package/dist-es/tabs/internal/overflow/TabSlot.js +28 -0
  176. package/dist-es/tabs/internal/overflow/TabSlot.js.map +1 -0
  177. package/dist-es/tabs/internal/overflow/overflowMath.js +82 -0
  178. package/dist-es/tabs/internal/overflow/overflowMath.js.map +1 -0
  179. package/dist-es/tabs/internal/overflow/useOverflow.js +271 -0
  180. package/dist-es/tabs/internal/overflow/useOverflow.js.map +1 -0
  181. package/dist-es/tabs/internal/overflow/useOverflowLayoutState.js +97 -0
  182. package/dist-es/tabs/internal/overflow/useOverflowLayoutState.js.map +1 -0
  183. package/dist-es/tabs/internal/overflow/useOverflowSelectionState.js +66 -0
  184. package/dist-es/tabs/internal/overflow/useOverflowSelectionState.js.map +1 -0
  185. package/dist-es/tabs/internal/overflow/useRenderedTabWidth.js +90 -0
  186. package/dist-es/tabs/internal/overflow/useRenderedTabWidth.js.map +1 -0
  187. package/dist-es/tabs/internal/overflow/widthMeasurement.js +36 -0
  188. package/dist-es/tabs/internal/overflow/widthMeasurement.js.map +1 -0
  189. package/dist-es/tabs/internal/registry/useCollection.js +195 -0
  190. package/dist-es/tabs/internal/registry/useCollection.js.map +1 -0
  191. package/dist-es/tabs/internal/registry/useRenderedTabsRegistry.js +204 -0
  192. package/dist-es/tabs/internal/registry/useRenderedTabsRegistry.js.map +1 -0
  193. package/dist-es/tabs/internal/utils/domUtils.js +11 -0
  194. package/dist-es/tabs/internal/utils/domUtils.js.map +1 -0
  195. package/dist-es/tooltip/useAriaAnnounce.js +1 -0
  196. package/dist-es/tooltip/useAriaAnnounce.js.map +1 -1
  197. package/dist-types/aria-announcer/AriaAnnounce.d.ts +9 -2
  198. package/dist-types/aria-announcer/AriaAnnouncerContext.d.ts +26 -2
  199. package/dist-types/aria-announcer/AriaAnnouncerProvider.d.ts +6 -7
  200. package/dist-types/aria-announcer/announcementRegistry.d.ts +5 -0
  201. package/dist-types/index.d.ts +2 -0
  202. package/dist-types/rating/Rating.d.ts +48 -0
  203. package/dist-types/rating/RatingItem.d.ts +47 -0
  204. package/dist-types/rating/index.d.ts +1 -0
  205. package/dist-types/semantic-icon-provider/SemanticIconProvider.d.ts +21 -19
  206. package/dist-types/tabs/Tab.d.ts +12 -0
  207. package/dist-types/tabs/TabAction.d.ts +4 -0
  208. package/dist-types/tabs/TabBar.d.ts +12 -0
  209. package/dist-types/tabs/TabList.d.ts +12 -0
  210. package/dist-types/tabs/TabPanel.d.ts +9 -0
  211. package/dist-types/tabs/TabTrigger.d.ts +4 -0
  212. package/dist-types/tabs/Tabs.d.ts +20 -0
  213. package/dist-types/tabs/index.d.ts +7 -0
  214. package/dist-types/tabs/internal/contexts/TabContext.d.ts +12 -0
  215. package/dist-types/tabs/internal/contexts/TabListLayoutContext.d.ts +9 -0
  216. package/dist-types/tabs/internal/contexts/TabSlotRegistryContext.d.ts +5 -0
  217. package/dist-types/tabs/internal/contexts/TabsContext.d.ts +43 -0
  218. package/dist-types/tabs/internal/hooks/useFocusWithRetry.d.ts +9 -0
  219. package/dist-types/tabs/internal/hooks/useTabListRecovery.d.ts +12 -0
  220. package/dist-types/tabs/internal/hooks/useTabRemovalHandler.d.ts +32 -0
  221. package/dist-types/tabs/internal/hooks/useTabSelectionFocus.d.ts +15 -0
  222. package/dist-types/tabs/internal/overflow/TabOverflowList.d.ts +10 -0
  223. package/dist-types/tabs/internal/overflow/TabSlot.d.ts +6 -0
  224. package/dist-types/tabs/internal/overflow/overflowMath.d.ts +18 -0
  225. package/dist-types/tabs/internal/overflow/useOverflow.d.ts +11 -0
  226. package/dist-types/tabs/internal/overflow/useOverflowLayoutState.d.ts +13 -0
  227. package/dist-types/tabs/internal/overflow/useOverflowSelectionState.d.ts +13 -0
  228. package/dist-types/tabs/internal/overflow/useRenderedTabWidth.d.ts +12 -0
  229. package/dist-types/tabs/internal/overflow/widthMeasurement.d.ts +5 -0
  230. package/dist-types/tabs/internal/registry/useCollection.d.ts +30 -0
  231. package/dist-types/tabs/internal/registry/useRenderedTabsRegistry.d.ts +12 -0
  232. package/dist-types/tabs/internal/utils/domUtils.d.ts +1 -0
  233. package/package.json +3 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabList.js","sources":["../src/tabs/TabList.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 KeyboardEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAriaAnnouncer } from \"../aria-announcer\";\nimport {\n capitalize,\n makePrefixer,\n useForkRef,\n useIsomorphicLayoutEffect,\n} from \"../utils\";\nimport { TabListLayoutContext } from \"./internal/contexts/TabListLayoutContext\";\nimport { TabSlotRegistryContext } from \"./internal/contexts/TabSlotRegistryContext\";\nimport { useTabs } from \"./internal/contexts/TabsContext\";\nimport { useFocusWithRetry } from \"./internal/hooks/useFocusWithRetry\";\nimport { useTabListRecovery } from \"./internal/hooks/useTabListRecovery\";\nimport { useTabRemovalHandler } from \"./internal/hooks/useTabRemovalHandler\";\nimport { useTabSelectionFocus } from \"./internal/hooks/useTabSelectionFocus\";\nimport { TabOverflowList } from \"./internal/overflow/TabOverflowList\";\nimport { TabSlot } from \"./internal/overflow/TabSlot\";\nimport { useOverflow } from \"./internal/overflow/useOverflow\";\nimport { useOverflowLayoutState } from \"./internal/overflow/useOverflowLayoutState\";\nimport tabListCss from \"./TabList.css\";\n\nconst withBaseName = makePrefixer(\"saltTabList\");\nconst MAX_FOCUS_RETRY_ATTEMPTS = 120;\n\nexport interface TabListProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /**\n * Styling active color variant. Defaults to \"primary\".\n */\n activeColor?: \"primary\" | \"secondary\" | \"tertiary\";\n /**\n * The appearance of the tabs. Defaults to \"bordered\".\n */\n appearance?: \"bordered\" | \"transparent\";\n}\n\nexport const TabList = forwardRef<HTMLDivElement, TabListProps>(\n function TabList(props, ref) {\n const {\n appearance = \"bordered\",\n activeColor = \"primary\",\n children,\n className,\n onKeyDown,\n ...rest\n } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tab-list\",\n css: tabListCss,\n window: targetWindow,\n });\n\n const {\n renderMode,\n selected,\n setSelected,\n setBootstrapOverflowReady,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n getIndex,\n item,\n itemAt,\n activeTab,\n selectionFromOverflowValueRef,\n menuOpen,\n setMenuOpen,\n sortItems,\n getRemovedItems,\n getRenderedTab,\n renderedTabs,\n removalVersion,\n } = useTabs();\n\n const tabstripRef = useRef<HTMLDivElement>(null);\n const overflowListRef = useRef<HTMLDivElement>(null);\n const slotMapRef = useRef<Map<string, HTMLDivElement>>(new Map());\n const removalRecoveryRafRef = useRef<number | null>(null);\n const pendingRemovalRecoveryRef = useRef(false);\n const pendingRemovalRecoveryRetriesRef = useRef(0);\n const [slotVersion, setSlotVersion] = useState(0);\n\n const handleRef = useForkRef(tabstripRef, ref);\n const overflowButtonRef = useRef<HTMLButtonElement>(null);\n\n const { announce } = useAriaAnnouncer();\n const overflowMenuOpen = renderMode === \"portal\" ? menuOpen : false;\n\n const [visibleValues, hiddenValues, isMeasuring] = useOverflow({\n container: tabstripRef,\n menuOpen: overflowMenuOpen,\n selected,\n tabs: renderedTabs,\n overflowButton: overflowButtonRef,\n });\n\n useEffect(() => {\n setBootstrapOverflowReady(\n renderMode === \"inline\" && renderedTabs.length > 0 && !isMeasuring,\n );\n }, [\n isMeasuring,\n renderMode,\n renderedTabs.length,\n setBootstrapOverflowReady,\n ]);\n\n const { resolvedOverflowActiveValue, tabListLayoutContext } =\n useOverflowLayoutState({\n hiddenValues,\n menuOpen,\n overflowMenuOpen,\n visibleValues,\n });\n const registerSlot = useCallback(\n (slotId: string, element: HTMLDivElement | null) => {\n const currentElement = slotMapRef.current.get(slotId) ?? null;\n if (currentElement === element) {\n return;\n }\n\n if (element) {\n slotMapRef.current.set(slotId, element);\n } else {\n slotMapRef.current.delete(slotId);\n }\n\n setSlotVersion((currentVersion) => currentVersion + 1);\n },\n [],\n );\n const slotRegistryContext = useMemo(\n () => ({ registerSlot }),\n [registerSlot],\n );\n const slotAssignments = useMemo(() => {\n const nextAssignments = new Map<string, string>();\n\n for (const value of visibleValues) {\n nextAssignments.set(value, `main:${value}`);\n }\n\n for (const value of hiddenValues) {\n nextAssignments.set(\n value,\n menuOpen ? `overflow:${value}` : `measure:${value}`,\n );\n }\n\n return {\n map: nextAssignments,\n version: slotVersion,\n };\n }, [hiddenValues, menuOpen, slotVersion, visibleValues]);\n\n useIsomorphicLayoutEffect(() => {\n if (renderMode !== \"portal\") {\n return;\n }\n\n for (const [value, slotId] of slotAssignments.map) {\n const host = getRenderedTab(value)?.host;\n const slot = slotMapRef.current.get(slotId);\n\n if (host && slot && host.parentElement !== slot) {\n slot.appendChild(host);\n }\n }\n }, [getRenderedTab, renderMode, slotAssignments]);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n if (menuOpen) return;\n\n const actionMap = {\n ArrowRight: getNext,\n ArrowLeft: getPrevious,\n Home: getFirst,\n End: getLast,\n };\n\n const action = actionMap[event.key as keyof typeof actionMap];\n\n if (action) {\n event.preventDefault();\n // Item registration/sorting is raf-driven; flush before keyboard nav to\n // avoid navigating against stale collection order/registration.\n sortItems();\n const activeTabId = activeTab.current?.id;\n if (!activeTabId) return;\n const nextItem = action(activeTabId);\n if (nextItem) {\n // Scrolling is handled by TabTrigger.\n nextItem.element?.focus({ preventScroll: true });\n }\n }\n };\n\n const getSelectedTabElement = useCallback(() => {\n return (\n tabstripRef.current?.querySelector<HTMLElement>(\n '[role=\"tab\"][aria-selected=\"true\"]',\n ) ?? item(activeTab.current?.id)?.element\n );\n }, [item, activeTab]);\n const { focusElementWithRetry } = useFocusWithRetry({\n maxAttempts: MAX_FOCUS_RETRY_ATTEMPTS,\n targetWindow,\n });\n useTabSelectionFocus({\n announce,\n focusElementWithRetry,\n getRenderedTab,\n getSelectedTabElement,\n menuOpen,\n resolvedOverflowActiveValue,\n selected,\n selectionFromOverflowValueRef,\n targetWindow,\n });\n\n const handleTabRemoval = useTabRemovalHandler({\n activeTab,\n focusElementWithRetry,\n getFirst,\n getIndex,\n getLast,\n getRemovedItems,\n getRenderedTab,\n getSelectedTabElement,\n item,\n itemAt,\n maxRetryAttempts: MAX_FOCUS_RETRY_ATTEMPTS,\n menuOpen,\n overflowButtonRef,\n overflowListRef,\n pendingRemovalRecoveryRef,\n pendingRemovalRecoveryRetriesRef,\n removalRecoveryRafRef,\n selected,\n setSelected,\n tabstripRef,\n targetWindow,\n });\n\n useTabListRecovery({\n removalVersion,\n targetWindow,\n tabstripRef,\n overflowListRef,\n handleTabRemoval,\n pendingRemovalRecoveryRef,\n pendingRemovalRecoveryRetriesRef,\n });\n\n return (\n <div\n role=\"tablist\"\n className={clsx(\n withBaseName(),\n withBaseName(appearance),\n withBaseName(\"horizontal\"),\n withBaseName(`activeColor${capitalize(activeColor)}`),\n className,\n )}\n data-ismeasuring={\n renderMode === \"portal\" && isMeasuring ? true : undefined\n }\n ref={handleRef}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {renderMode === \"inline\" ? (\n children\n ) : (\n <TabSlotRegistryContext.Provider value={slotRegistryContext}>\n <TabListLayoutContext.Provider value={tabListLayoutContext}>\n {children}\n {visibleValues.map((value) => (\n <TabSlot key={value} slotId={`main:${value}`} value={value} />\n ))}\n {!menuOpen && hiddenValues.length > 0 ? (\n <div\n aria-hidden=\"true\"\n role=\"presentation\"\n className={withBaseName(\"measureContainer\")}\n >\n {hiddenValues.map((value) => (\n <TabSlot\n key={`measure-${value}`}\n slotId={`measure:${value}`}\n value={value}\n />\n ))}\n </div>\n ) : null}\n <TabOverflowList\n buttonRef={overflowButtonRef}\n hiddenValues={hiddenValues}\n open={menuOpen}\n order={renderedTabs.length}\n setOpen={setMenuOpen}\n ref={overflowListRef}\n />\n </TabListLayoutContext.Provider>\n </TabSlotRegistryContext.Provider>\n )}\n </div>\n );\n },\n);\n"],"names":["TabList","tabListCss"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ var css_248z = ".saltTabPanel {\n height: 100%;\n width: 100%;\n}\n\n.saltTabPanel[hidden] {\n display: none;\n}\n\n.saltTabPanel:focus-visible {\n outline: var(--salt-focused-outline);\n}\n";
2
+
3
+ export { css_248z as default };
4
+ //# sourceMappingURL=TabPanel.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabPanel.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,96 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useComponentCssInjection } from '@salt-ds/styles';
3
+ import { useWindow } from '@salt-ds/window';
4
+ import { clsx } from 'clsx';
5
+ import { forwardRef, useRef, useState, useEffect } from 'react';
6
+ import { tabbable } from 'tabbable';
7
+ import { makePrefixer } from '../utils/makePrefixer.js';
8
+ import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect.js';
9
+ import '../utils/useFloatingUI/useFloatingUI.js';
10
+ import { useForkRef } from '../utils/useForkRef.js';
11
+ import { useId } from '../utils/useId.js';
12
+ import '../salt-provider/SaltProvider.js';
13
+ import '../viewport/ViewportProvider.js';
14
+ import { useTabs } from './internal/contexts/TabsContext.js';
15
+ import css_248z from './TabPanel.css.js';
16
+
17
+ const withBaseName = makePrefixer("saltTabPanel");
18
+ const TabPanel = forwardRef(
19
+ function TabPanel2(props, ref) {
20
+ const { className, children, id: idProp, value, ...rest } = props;
21
+ const targetWindow = useWindow();
22
+ useComponentCssInjection({
23
+ testId: "salt-tab-panel",
24
+ css: css_248z,
25
+ window: targetWindow
26
+ });
27
+ const id = useId(idProp);
28
+ const { registerPanel, getTabId, selected } = useTabs();
29
+ const hidden = selected !== value;
30
+ const panelRef = useRef(null);
31
+ const handleRef = useForkRef(panelRef, ref);
32
+ useIsomorphicLayoutEffect(() => {
33
+ if (id) {
34
+ return registerPanel(id, value);
35
+ }
36
+ }, [value, id, registerPanel]);
37
+ const [hasFocusableChildren, setHasFocusableChildren] = useState(false);
38
+ useEffect(() => {
39
+ const element = panelRef.current;
40
+ const mutationObserverCtor = targetWindow == null ? void 0 : targetWindow.MutationObserver;
41
+ if (!element || hidden) return;
42
+ let rafId = null;
43
+ const detectFocusableChildren = () => {
44
+ rafId = null;
45
+ const elements = tabbable(element);
46
+ const nextHasFocusableChildren = elements.length > 0;
47
+ setHasFocusableChildren((prev) => {
48
+ return prev === nextHasFocusableChildren ? prev : nextHasFocusableChildren;
49
+ });
50
+ };
51
+ const scheduleDetectFocusableChildren = () => {
52
+ if (rafId != null && targetWindow) {
53
+ targetWindow.cancelAnimationFrame(rafId);
54
+ }
55
+ if (!(targetWindow == null ? void 0 : targetWindow.requestAnimationFrame)) {
56
+ detectFocusableChildren();
57
+ return;
58
+ }
59
+ rafId = targetWindow.requestAnimationFrame(detectFocusableChildren);
60
+ };
61
+ const observer = mutationObserverCtor ? new mutationObserverCtor(() => {
62
+ scheduleDetectFocusableChildren();
63
+ }) : null;
64
+ scheduleDetectFocusableChildren();
65
+ observer == null ? void 0 : observer.observe(element, {
66
+ childList: true,
67
+ subtree: true,
68
+ attributes: true
69
+ });
70
+ return () => {
71
+ observer == null ? void 0 : observer.disconnect();
72
+ if (rafId != null && targetWindow) {
73
+ targetWindow.cancelAnimationFrame(rafId);
74
+ }
75
+ };
76
+ }, [hidden, targetWindow]);
77
+ const tabId = getTabId(value);
78
+ return /* @__PURE__ */ jsx(
79
+ "div",
80
+ {
81
+ id,
82
+ ref: handleRef,
83
+ role: "tabpanel",
84
+ "aria-labelledby": tabId,
85
+ className: clsx(withBaseName(), className),
86
+ hidden: hidden || void 0,
87
+ tabIndex: hidden || hasFocusableChildren ? void 0 : 0,
88
+ ...rest,
89
+ children
90
+ }
91
+ );
92
+ }
93
+ );
94
+
95
+ export { TabPanel };
96
+ //# sourceMappingURL=TabPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabPanel.js","sources":["../src/tabs/TabPanel.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 useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { tabbable } from \"tabbable\";\nimport {\n makePrefixer,\n useForkRef,\n useId,\n useIsomorphicLayoutEffect,\n} from \"../utils\";\nimport { useTabs } from \"./internal/contexts/TabsContext\";\nimport tabPanelCss from \"./TabPanel.css\";\n\nexport interface TabPanelProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The value of the panel. This should map to the corresponding tab and must\n * be unique within a `Tabs` instance.\n */\n value: string;\n}\n\nconst withBaseName = makePrefixer(\"saltTabPanel\");\n\nexport const TabPanel = forwardRef<HTMLDivElement, TabPanelProps>(\n function TabPanel(props, ref) {\n const { className, children, id: idProp, value, ...rest } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tab-panel\",\n css: tabPanelCss,\n window: targetWindow,\n });\n const id = useId(idProp);\n const { registerPanel, getTabId, selected } = useTabs();\n const hidden = selected !== value;\n\n const panelRef = useRef<HTMLDivElement>(null);\n const handleRef = useForkRef(panelRef, ref);\n\n useIsomorphicLayoutEffect(() => {\n if (id) {\n return registerPanel(id, value);\n }\n }, [value, id, registerPanel]);\n\n const [hasFocusableChildren, setHasFocusableChildren] = useState(false);\n useEffect(() => {\n const element = panelRef.current;\n const mutationObserverCtor = (\n targetWindow as\n | (Window & { MutationObserver?: typeof MutationObserver })\n | undefined\n )?.MutationObserver;\n if (!element || hidden) return;\n\n let rafId: number | null = null;\n\n const detectFocusableChildren = () => {\n rafId = null;\n const elements = tabbable(element);\n const nextHasFocusableChildren = elements.length > 0;\n setHasFocusableChildren((prev) => {\n return prev === nextHasFocusableChildren\n ? prev\n : nextHasFocusableChildren;\n });\n };\n\n const scheduleDetectFocusableChildren = () => {\n if (rafId != null && targetWindow) {\n targetWindow.cancelAnimationFrame(rafId);\n }\n\n if (!targetWindow?.requestAnimationFrame) {\n detectFocusableChildren();\n return;\n }\n\n rafId = targetWindow.requestAnimationFrame(detectFocusableChildren);\n };\n\n const observer = mutationObserverCtor\n ? new mutationObserverCtor(() => {\n scheduleDetectFocusableChildren();\n })\n : null;\n\n scheduleDetectFocusableChildren();\n\n observer?.observe(element, {\n childList: true,\n subtree: true,\n attributes: true,\n });\n\n return () => {\n observer?.disconnect();\n if (rafId != null && targetWindow) {\n targetWindow.cancelAnimationFrame(rafId);\n }\n };\n }, [hidden, targetWindow]);\n\n const tabId = getTabId(value);\n\n return (\n <div\n id={id}\n ref={handleRef}\n role=\"tabpanel\"\n aria-labelledby={tabId}\n className={clsx(withBaseName(), className)}\n hidden={hidden || undefined}\n tabIndex={hidden || hasFocusableChildren ? undefined : 0}\n {...rest}\n >\n {children}\n </div>\n );\n },\n);\n"],"names":["TabPanel","tabPanelCss"],"mappings":";;;;;;;;;;;;;;;;AA4BA,MAAM,YAAA,GAAe,aAAa,cAAc,CAAA;AAEzC,MAAM,QAAA,GAAW,UAAA;AAAA,EACtB,SAASA,SAAAA,CAAS,KAAA,EAAO,GAAA,EAAK;AAC5B,IAAA,MAAM,EAAE,WAAW,QAAA,EAAU,EAAA,EAAI,QAAQ,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AAC5D,IAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,gBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,MAAM,EAAA,GAAK,MAAM,MAAM,CAAA;AACvB,IAAA,MAAM,EAAE,aAAA,EAAe,QAAA,EAAU,QAAA,KAAa,OAAA,EAAQ;AACtD,IAAA,MAAM,SAAS,QAAA,KAAa,KAAA;AAE5B,IAAA,MAAM,QAAA,GAAW,OAAuB,IAAI,CAAA;AAC5C,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,QAAA,EAAU,GAAG,CAAA;AAE1C,IAAA,yBAAA,CAA0B,MAAM;AAC9B,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,OAAO,aAAA,CAAc,IAAI,KAAK,CAAA;AAAA,MAChC;AAAA,IACF,CAAA,EAAG,CAAC,KAAA,EAAO,EAAA,EAAI,aAAa,CAAC,CAAA;AAE7B,IAAA,MAAM,CAAC,oBAAA,EAAsB,uBAAuB,CAAA,GAAI,SAAS,KAAK,CAAA;AACtE,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AACzB,MAAA,MAAM,uBACJ,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAGC,gBAAA;AACH,MAAA,IAAI,CAAC,WAAW,MAAA,EAAQ;AAExB,MAAA,IAAI,KAAA,GAAuB,IAAA;AAE3B,MAAA,MAAM,0BAA0B,MAAM;AACpC,QAAA,KAAA,GAAQ,IAAA;AACR,QAAA,MAAM,QAAA,GAAW,SAAS,OAAO,CAAA;AACjC,QAAA,MAAM,wBAAA,GAA2B,SAAS,MAAA,GAAS,CAAA;AACnD,QAAA,uBAAA,CAAwB,CAAC,IAAA,KAAS;AAChC,UAAA,OAAO,IAAA,KAAS,2BACZ,IAAA,GACA,wBAAA;AAAA,QACN,CAAC,CAAA;AAAA,MACH,CAAA;AAEA,MAAA,MAAM,kCAAkC,MAAM;AAC5C,QAAA,IAAI,KAAA,IAAS,QAAQ,YAAA,EAAc;AACjC,UAAA,YAAA,CAAa,qBAAqB,KAAK,CAAA;AAAA,QACzC;AAEA,QAAA,IAAI,EAAC,6CAAc,qBAAA,CAAA,EAAuB;AACxC,UAAA,uBAAA,EAAwB;AACxB,UAAA;AAAA,QACF;AAEA,QAAA,KAAA,GAAQ,YAAA,CAAa,sBAAsB,uBAAuB,CAAA;AAAA,MACpE,CAAA;AAEA,MAAA,MAAM,QAAA,GAAW,oBAAA,GACb,IAAI,oBAAA,CAAqB,MAAM;AAC7B,QAAA,+BAAA,EAAgC;AAAA,MAClC,CAAC,CAAA,GACD,IAAA;AAEJ,MAAA,+BAAA,EAAgC;AAEhC,MAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,QAAQ,OAAA,EAAS;AAAA,QACzB,SAAA,EAAW,IAAA;AAAA,QACX,OAAA,EAAS,IAAA;AAAA,QACT,UAAA,EAAY;AAAA,OACd,CAAA;AAEA,MAAA,OAAO,MAAM;AACX,QAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,UAAA,EAAA;AACV,QAAA,IAAI,KAAA,IAAS,QAAQ,YAAA,EAAc;AACjC,UAAA,YAAA,CAAa,qBAAqB,KAAK,CAAA;AAAA,QACzC;AAAA,MACF,CAAA;AAAA,IACF,CAAA,EAAG,CAAC,MAAA,EAAQ,YAAY,CAAC,CAAA;AAEzB,IAAA,MAAM,KAAA,GAAQ,SAAS,KAAK,CAAA;AAE5B,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,EAAA;AAAA,QACA,GAAA,EAAK,SAAA;AAAA,QACL,IAAA,EAAK,UAAA;AAAA,QACL,iBAAA,EAAiB,KAAA;AAAA,QACjB,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACzC,QAAQ,MAAA,IAAU,MAAA;AAAA,QAClB,QAAA,EAAU,MAAA,IAAU,oBAAA,GAAuB,MAAA,GAAY,CAAA;AAAA,QACtD,GAAG,IAAA;AAAA,QAEH;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;;;;"}
@@ -0,0 +1,4 @@
1
+ var css_248z = ".saltTabTrigger {\n all: unset;\n display: flex;\n gap: var(--salt-spacing-100);\n align-items: center;\n justify-content: center;\n flex: 1;\n overflow: hidden;\n}\n\n/* The action should be triggered by clicking anywhere on the tab. */\n.saltTabTrigger::before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n}\n\n.saltTabTrigger:focus-visible {\n outline: none;\n}\n";
2
+
3
+ export { css_248z as default };
4
+ //# sourceMappingURL=TabTrigger.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabTrigger.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,186 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useComponentCssInjection } from '@salt-ds/styles';
3
+ import { useWindow } from '@salt-ds/window';
4
+ import { clsx } from 'clsx';
5
+ import { forwardRef, useRef } from 'react';
6
+ import { makePrefixer } from '../utils/makePrefixer.js';
7
+ import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect.js';
8
+ import '../utils/useFloatingUI/useFloatingUI.js';
9
+ import { useForkRef } from '../utils/useForkRef.js';
10
+ import '../utils/useId.js';
11
+ import '../salt-provider/SaltProvider.js';
12
+ import '../viewport/ViewportProvider.js';
13
+ import { useTab } from './internal/contexts/TabContext.js';
14
+ import { useTabListLayout } from './internal/contexts/TabListLayoutContext.js';
15
+ import { useTabs } from './internal/contexts/TabsContext.js';
16
+ import css_248z from './TabTrigger.css.js';
17
+
18
+ const withBaseName = makePrefixer("saltTabTrigger");
19
+ function getAriaDescription(count) {
20
+ if (count < 1) {
21
+ return void 0;
22
+ }
23
+ if (count === 1) {
24
+ return "1 action available";
25
+ }
26
+ return `${count} actions available`;
27
+ }
28
+ const ariaActionSupported = typeof HTMLElement !== "undefined" && "ariaActions" in HTMLElement.prototype;
29
+ const TabTrigger = forwardRef(
30
+ function TabTrigger2(props, ref) {
31
+ const { children, className, onClick, onKeyDown, onFocus, ...rest } = props;
32
+ const targetWindow = useWindow();
33
+ useComponentCssInjection({
34
+ testId: "salt-tab-trigger",
35
+ css: css_248z,
36
+ window: targetWindow
37
+ });
38
+ const {
39
+ setSelected,
40
+ registerTab,
41
+ updateTab,
42
+ updateRenderedTab,
43
+ getRenderedTabOrder,
44
+ getPanelId,
45
+ getTabId,
46
+ selected: selectedValue,
47
+ activeTab,
48
+ menuOpen,
49
+ setMenuOpen
50
+ } = useTabs();
51
+ const { selected, value, focused, disabled, tabId, actions } = useTab();
52
+ const tabListLayout = useTabListLayout();
53
+ const tabRef = useRef(null);
54
+ const location = (tabListLayout == null ? void 0 : tabListLayout.getLocation(value)) ?? "main";
55
+ const selectionSource = location === "overflow" ? "overflow" : "main";
56
+ const hidden = location === "hidden";
57
+ const overflowOpen = location === "overflow" && menuOpen;
58
+ const renderOrder = getRenderedTabOrder(value);
59
+ const order = renderOrder >= 0 ? renderOrder : void 0;
60
+ const initialLocationRef = useRef(location);
61
+ const initialOrderRef = useRef(order);
62
+ const id = tabId;
63
+ useIsomorphicLayoutEffect(() => {
64
+ if (id && tabRef.current) {
65
+ const item = {
66
+ id,
67
+ value,
68
+ element: tabRef.current,
69
+ location: initialLocationRef.current,
70
+ order: initialOrderRef.current
71
+ };
72
+ return registerTab(item);
73
+ }
74
+ }, [id, registerTab, value]);
75
+ useIsomorphicLayoutEffect(() => {
76
+ if (!id) {
77
+ return;
78
+ }
79
+ updateTab(id, {
80
+ element: tabRef.current,
81
+ location,
82
+ order
83
+ });
84
+ }, [id, location, order, updateTab]);
85
+ useIsomorphicLayoutEffect(() => {
86
+ updateRenderedTab(value, {
87
+ trigger: tabRef.current
88
+ });
89
+ }, [updateRenderedTab, value]);
90
+ useIsomorphicLayoutEffect(() => {
91
+ var _a;
92
+ if (!overflowOpen || (tabListLayout == null ? void 0 : tabListLayout.overflowActiveValue) !== value) {
93
+ return;
94
+ }
95
+ (_a = tabRef.current) == null ? void 0 : _a.focus({ preventScroll: true });
96
+ }, [overflowOpen, tabListLayout == null ? void 0 : tabListLayout.overflowActiveValue, value]);
97
+ const handleClick = (event) => {
98
+ onClick == null ? void 0 : onClick(event);
99
+ setSelected(event, value, selectionSource);
100
+ };
101
+ const handleKeyDown = (event) => {
102
+ onKeyDown == null ? void 0 : onKeyDown(event);
103
+ if (location === "overflow" && event.key === "Tab" && event.shiftKey) {
104
+ event.preventDefault();
105
+ setMenuOpen(false);
106
+ const doc = event.currentTarget.ownerDocument;
107
+ const overflowTrigger = doc.querySelector(
108
+ "[data-overflowbutton]"
109
+ );
110
+ const scheduleFocus = targetWindow == null ? void 0 : targetWindow.requestAnimationFrame;
111
+ if (scheduleFocus) {
112
+ scheduleFocus(() => overflowTrigger == null ? void 0 : overflowTrigger.focus({ preventScroll: true }));
113
+ } else {
114
+ queueMicrotask(() => overflowTrigger == null ? void 0 : overflowTrigger.focus({ preventScroll: true }));
115
+ }
116
+ return;
117
+ }
118
+ if (location === "overflow" && tabListLayout && (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Home" || event.key === "End")) {
119
+ const moved = tabListLayout.moveOverflowFocus(event.key, value);
120
+ if (moved) {
121
+ event.preventDefault();
122
+ return;
123
+ }
124
+ }
125
+ if (disabled) {
126
+ if (event.key === "Enter" || event.key === " ") {
127
+ event.preventDefault();
128
+ }
129
+ return;
130
+ }
131
+ if (event.key === "Enter" || event.key === " ") {
132
+ event.preventDefault();
133
+ setSelected(event, value, selectionSource);
134
+ }
135
+ };
136
+ const handleFocus = (event) => {
137
+ var _a;
138
+ onFocus == null ? void 0 : onFocus(event);
139
+ if (id) {
140
+ activeTab.current = { value, id };
141
+ }
142
+ if (location === "overflow") {
143
+ tabListLayout == null ? void 0 : tabListLayout.setOverflowActiveValue(value);
144
+ }
145
+ (_a = event.currentTarget.parentElement) == null ? void 0 : _a.scrollIntoView({
146
+ block: "nearest",
147
+ inline: "nearest"
148
+ });
149
+ };
150
+ const handleRef = useForkRef(tabRef, ref);
151
+ const panelId = getPanelId(value);
152
+ const ariaActionsProps = ariaActionSupported ? {
153
+ "aria-actions": clsx(actions) || void 0
154
+ } : {};
155
+ const active = location === "overflow" && (tabListLayout == null ? void 0 : tabListLayout.overflowActiveValue) === value;
156
+ const hasSelectedTab = selectedValue !== void 0 && getTabId(selectedValue) != null;
157
+ const fallbackTabStop = !hasSelectedTab && location === "main" && order === 0;
158
+ const isTabStop = !hidden && (focused || selected || active || fallbackTabStop);
159
+ const shouldHandleKeyDown = location === "overflow" || !disabled;
160
+ return /* @__PURE__ */ jsx(
161
+ "button",
162
+ {
163
+ "aria-selected": selected,
164
+ "aria-disabled": disabled,
165
+ "aria-controls": panelId,
166
+ ...ariaActionsProps,
167
+ "aria-description": getAriaDescription(actions.length),
168
+ tabIndex: isTabStop ? 0 : -1,
169
+ role: "tab",
170
+ type: "button",
171
+ onClick: !disabled ? handleClick : void 0,
172
+ onKeyDown: shouldHandleKeyDown ? handleKeyDown : void 0,
173
+ onFocus: handleFocus,
174
+ className: clsx(withBaseName(), className),
175
+ id,
176
+ ref: handleRef,
177
+ "data-value": value,
178
+ ...rest,
179
+ children
180
+ }
181
+ );
182
+ }
183
+ );
184
+
185
+ export { TabTrigger };
186
+ //# sourceMappingURL=TabTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabTrigger.js","sources":["../src/tabs/TabTrigger.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n useRef,\n} from \"react\";\nimport { makePrefixer, useForkRef, useIsomorphicLayoutEffect } from \"../utils\";\nimport { useTab } from \"./internal/contexts/TabContext\";\nimport { useTabListLayout } from \"./internal/contexts/TabListLayoutContext\";\nimport { useTabs } from \"./internal/contexts/TabsContext\";\nimport tabTriggerCss from \"./TabTrigger.css\";\n\nexport interface TabTriggerProps\n extends Omit<ComponentPropsWithoutRef<\"button\">, \"id\"> {}\n\nconst withBaseName = makePrefixer(\"saltTabTrigger\");\n\nfunction getAriaDescription(count: number) {\n if (count < 1) {\n return undefined;\n }\n\n if (count === 1) {\n return \"1 action available\";\n }\n\n return `${count} actions available`;\n}\n\nconst ariaActionSupported =\n typeof HTMLElement !== \"undefined\" && \"ariaActions\" in HTMLElement.prototype;\n\nexport const TabTrigger = forwardRef<HTMLButtonElement, TabTriggerProps>(\n function TabTrigger(props, ref) {\n const { children, className, onClick, onKeyDown, onFocus, ...rest } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tab-trigger\",\n css: tabTriggerCss,\n window: targetWindow,\n });\n\n const {\n setSelected,\n registerTab,\n updateTab,\n updateRenderedTab,\n getRenderedTabOrder,\n getPanelId,\n getTabId,\n selected: selectedValue,\n activeTab,\n menuOpen,\n setMenuOpen,\n } = useTabs();\n const { selected, value, focused, disabled, tabId, actions } = useTab();\n const tabListLayout = useTabListLayout();\n\n const tabRef = useRef<HTMLButtonElement>(null);\n\n const location = tabListLayout?.getLocation(value) ?? \"main\";\n const selectionSource = location === \"overflow\" ? \"overflow\" : \"main\";\n const hidden = location === \"hidden\";\n const overflowOpen = location === \"overflow\" && menuOpen;\n const renderOrder = getRenderedTabOrder(value);\n const order = renderOrder >= 0 ? renderOrder : undefined;\n const initialLocationRef = useRef(location);\n const initialOrderRef = useRef(order);\n\n const id = tabId;\n\n useIsomorphicLayoutEffect(() => {\n if (id && tabRef.current) {\n const item = {\n id,\n value,\n element: tabRef.current,\n location: initialLocationRef.current,\n order: initialOrderRef.current,\n };\n\n return registerTab(item);\n }\n }, [id, registerTab, value]);\n\n useIsomorphicLayoutEffect(() => {\n if (!id) {\n return;\n }\n\n updateTab(id, {\n element: tabRef.current,\n location,\n order,\n });\n }, [id, location, order, updateTab]);\n\n useIsomorphicLayoutEffect(() => {\n updateRenderedTab(value, {\n trigger: tabRef.current,\n });\n }, [updateRenderedTab, value]);\n\n useIsomorphicLayoutEffect(() => {\n if (!overflowOpen || tabListLayout?.overflowActiveValue !== value) {\n return;\n }\n\n tabRef.current?.focus({ preventScroll: true });\n }, [overflowOpen, tabListLayout?.overflowActiveValue, value]);\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n\n setSelected(event, value, selectionSource);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event);\n\n if (location === \"overflow\" && event.key === \"Tab\" && event.shiftKey) {\n event.preventDefault();\n setMenuOpen(false);\n\n const doc = event.currentTarget.ownerDocument;\n const overflowTrigger = doc.querySelector<HTMLElement>(\n \"[data-overflowbutton]\",\n );\n const scheduleFocus = targetWindow?.requestAnimationFrame;\n\n if (scheduleFocus) {\n scheduleFocus(() => overflowTrigger?.focus({ preventScroll: true }));\n } else {\n queueMicrotask(() => overflowTrigger?.focus({ preventScroll: true }));\n }\n\n return;\n }\n\n if (\n location === \"overflow\" &&\n tabListLayout &&\n (event.key === \"ArrowDown\" ||\n event.key === \"ArrowUp\" ||\n event.key === \"Home\" ||\n event.key === \"End\")\n ) {\n const moved = tabListLayout.moveOverflowFocus(event.key, value);\n if (moved) {\n event.preventDefault();\n return;\n }\n }\n\n if (disabled) {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n }\n return;\n }\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n setSelected(event, value, selectionSource);\n }\n };\n\n const handleFocus = (event: FocusEvent<HTMLButtonElement>) => {\n onFocus?.(event);\n\n if (id) {\n activeTab.current = { value, id };\n }\n\n if (location === \"overflow\") {\n tabListLayout?.setOverflowActiveValue(value);\n }\n\n // Ensures the associated tab is in view.\n event.currentTarget.parentElement?.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n };\n\n const handleRef = useForkRef<HTMLButtonElement>(tabRef, ref);\n const panelId = getPanelId(value);\n\n // Applying aria-actions this way avoids React warnings about unknown props\n const ariaActionsProps = ariaActionSupported\n ? {\n \"aria-actions\": clsx(actions) || undefined,\n }\n : {};\n\n const active =\n location === \"overflow\" && tabListLayout?.overflowActiveValue === value;\n const hasSelectedTab =\n selectedValue !== undefined && getTabId(selectedValue) != null;\n const fallbackTabStop =\n !hasSelectedTab && location === \"main\" && order === 0;\n const isTabStop =\n !hidden && (focused || selected || active || fallbackTabStop);\n const shouldHandleKeyDown = location === \"overflow\" || !disabled;\n\n return (\n <button\n aria-selected={selected}\n aria-disabled={disabled}\n aria-controls={panelId}\n {...ariaActionsProps}\n aria-description={getAriaDescription(actions.length)}\n tabIndex={isTabStop ? 0 : -1}\n role=\"tab\"\n type=\"button\"\n onClick={!disabled ? handleClick : undefined}\n onKeyDown={shouldHandleKeyDown ? handleKeyDown : undefined}\n onFocus={handleFocus}\n className={clsx(withBaseName(), className)}\n id={id}\n ref={handleRef}\n data-value={value}\n {...rest}\n >\n {children}\n </button>\n );\n },\n);\n"],"names":["TabTrigger","tabTriggerCss"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ var css_248z = ".saltTabs {\n min-width: 0;\n}\n";
2
+
3
+ export { css_248z as default };
4
+ //# sourceMappingURL=Tabs.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,198 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useComponentCssInjection } from '@salt-ds/styles';
3
+ import { useWindow } from '@salt-ds/window';
4
+ import { clsx } from 'clsx';
5
+ import { forwardRef, useState, useRef, useCallback, useMemo } from 'react';
6
+ import { makePrefixer } from '../utils/makePrefixer.js';
7
+ import { useControlled } from '../utils/useControlled.js';
8
+ import '../utils/useFloatingUI/useFloatingUI.js';
9
+ import '../utils/useId.js';
10
+ import '../salt-provider/SaltProvider.js';
11
+ import '../viewport/ViewportProvider.js';
12
+ import { TabsContext } from './internal/contexts/TabsContext.js';
13
+ import { useOverflowSelectionState } from './internal/overflow/useOverflowSelectionState.js';
14
+ import { useCollection } from './internal/registry/useCollection.js';
15
+ import { useRenderedTabsRegistry } from './internal/registry/useRenderedTabsRegistry.js';
16
+ import css_248z from './Tabs.css.js';
17
+
18
+ const withBaseName = makePrefixer("saltTabs");
19
+ function setValueIdMapEntry(map, value, id) {
20
+ if (map.get(value) === id) {
21
+ return map;
22
+ }
23
+ const next = new Map(map);
24
+ next.set(value, id);
25
+ return next;
26
+ }
27
+ function removeValueIdMapEntry(map, value, id) {
28
+ if (map.get(value) !== id) {
29
+ return map;
30
+ }
31
+ const next = new Map(map);
32
+ next.delete(value);
33
+ return next;
34
+ }
35
+ const Tabs = forwardRef(
36
+ function Tabs2(props, ref) {
37
+ const { className, children, value, defaultValue, onChange, ...rest } = props;
38
+ const targetWindow = useWindow();
39
+ useComponentCssInjection({
40
+ testId: "salt-tabs",
41
+ css: css_248z,
42
+ window: targetWindow
43
+ });
44
+ const [valueToTabIdMap, setValueToIdMap] = useState(
45
+ () => /* @__PURE__ */ new Map()
46
+ );
47
+ const [valueToPanelIdMap, setValueToPanelIdMap] = useState(
48
+ () => /* @__PURE__ */ new Map()
49
+ );
50
+ const {
51
+ renderMode,
52
+ registerBootstrapTab,
53
+ setBootstrapTabReady,
54
+ setBootstrapOverflowReady,
55
+ registerRenderedTab,
56
+ updateRenderedTab,
57
+ getRenderedTab,
58
+ getRenderedTabOrder,
59
+ renderedTabs
60
+ } = useRenderedTabsRegistry();
61
+ const {
62
+ registerItem,
63
+ updateItem,
64
+ item,
65
+ getNext,
66
+ getPrevious,
67
+ getFirst,
68
+ getLast,
69
+ itemAt,
70
+ getIndex,
71
+ sortItems,
72
+ removalVersion,
73
+ getRemovedItems
74
+ } = useCollection({ targetWindow, wrap: true });
75
+ const activeTab = useRef();
76
+ const [menuOpen, setMenuOpen] = useState(false);
77
+ const [selected, setSelectedState] = useControlled({
78
+ controlled: value,
79
+ default: defaultValue,
80
+ name: "Tabs",
81
+ state: "selected"
82
+ });
83
+ const commitSelection = useCallback(
84
+ (event, newValue) => {
85
+ setSelectedState(newValue);
86
+ if (selected !== newValue) {
87
+ onChange == null ? void 0 : onChange(event, newValue);
88
+ }
89
+ },
90
+ [onChange, selected]
91
+ );
92
+ const { selectionFromOverflowValueRef, setSelected } = useOverflowSelectionState({
93
+ commitSelection,
94
+ menuOpen,
95
+ selected,
96
+ setMenuOpen
97
+ });
98
+ const registerTab = useCallback(
99
+ (tab) => {
100
+ const cleanup = registerItem(tab);
101
+ setValueToIdMap((map) => setValueIdMapEntry(map, tab.value, tab.id));
102
+ return () => {
103
+ cleanup();
104
+ setValueToIdMap(
105
+ (map) => removeValueIdMapEntry(map, tab.value, tab.id)
106
+ );
107
+ };
108
+ },
109
+ [registerItem]
110
+ );
111
+ const registerPanel = useCallback((id, value2) => {
112
+ setValueToPanelIdMap((map) => setValueIdMapEntry(map, value2, id));
113
+ return () => {
114
+ setValueToPanelIdMap((map) => removeValueIdMapEntry(map, value2, id));
115
+ };
116
+ }, []);
117
+ const getPanelId = useCallback(
118
+ (value2) => {
119
+ return valueToPanelIdMap.get(value2);
120
+ },
121
+ [valueToPanelIdMap]
122
+ );
123
+ const getTabId = useCallback(
124
+ (value2) => {
125
+ return valueToTabIdMap.get(value2);
126
+ },
127
+ [valueToTabIdMap]
128
+ );
129
+ const context = useMemo(
130
+ () => ({
131
+ renderMode,
132
+ registerBootstrapTab,
133
+ setBootstrapTabReady,
134
+ setBootstrapOverflowReady,
135
+ registerTab,
136
+ updateTab: updateItem,
137
+ registerRenderedTab,
138
+ updateRenderedTab,
139
+ getRenderedTab,
140
+ getRenderedTabOrder,
141
+ renderedTabs,
142
+ registerPanel,
143
+ getPanelId,
144
+ getTabId,
145
+ selected,
146
+ setSelected,
147
+ item,
148
+ getNext,
149
+ getPrevious,
150
+ getFirst,
151
+ getLast,
152
+ activeTab,
153
+ selectionFromOverflowValueRef,
154
+ menuOpen,
155
+ setMenuOpen,
156
+ itemAt,
157
+ getIndex,
158
+ sortItems,
159
+ removalVersion,
160
+ getRemovedItems
161
+ }),
162
+ [
163
+ renderMode,
164
+ registerBootstrapTab,
165
+ setBootstrapTabReady,
166
+ setBootstrapOverflowReady,
167
+ registerPanel,
168
+ registerTab,
169
+ updateItem,
170
+ registerRenderedTab,
171
+ updateRenderedTab,
172
+ getRenderedTab,
173
+ getRenderedTabOrder,
174
+ renderedTabs,
175
+ getPanelId,
176
+ getTabId,
177
+ selected,
178
+ setSelected,
179
+ item,
180
+ getNext,
181
+ getPrevious,
182
+ getFirst,
183
+ getLast,
184
+ menuOpen,
185
+ itemAt,
186
+ getIndex,
187
+ sortItems,
188
+ removalVersion,
189
+ getRemovedItems,
190
+ selectionFromOverflowValueRef
191
+ ]
192
+ );
193
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value: context, children: /* @__PURE__ */ jsx("div", { className: clsx(withBaseName(), className), ref, ...rest, children }) });
194
+ }
195
+ );
196
+
197
+ export { Tabs };
198
+ //# sourceMappingURL=Tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.js","sources":["../src/tabs/Tabs.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 useRef,\n useState,\n} from \"react\";\nimport { makePrefixer, useControlled } from \"../utils\";\nimport { type Item, TabsContext } from \"./internal/contexts/TabsContext\";\nimport { useOverflowSelectionState } from \"./internal/overflow/useOverflowSelectionState\";\nimport { useCollection } from \"./internal/registry/useCollection\";\nimport { useRenderedTabsRegistry } from \"./internal/registry/useRenderedTabsRegistry\";\nimport tabsCss from \"./Tabs.css\";\n\nexport interface TabsProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n children?: ReactNode;\n /**\n * The default value. Use when the component is not controlled.\n */\n defaultValue?: string;\n /**\n * The value. Use when the component is controlled.\n */\n value?: string;\n /**\n * Callback fired when the selection changes.\n * The event will be null when selection is moved automatically, such as when\n * the currently selected tab is removed and the next available tab is\n * selected.\n */\n onChange?: (event: SyntheticEvent | null, value: string) => void;\n}\n\nconst withBaseName = makePrefixer(\"saltTabs\");\n\nfunction setValueIdMapEntry(\n map: Map<string, string>,\n value: string,\n id: string,\n) {\n if (map.get(value) === id) {\n return map;\n }\n\n const next = new Map(map);\n next.set(value, id);\n return next;\n}\n\nfunction removeValueIdMapEntry(\n map: Map<string, string>,\n value: string,\n id: string,\n) {\n if (map.get(value) !== id) {\n return map;\n }\n\n const next = new Map(map);\n next.delete(value);\n return next;\n}\n\nexport const Tabs = forwardRef<HTMLDivElement, TabsProps>(\n function Tabs(props, ref) {\n const { className, children, value, defaultValue, onChange, ...rest } =\n props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tabs\",\n css: tabsCss,\n window: targetWindow,\n });\n\n const [valueToTabIdMap, setValueToIdMap] = useState(\n () => new Map<string, string>(),\n );\n const [valueToPanelIdMap, setValueToPanelIdMap] = useState(\n () => new Map<string, string>(),\n );\n const {\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n setBootstrapOverflowReady,\n registerRenderedTab,\n updateRenderedTab,\n getRenderedTab,\n getRenderedTabOrder,\n renderedTabs,\n } = useRenderedTabsRegistry();\n\n const {\n registerItem,\n updateItem,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n itemAt,\n getIndex,\n sortItems,\n removalVersion,\n getRemovedItems,\n } = useCollection({ targetWindow, wrap: true });\n\n const activeTab = useRef<Pick<Item, \"id\" | \"value\">>();\n\n const [menuOpen, setMenuOpen] = useState(false);\n\n const [selected, setSelectedState] = useControlled({\n controlled: value,\n default: defaultValue,\n name: \"Tabs\",\n state: \"selected\",\n });\n\n const commitSelection = useCallback(\n (event: SyntheticEvent | null, newValue: string) => {\n setSelectedState(newValue);\n if (selected !== newValue) {\n onChange?.(event, newValue);\n }\n },\n [onChange, selected],\n );\n const { selectionFromOverflowValueRef, setSelected } =\n useOverflowSelectionState({\n commitSelection,\n menuOpen,\n selected,\n setMenuOpen,\n });\n\n const registerTab = useCallback(\n (tab: Item) => {\n const cleanup = registerItem(tab);\n setValueToIdMap((map) => setValueIdMapEntry(map, tab.value, tab.id));\n\n return () => {\n cleanup();\n setValueToIdMap((map) =>\n removeValueIdMapEntry(map, tab.value, tab.id),\n );\n };\n },\n [registerItem],\n );\n\n const registerPanel = useCallback((id: string, value: string) => {\n setValueToPanelIdMap((map) => setValueIdMapEntry(map, value, id));\n return () => {\n setValueToPanelIdMap((map) => removeValueIdMapEntry(map, value, id));\n };\n }, []);\n\n const getPanelId = useCallback(\n (value: string) => {\n return valueToPanelIdMap.get(value);\n },\n [valueToPanelIdMap],\n );\n\n const getTabId = useCallback(\n (value: string) => {\n return valueToTabIdMap.get(value);\n },\n [valueToTabIdMap],\n );\n\n const context = useMemo(\n () => ({\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n setBootstrapOverflowReady,\n registerTab,\n updateTab: updateItem,\n registerRenderedTab,\n updateRenderedTab,\n getRenderedTab,\n getRenderedTabOrder,\n renderedTabs,\n registerPanel,\n getPanelId,\n getTabId,\n selected,\n setSelected,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n activeTab,\n selectionFromOverflowValueRef,\n menuOpen,\n setMenuOpen,\n itemAt,\n getIndex,\n sortItems,\n removalVersion,\n getRemovedItems,\n }),\n [\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n setBootstrapOverflowReady,\n registerPanel,\n registerTab,\n updateItem,\n registerRenderedTab,\n updateRenderedTab,\n getRenderedTab,\n getRenderedTabOrder,\n renderedTabs,\n getPanelId,\n getTabId,\n selected,\n setSelected,\n item,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n menuOpen,\n itemAt,\n getIndex,\n sortItems,\n removalVersion,\n getRemovedItems,\n selectionFromOverflowValueRef,\n ],\n );\n\n return (\n <TabsContext.Provider value={context}>\n <div className={clsx(withBaseName(), className)} ref={ref} {...rest}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n },\n);\n"],"names":["Tabs","tabsCss","value"],"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 TabContext = createContext("TabContext", {
11
+ focused: false,
12
+ selected: false,
13
+ disabled: false,
14
+ value: "",
15
+ actions: [],
16
+ registerAction: () => () => void 0
17
+ });
18
+ function useTab() {
19
+ return useContext(TabContext);
20
+ }
21
+
22
+ export { TabContext, useTab };
23
+ //# sourceMappingURL=TabContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabContext.js","sources":["../src/tabs/internal/contexts/TabContext.tsx"],"sourcesContent":["import { useContext } from \"react\";\nimport { createContext } from \"../../../utils\";\n\ninterface TabContextValue {\n tabId?: string;\n focused: boolean;\n selected: boolean;\n value: string;\n disabled: boolean;\n actions: string[];\n registerAction: (id: string) => () => void;\n}\n\nexport const TabContext = createContext<TabContextValue>(\"TabContext\", {\n focused: false,\n selected: false,\n disabled: false,\n value: \"\",\n actions: [],\n registerAction: () => () => undefined,\n});\n\nexport function useTab() {\n return useContext(TabContext);\n}\n"],"names":[],"mappings":";;;;;;;;;AAaO,MAAM,UAAA,GAAa,cAA+B,YAAA,EAAc;AAAA,EACrE,OAAA,EAAS,KAAA;AAAA,EACT,QAAA,EAAU,KAAA;AAAA,EACV,QAAA,EAAU,KAAA;AAAA,EACV,KAAA,EAAO,EAAA;AAAA,EACP,SAAS,EAAC;AAAA,EACV,cAAA,EAAgB,MAAM,MAAM;AAC9B,CAAC;AAEM,SAAS,MAAA,GAAS;AACvB,EAAA,OAAO,WAAW,UAAU,CAAA;AAC9B;;;;"}