@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.
- package/CHANGELOG.md +64 -0
- package/css/salt-core.css +366 -1
- package/dist-cjs/aria-announcer/AriaAnnounce.js +15 -3
- package/dist-cjs/aria-announcer/AriaAnnounce.js.map +1 -1
- package/dist-cjs/aria-announcer/AriaAnnouncerContext.js.map +1 -1
- package/dist-cjs/aria-announcer/AriaAnnouncerProvider.js +65 -43
- package/dist-cjs/aria-announcer/AriaAnnouncerProvider.js.map +1 -1
- package/dist-cjs/aria-announcer/announcementRegistry.js +31 -0
- package/dist-cjs/aria-announcer/announcementRegistry.js.map +1 -0
- package/dist-cjs/aria-announcer/useAriaAnnouncer.js +44 -16
- package/dist-cjs/aria-announcer/useAriaAnnouncer.js.map +1 -1
- package/dist-cjs/index.js +17 -1
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/navigation-item/NavigationItem.js +2 -0
- package/dist-cjs/navigation-item/NavigationItem.js.map +1 -1
- package/dist-cjs/pagination/Pagination.js +1 -0
- package/dist-cjs/pagination/Pagination.js.map +1 -1
- package/dist-cjs/rating/Rating.css.js +6 -0
- package/dist-cjs/rating/Rating.css.js.map +1 -0
- package/dist-cjs/rating/Rating.js +140 -0
- package/dist-cjs/rating/Rating.js.map +1 -0
- package/dist-cjs/rating/RatingItem.css.js +6 -0
- package/dist-cjs/rating/RatingItem.css.js.map +1 -0
- package/dist-cjs/rating/RatingItem.js +75 -0
- package/dist-cjs/rating/RatingItem.js.map +1 -0
- package/dist-cjs/salt-provider/SaltProvider.js +3 -1
- package/dist-cjs/salt-provider/SaltProvider.js.map +1 -1
- package/dist-cjs/semantic-icon-provider/SemanticIconProvider.js +22 -20
- package/dist-cjs/semantic-icon-provider/SemanticIconProvider.js.map +1 -1
- package/dist-cjs/spinner/Spinner.js +1 -0
- package/dist-cjs/spinner/Spinner.js.map +1 -1
- package/dist-cjs/tabs/Tab.css.js +6 -0
- package/dist-cjs/tabs/Tab.css.js.map +1 -0
- package/dist-cjs/tabs/Tab.js +211 -0
- package/dist-cjs/tabs/Tab.js.map +1 -0
- package/dist-cjs/tabs/TabAction.js +63 -0
- package/dist-cjs/tabs/TabAction.js.map +1 -0
- package/dist-cjs/tabs/TabBar.css.js +6 -0
- package/dist-cjs/tabs/TabBar.css.js.map +1 -0
- package/dist-cjs/tabs/TabBar.js +45 -0
- package/dist-cjs/tabs/TabBar.js.map +1 -0
- package/dist-cjs/tabs/TabList.css.js +6 -0
- package/dist-cjs/tabs/TabList.css.js.map +1 -0
- package/dist-cjs/tabs/TabList.js +281 -0
- package/dist-cjs/tabs/TabList.js.map +1 -0
- package/dist-cjs/tabs/TabPanel.css.js +6 -0
- package/dist-cjs/tabs/TabPanel.css.js.map +1 -0
- package/dist-cjs/tabs/TabPanel.js +98 -0
- package/dist-cjs/tabs/TabPanel.js.map +1 -0
- package/dist-cjs/tabs/TabTrigger.css.js +6 -0
- package/dist-cjs/tabs/TabTrigger.css.js.map +1 -0
- package/dist-cjs/tabs/TabTrigger.js +188 -0
- package/dist-cjs/tabs/TabTrigger.js.map +1 -0
- package/dist-cjs/tabs/Tabs.css.js +6 -0
- package/dist-cjs/tabs/Tabs.css.js.map +1 -0
- package/dist-cjs/tabs/Tabs.js +200 -0
- package/dist-cjs/tabs/Tabs.js.map +1 -0
- package/dist-cjs/tabs/internal/contexts/TabContext.js +26 -0
- package/dist-cjs/tabs/internal/contexts/TabContext.js.map +1 -0
- package/dist-cjs/tabs/internal/contexts/TabListLayoutContext.js +19 -0
- package/dist-cjs/tabs/internal/contexts/TabListLayoutContext.js.map +1 -0
- package/dist-cjs/tabs/internal/contexts/TabSlotRegistryContext.js +22 -0
- package/dist-cjs/tabs/internal/contexts/TabSlotRegistryContext.js.map +1 -0
- package/dist-cjs/tabs/internal/contexts/TabsContext.js +50 -0
- package/dist-cjs/tabs/internal/contexts/TabsContext.js.map +1 -0
- package/dist-cjs/tabs/internal/hooks/useFocusWithRetry.js +64 -0
- package/dist-cjs/tabs/internal/hooks/useFocusWithRetry.js.map +1 -0
- package/dist-cjs/tabs/internal/hooks/useTabListRecovery.js +76 -0
- package/dist-cjs/tabs/internal/hooks/useTabListRecovery.js.map +1 -0
- package/dist-cjs/tabs/internal/hooks/useTabRemovalHandler.js +165 -0
- package/dist-cjs/tabs/internal/hooks/useTabRemovalHandler.js.map +1 -0
- package/dist-cjs/tabs/internal/hooks/useTabSelectionFocus.js +87 -0
- package/dist-cjs/tabs/internal/hooks/useTabSelectionFocus.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/TabOverflowList.css.js +6 -0
- package/dist-cjs/tabs/internal/overflow/TabOverflowList.css.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/TabOverflowList.js +245 -0
- package/dist-cjs/tabs/internal/overflow/TabOverflowList.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/TabSlot.js +30 -0
- package/dist-cjs/tabs/internal/overflow/TabSlot.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/overflowMath.js +86 -0
- package/dist-cjs/tabs/internal/overflow/overflowMath.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/useOverflow.js +273 -0
- package/dist-cjs/tabs/internal/overflow/useOverflow.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/useOverflowLayoutState.js +99 -0
- package/dist-cjs/tabs/internal/overflow/useOverflowLayoutState.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/useOverflowSelectionState.js +68 -0
- package/dist-cjs/tabs/internal/overflow/useOverflowSelectionState.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/useRenderedTabWidth.js +92 -0
- package/dist-cjs/tabs/internal/overflow/useRenderedTabWidth.js.map +1 -0
- package/dist-cjs/tabs/internal/overflow/widthMeasurement.js +42 -0
- package/dist-cjs/tabs/internal/overflow/widthMeasurement.js.map +1 -0
- package/dist-cjs/tabs/internal/registry/useCollection.js +197 -0
- package/dist-cjs/tabs/internal/registry/useCollection.js.map +1 -0
- package/dist-cjs/tabs/internal/registry/useRenderedTabsRegistry.js +206 -0
- package/dist-cjs/tabs/internal/registry/useRenderedTabsRegistry.js.map +1 -0
- package/dist-cjs/tabs/internal/utils/domUtils.js +13 -0
- package/dist-cjs/tabs/internal/utils/domUtils.js.map +1 -0
- package/dist-cjs/tooltip/useAriaAnnounce.js +1 -0
- package/dist-cjs/tooltip/useAriaAnnounce.js.map +1 -1
- package/dist-es/aria-announcer/AriaAnnounce.js +15 -3
- package/dist-es/aria-announcer/AriaAnnounce.js.map +1 -1
- package/dist-es/aria-announcer/AriaAnnouncerContext.js.map +1 -1
- package/dist-es/aria-announcer/AriaAnnouncerProvider.js +67 -45
- package/dist-es/aria-announcer/AriaAnnouncerProvider.js.map +1 -1
- package/dist-es/aria-announcer/announcementRegistry.js +28 -0
- package/dist-es/aria-announcer/announcementRegistry.js.map +1 -0
- package/dist-es/aria-announcer/useAriaAnnouncer.js +45 -17
- package/dist-es/aria-announcer/useAriaAnnouncer.js.map +1 -1
- package/dist-es/index.js +9 -1
- package/dist-es/index.js.map +1 -1
- package/dist-es/navigation-item/NavigationItem.js +2 -0
- package/dist-es/navigation-item/NavigationItem.js.map +1 -1
- package/dist-es/pagination/Pagination.js +1 -0
- package/dist-es/pagination/Pagination.js.map +1 -1
- package/dist-es/rating/Rating.css.js +4 -0
- package/dist-es/rating/Rating.css.js.map +1 -0
- package/dist-es/rating/Rating.js +138 -0
- package/dist-es/rating/Rating.js.map +1 -0
- package/dist-es/rating/RatingItem.css.js +4 -0
- package/dist-es/rating/RatingItem.css.js.map +1 -0
- package/dist-es/rating/RatingItem.js +73 -0
- package/dist-es/rating/RatingItem.js.map +1 -0
- package/dist-es/salt-provider/SaltProvider.js +3 -1
- package/dist-es/salt-provider/SaltProvider.js.map +1 -1
- package/dist-es/semantic-icon-provider/SemanticIconProvider.js +23 -21
- package/dist-es/semantic-icon-provider/SemanticIconProvider.js.map +1 -1
- package/dist-es/spinner/Spinner.js +1 -0
- package/dist-es/spinner/Spinner.js.map +1 -1
- package/dist-es/tabs/Tab.css.js +4 -0
- package/dist-es/tabs/Tab.css.js.map +1 -0
- package/dist-es/tabs/Tab.js +209 -0
- package/dist-es/tabs/Tab.js.map +1 -0
- package/dist-es/tabs/TabAction.js +61 -0
- package/dist-es/tabs/TabAction.js.map +1 -0
- package/dist-es/tabs/TabBar.css.js +4 -0
- package/dist-es/tabs/TabBar.css.js.map +1 -0
- package/dist-es/tabs/TabBar.js +43 -0
- package/dist-es/tabs/TabBar.js.map +1 -0
- package/dist-es/tabs/TabList.css.js +4 -0
- package/dist-es/tabs/TabList.css.js.map +1 -0
- package/dist-es/tabs/TabList.js +279 -0
- package/dist-es/tabs/TabList.js.map +1 -0
- package/dist-es/tabs/TabPanel.css.js +4 -0
- package/dist-es/tabs/TabPanel.css.js.map +1 -0
- package/dist-es/tabs/TabPanel.js +96 -0
- package/dist-es/tabs/TabPanel.js.map +1 -0
- package/dist-es/tabs/TabTrigger.css.js +4 -0
- package/dist-es/tabs/TabTrigger.css.js.map +1 -0
- package/dist-es/tabs/TabTrigger.js +186 -0
- package/dist-es/tabs/TabTrigger.js.map +1 -0
- package/dist-es/tabs/Tabs.css.js +4 -0
- package/dist-es/tabs/Tabs.css.js.map +1 -0
- package/dist-es/tabs/Tabs.js +198 -0
- package/dist-es/tabs/Tabs.js.map +1 -0
- package/dist-es/tabs/internal/contexts/TabContext.js +23 -0
- package/dist-es/tabs/internal/contexts/TabContext.js.map +1 -0
- package/dist-es/tabs/internal/contexts/TabListLayoutContext.js +16 -0
- package/dist-es/tabs/internal/contexts/TabListLayoutContext.js.map +1 -0
- package/dist-es/tabs/internal/contexts/TabSlotRegistryContext.js +19 -0
- package/dist-es/tabs/internal/contexts/TabSlotRegistryContext.js.map +1 -0
- package/dist-es/tabs/internal/contexts/TabsContext.js +47 -0
- package/dist-es/tabs/internal/contexts/TabsContext.js.map +1 -0
- package/dist-es/tabs/internal/hooks/useFocusWithRetry.js +62 -0
- package/dist-es/tabs/internal/hooks/useFocusWithRetry.js.map +1 -0
- package/dist-es/tabs/internal/hooks/useTabListRecovery.js +74 -0
- package/dist-es/tabs/internal/hooks/useTabListRecovery.js.map +1 -0
- package/dist-es/tabs/internal/hooks/useTabRemovalHandler.js +163 -0
- package/dist-es/tabs/internal/hooks/useTabRemovalHandler.js.map +1 -0
- package/dist-es/tabs/internal/hooks/useTabSelectionFocus.js +85 -0
- package/dist-es/tabs/internal/hooks/useTabSelectionFocus.js.map +1 -0
- package/dist-es/tabs/internal/overflow/TabOverflowList.css.js +4 -0
- package/dist-es/tabs/internal/overflow/TabOverflowList.css.js.map +1 -0
- package/dist-es/tabs/internal/overflow/TabOverflowList.js +243 -0
- package/dist-es/tabs/internal/overflow/TabOverflowList.js.map +1 -0
- package/dist-es/tabs/internal/overflow/TabSlot.js +28 -0
- package/dist-es/tabs/internal/overflow/TabSlot.js.map +1 -0
- package/dist-es/tabs/internal/overflow/overflowMath.js +82 -0
- package/dist-es/tabs/internal/overflow/overflowMath.js.map +1 -0
- package/dist-es/tabs/internal/overflow/useOverflow.js +271 -0
- package/dist-es/tabs/internal/overflow/useOverflow.js.map +1 -0
- package/dist-es/tabs/internal/overflow/useOverflowLayoutState.js +97 -0
- package/dist-es/tabs/internal/overflow/useOverflowLayoutState.js.map +1 -0
- package/dist-es/tabs/internal/overflow/useOverflowSelectionState.js +66 -0
- package/dist-es/tabs/internal/overflow/useOverflowSelectionState.js.map +1 -0
- package/dist-es/tabs/internal/overflow/useRenderedTabWidth.js +90 -0
- package/dist-es/tabs/internal/overflow/useRenderedTabWidth.js.map +1 -0
- package/dist-es/tabs/internal/overflow/widthMeasurement.js +36 -0
- package/dist-es/tabs/internal/overflow/widthMeasurement.js.map +1 -0
- package/dist-es/tabs/internal/registry/useCollection.js +195 -0
- package/dist-es/tabs/internal/registry/useCollection.js.map +1 -0
- package/dist-es/tabs/internal/registry/useRenderedTabsRegistry.js +204 -0
- package/dist-es/tabs/internal/registry/useRenderedTabsRegistry.js.map +1 -0
- package/dist-es/tabs/internal/utils/domUtils.js +11 -0
- package/dist-es/tabs/internal/utils/domUtils.js.map +1 -0
- package/dist-es/tooltip/useAriaAnnounce.js +1 -0
- package/dist-es/tooltip/useAriaAnnounce.js.map +1 -1
- package/dist-types/aria-announcer/AriaAnnounce.d.ts +9 -2
- package/dist-types/aria-announcer/AriaAnnouncerContext.d.ts +26 -2
- package/dist-types/aria-announcer/AriaAnnouncerProvider.d.ts +6 -7
- package/dist-types/aria-announcer/announcementRegistry.d.ts +5 -0
- package/dist-types/index.d.ts +2 -0
- package/dist-types/rating/Rating.d.ts +48 -0
- package/dist-types/rating/RatingItem.d.ts +47 -0
- package/dist-types/rating/index.d.ts +1 -0
- package/dist-types/semantic-icon-provider/SemanticIconProvider.d.ts +21 -19
- package/dist-types/tabs/Tab.d.ts +12 -0
- package/dist-types/tabs/TabAction.d.ts +4 -0
- package/dist-types/tabs/TabBar.d.ts +12 -0
- package/dist-types/tabs/TabList.d.ts +12 -0
- package/dist-types/tabs/TabPanel.d.ts +9 -0
- package/dist-types/tabs/TabTrigger.d.ts +4 -0
- package/dist-types/tabs/Tabs.d.ts +20 -0
- package/dist-types/tabs/index.d.ts +7 -0
- package/dist-types/tabs/internal/contexts/TabContext.d.ts +12 -0
- package/dist-types/tabs/internal/contexts/TabListLayoutContext.d.ts +9 -0
- package/dist-types/tabs/internal/contexts/TabSlotRegistryContext.d.ts +5 -0
- package/dist-types/tabs/internal/contexts/TabsContext.d.ts +43 -0
- package/dist-types/tabs/internal/hooks/useFocusWithRetry.d.ts +9 -0
- package/dist-types/tabs/internal/hooks/useTabListRecovery.d.ts +12 -0
- package/dist-types/tabs/internal/hooks/useTabRemovalHandler.d.ts +32 -0
- package/dist-types/tabs/internal/hooks/useTabSelectionFocus.d.ts +15 -0
- package/dist-types/tabs/internal/overflow/TabOverflowList.d.ts +10 -0
- package/dist-types/tabs/internal/overflow/TabSlot.d.ts +6 -0
- package/dist-types/tabs/internal/overflow/overflowMath.d.ts +18 -0
- package/dist-types/tabs/internal/overflow/useOverflow.d.ts +11 -0
- package/dist-types/tabs/internal/overflow/useOverflowLayoutState.d.ts +13 -0
- package/dist-types/tabs/internal/overflow/useOverflowSelectionState.d.ts +13 -0
- package/dist-types/tabs/internal/overflow/useRenderedTabWidth.d.ts +12 -0
- package/dist-types/tabs/internal/overflow/widthMeasurement.d.ts +5 -0
- package/dist-types/tabs/internal/registry/useCollection.d.ts +30 -0
- package/dist-types/tabs/internal/registry/useRenderedTabsRegistry.d.ts +12 -0
- package/dist-types/tabs/internal/utils/domUtils.d.ts +1 -0
- package/package.json +3 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var styles = require('@salt-ds/styles');
|
|
5
|
+
var window = require('@salt-ds/window');
|
|
6
|
+
var clsx = require('clsx');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var useAriaAnnouncer = require('../aria-announcer/useAriaAnnouncer.js');
|
|
9
|
+
require('../aria-announcer/AriaAnnouncerContext.js');
|
|
10
|
+
require('../aria-announcer/AriaAnnouncerProvider.js');
|
|
11
|
+
var capitalize = require('../utils/capitalize.js');
|
|
12
|
+
var makePrefixer = require('../utils/makePrefixer.js');
|
|
13
|
+
var useIsomorphicLayoutEffect = require('../utils/useIsomorphicLayoutEffect.js');
|
|
14
|
+
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
15
|
+
var useForkRef = require('../utils/useForkRef.js');
|
|
16
|
+
require('../utils/useId.js');
|
|
17
|
+
require('../salt-provider/SaltProvider.js');
|
|
18
|
+
require('../viewport/ViewportProvider.js');
|
|
19
|
+
var TabListLayoutContext = require('./internal/contexts/TabListLayoutContext.js');
|
|
20
|
+
var TabSlotRegistryContext = require('./internal/contexts/TabSlotRegistryContext.js');
|
|
21
|
+
var TabsContext = require('./internal/contexts/TabsContext.js');
|
|
22
|
+
var useFocusWithRetry = require('./internal/hooks/useFocusWithRetry.js');
|
|
23
|
+
var useTabListRecovery = require('./internal/hooks/useTabListRecovery.js');
|
|
24
|
+
var useTabRemovalHandler = require('./internal/hooks/useTabRemovalHandler.js');
|
|
25
|
+
var useTabSelectionFocus = require('./internal/hooks/useTabSelectionFocus.js');
|
|
26
|
+
var TabOverflowList = require('./internal/overflow/TabOverflowList.js');
|
|
27
|
+
var TabSlot = require('./internal/overflow/TabSlot.js');
|
|
28
|
+
var useOverflow = require('./internal/overflow/useOverflow.js');
|
|
29
|
+
var useOverflowLayoutState = require('./internal/overflow/useOverflowLayoutState.js');
|
|
30
|
+
var TabList$1 = require('./TabList.css.js');
|
|
31
|
+
|
|
32
|
+
const withBaseName = makePrefixer.makePrefixer("saltTabList");
|
|
33
|
+
const MAX_FOCUS_RETRY_ATTEMPTS = 120;
|
|
34
|
+
const TabList = React.forwardRef(
|
|
35
|
+
function TabList2(props, ref) {
|
|
36
|
+
const {
|
|
37
|
+
appearance = "bordered",
|
|
38
|
+
activeColor = "primary",
|
|
39
|
+
children,
|
|
40
|
+
className,
|
|
41
|
+
onKeyDown,
|
|
42
|
+
...rest
|
|
43
|
+
} = props;
|
|
44
|
+
const targetWindow = window.useWindow();
|
|
45
|
+
styles.useComponentCssInjection({
|
|
46
|
+
testId: "salt-tab-list",
|
|
47
|
+
css: TabList$1,
|
|
48
|
+
window: targetWindow
|
|
49
|
+
});
|
|
50
|
+
const {
|
|
51
|
+
renderMode,
|
|
52
|
+
selected,
|
|
53
|
+
setSelected,
|
|
54
|
+
setBootstrapOverflowReady,
|
|
55
|
+
getNext,
|
|
56
|
+
getPrevious,
|
|
57
|
+
getFirst,
|
|
58
|
+
getLast,
|
|
59
|
+
getIndex,
|
|
60
|
+
item,
|
|
61
|
+
itemAt,
|
|
62
|
+
activeTab,
|
|
63
|
+
selectionFromOverflowValueRef,
|
|
64
|
+
menuOpen,
|
|
65
|
+
setMenuOpen,
|
|
66
|
+
sortItems,
|
|
67
|
+
getRemovedItems,
|
|
68
|
+
getRenderedTab,
|
|
69
|
+
renderedTabs,
|
|
70
|
+
removalVersion
|
|
71
|
+
} = TabsContext.useTabs();
|
|
72
|
+
const tabstripRef = React.useRef(null);
|
|
73
|
+
const overflowListRef = React.useRef(null);
|
|
74
|
+
const slotMapRef = React.useRef(/* @__PURE__ */ new Map());
|
|
75
|
+
const removalRecoveryRafRef = React.useRef(null);
|
|
76
|
+
const pendingRemovalRecoveryRef = React.useRef(false);
|
|
77
|
+
const pendingRemovalRecoveryRetriesRef = React.useRef(0);
|
|
78
|
+
const [slotVersion, setSlotVersion] = React.useState(0);
|
|
79
|
+
const handleRef = useForkRef.useForkRef(tabstripRef, ref);
|
|
80
|
+
const overflowButtonRef = React.useRef(null);
|
|
81
|
+
const { announce } = useAriaAnnouncer.useAriaAnnouncer();
|
|
82
|
+
const overflowMenuOpen = renderMode === "portal" ? menuOpen : false;
|
|
83
|
+
const [visibleValues, hiddenValues, isMeasuring] = useOverflow.useOverflow({
|
|
84
|
+
container: tabstripRef,
|
|
85
|
+
menuOpen: overflowMenuOpen,
|
|
86
|
+
selected,
|
|
87
|
+
tabs: renderedTabs,
|
|
88
|
+
overflowButton: overflowButtonRef
|
|
89
|
+
});
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
setBootstrapOverflowReady(
|
|
92
|
+
renderMode === "inline" && renderedTabs.length > 0 && !isMeasuring
|
|
93
|
+
);
|
|
94
|
+
}, [
|
|
95
|
+
isMeasuring,
|
|
96
|
+
renderMode,
|
|
97
|
+
renderedTabs.length,
|
|
98
|
+
setBootstrapOverflowReady
|
|
99
|
+
]);
|
|
100
|
+
const { resolvedOverflowActiveValue, tabListLayoutContext } = useOverflowLayoutState.useOverflowLayoutState({
|
|
101
|
+
hiddenValues,
|
|
102
|
+
menuOpen,
|
|
103
|
+
overflowMenuOpen,
|
|
104
|
+
visibleValues
|
|
105
|
+
});
|
|
106
|
+
const registerSlot = React.useCallback(
|
|
107
|
+
(slotId, element) => {
|
|
108
|
+
const currentElement = slotMapRef.current.get(slotId) ?? null;
|
|
109
|
+
if (currentElement === element) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (element) {
|
|
113
|
+
slotMapRef.current.set(slotId, element);
|
|
114
|
+
} else {
|
|
115
|
+
slotMapRef.current.delete(slotId);
|
|
116
|
+
}
|
|
117
|
+
setSlotVersion((currentVersion) => currentVersion + 1);
|
|
118
|
+
},
|
|
119
|
+
[]
|
|
120
|
+
);
|
|
121
|
+
const slotRegistryContext = React.useMemo(
|
|
122
|
+
() => ({ registerSlot }),
|
|
123
|
+
[registerSlot]
|
|
124
|
+
);
|
|
125
|
+
const slotAssignments = React.useMemo(() => {
|
|
126
|
+
const nextAssignments = /* @__PURE__ */ new Map();
|
|
127
|
+
for (const value of visibleValues) {
|
|
128
|
+
nextAssignments.set(value, `main:${value}`);
|
|
129
|
+
}
|
|
130
|
+
for (const value of hiddenValues) {
|
|
131
|
+
nextAssignments.set(
|
|
132
|
+
value,
|
|
133
|
+
menuOpen ? `overflow:${value}` : `measure:${value}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
map: nextAssignments,
|
|
138
|
+
version: slotVersion
|
|
139
|
+
};
|
|
140
|
+
}, [hiddenValues, menuOpen, slotVersion, visibleValues]);
|
|
141
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
142
|
+
var _a;
|
|
143
|
+
if (renderMode !== "portal") {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
for (const [value, slotId] of slotAssignments.map) {
|
|
147
|
+
const host = (_a = getRenderedTab(value)) == null ? void 0 : _a.host;
|
|
148
|
+
const slot = slotMapRef.current.get(slotId);
|
|
149
|
+
if (host && slot && host.parentElement !== slot) {
|
|
150
|
+
slot.appendChild(host);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, [getRenderedTab, renderMode, slotAssignments]);
|
|
154
|
+
const handleKeyDown = (event) => {
|
|
155
|
+
var _a, _b;
|
|
156
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
157
|
+
if (menuOpen) return;
|
|
158
|
+
const actionMap = {
|
|
159
|
+
ArrowRight: getNext,
|
|
160
|
+
ArrowLeft: getPrevious,
|
|
161
|
+
Home: getFirst,
|
|
162
|
+
End: getLast
|
|
163
|
+
};
|
|
164
|
+
const action = actionMap[event.key];
|
|
165
|
+
if (action) {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
sortItems();
|
|
168
|
+
const activeTabId = (_a = activeTab.current) == null ? void 0 : _a.id;
|
|
169
|
+
if (!activeTabId) return;
|
|
170
|
+
const nextItem = action(activeTabId);
|
|
171
|
+
if (nextItem) {
|
|
172
|
+
(_b = nextItem.element) == null ? void 0 : _b.focus({ preventScroll: true });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const getSelectedTabElement = React.useCallback(() => {
|
|
177
|
+
var _a, _b, _c;
|
|
178
|
+
return ((_a = tabstripRef.current) == null ? void 0 : _a.querySelector(
|
|
179
|
+
'[role="tab"][aria-selected="true"]'
|
|
180
|
+
)) ?? ((_c = item((_b = activeTab.current) == null ? void 0 : _b.id)) == null ? void 0 : _c.element);
|
|
181
|
+
}, [item, activeTab]);
|
|
182
|
+
const { focusElementWithRetry } = useFocusWithRetry.useFocusWithRetry({
|
|
183
|
+
maxAttempts: MAX_FOCUS_RETRY_ATTEMPTS,
|
|
184
|
+
targetWindow
|
|
185
|
+
});
|
|
186
|
+
useTabSelectionFocus.useTabSelectionFocus({
|
|
187
|
+
announce,
|
|
188
|
+
focusElementWithRetry,
|
|
189
|
+
getRenderedTab,
|
|
190
|
+
getSelectedTabElement,
|
|
191
|
+
menuOpen,
|
|
192
|
+
resolvedOverflowActiveValue,
|
|
193
|
+
selected,
|
|
194
|
+
selectionFromOverflowValueRef,
|
|
195
|
+
targetWindow
|
|
196
|
+
});
|
|
197
|
+
const handleTabRemoval = useTabRemovalHandler.useTabRemovalHandler({
|
|
198
|
+
activeTab,
|
|
199
|
+
focusElementWithRetry,
|
|
200
|
+
getFirst,
|
|
201
|
+
getIndex,
|
|
202
|
+
getLast,
|
|
203
|
+
getRemovedItems,
|
|
204
|
+
getRenderedTab,
|
|
205
|
+
getSelectedTabElement,
|
|
206
|
+
item,
|
|
207
|
+
itemAt,
|
|
208
|
+
maxRetryAttempts: MAX_FOCUS_RETRY_ATTEMPTS,
|
|
209
|
+
menuOpen,
|
|
210
|
+
overflowButtonRef,
|
|
211
|
+
overflowListRef,
|
|
212
|
+
pendingRemovalRecoveryRef,
|
|
213
|
+
pendingRemovalRecoveryRetriesRef,
|
|
214
|
+
removalRecoveryRafRef,
|
|
215
|
+
selected,
|
|
216
|
+
setSelected,
|
|
217
|
+
tabstripRef,
|
|
218
|
+
targetWindow
|
|
219
|
+
});
|
|
220
|
+
useTabListRecovery.useTabListRecovery({
|
|
221
|
+
removalVersion,
|
|
222
|
+
targetWindow,
|
|
223
|
+
tabstripRef,
|
|
224
|
+
overflowListRef,
|
|
225
|
+
handleTabRemoval,
|
|
226
|
+
pendingRemovalRecoveryRef,
|
|
227
|
+
pendingRemovalRecoveryRetriesRef
|
|
228
|
+
});
|
|
229
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
230
|
+
"div",
|
|
231
|
+
{
|
|
232
|
+
role: "tablist",
|
|
233
|
+
className: clsx.clsx(
|
|
234
|
+
withBaseName(),
|
|
235
|
+
withBaseName(appearance),
|
|
236
|
+
withBaseName("horizontal"),
|
|
237
|
+
withBaseName(`activeColor${capitalize.capitalize(activeColor)}`),
|
|
238
|
+
className
|
|
239
|
+
),
|
|
240
|
+
"data-ismeasuring": renderMode === "portal" && isMeasuring ? true : void 0,
|
|
241
|
+
ref: handleRef,
|
|
242
|
+
onKeyDown: handleKeyDown,
|
|
243
|
+
...rest,
|
|
244
|
+
children: renderMode === "inline" ? children : /* @__PURE__ */ jsxRuntime.jsx(TabSlotRegistryContext.TabSlotRegistryContext.Provider, { value: slotRegistryContext, children: /* @__PURE__ */ jsxRuntime.jsxs(TabListLayoutContext.TabListLayoutContext.Provider, { value: tabListLayoutContext, children: [
|
|
245
|
+
children,
|
|
246
|
+
visibleValues.map((value) => /* @__PURE__ */ jsxRuntime.jsx(TabSlot.TabSlot, { slotId: `main:${value}`, value }, value)),
|
|
247
|
+
!menuOpen && hiddenValues.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
248
|
+
"div",
|
|
249
|
+
{
|
|
250
|
+
"aria-hidden": "true",
|
|
251
|
+
role: "presentation",
|
|
252
|
+
className: withBaseName("measureContainer"),
|
|
253
|
+
children: hiddenValues.map((value) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
254
|
+
TabSlot.TabSlot,
|
|
255
|
+
{
|
|
256
|
+
slotId: `measure:${value}`,
|
|
257
|
+
value
|
|
258
|
+
},
|
|
259
|
+
`measure-${value}`
|
|
260
|
+
))
|
|
261
|
+
}
|
|
262
|
+
) : null,
|
|
263
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
264
|
+
TabOverflowList.TabOverflowList,
|
|
265
|
+
{
|
|
266
|
+
buttonRef: overflowButtonRef,
|
|
267
|
+
hiddenValues,
|
|
268
|
+
open: menuOpen,
|
|
269
|
+
order: renderedTabs.length,
|
|
270
|
+
setOpen: setMenuOpen,
|
|
271
|
+
ref: overflowListRef
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
] }) })
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
exports.TabList = TabList;
|
|
281
|
+
//# sourceMappingURL=TabList.js.map
|
|
@@ -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":["makePrefixer","forwardRef","TabList","useWindow","useComponentCssInjection","tabListCss","useTabs","useRef","useState","useForkRef","useAriaAnnouncer","useOverflow","useEffect","useOverflowLayoutState","useCallback","useMemo","useIsomorphicLayoutEffect","useFocusWithRetry","useTabSelectionFocus","useTabRemovalHandler","useTabListRecovery","jsx","clsx","capitalize","TabSlotRegistryContext","jsxs","TabListLayoutContext","TabSlot","TabOverflowList"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
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";
|
|
4
|
+
|
|
5
|
+
module.exports = css_248z;
|
|
6
|
+
//# sourceMappingURL=TabPanel.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabPanel.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var styles = require('@salt-ds/styles');
|
|
5
|
+
var window = require('@salt-ds/window');
|
|
6
|
+
var clsx = require('clsx');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var tabbable = require('tabbable');
|
|
9
|
+
var makePrefixer = require('../utils/makePrefixer.js');
|
|
10
|
+
var useIsomorphicLayoutEffect = require('../utils/useIsomorphicLayoutEffect.js');
|
|
11
|
+
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
12
|
+
var useForkRef = require('../utils/useForkRef.js');
|
|
13
|
+
var useId = require('../utils/useId.js');
|
|
14
|
+
require('../salt-provider/SaltProvider.js');
|
|
15
|
+
require('../viewport/ViewportProvider.js');
|
|
16
|
+
var TabsContext = require('./internal/contexts/TabsContext.js');
|
|
17
|
+
var TabPanel$1 = require('./TabPanel.css.js');
|
|
18
|
+
|
|
19
|
+
const withBaseName = makePrefixer.makePrefixer("saltTabPanel");
|
|
20
|
+
const TabPanel = React.forwardRef(
|
|
21
|
+
function TabPanel2(props, ref) {
|
|
22
|
+
const { className, children, id: idProp, value, ...rest } = props;
|
|
23
|
+
const targetWindow = window.useWindow();
|
|
24
|
+
styles.useComponentCssInjection({
|
|
25
|
+
testId: "salt-tab-panel",
|
|
26
|
+
css: TabPanel$1,
|
|
27
|
+
window: targetWindow
|
|
28
|
+
});
|
|
29
|
+
const id = useId.useId(idProp);
|
|
30
|
+
const { registerPanel, getTabId, selected } = TabsContext.useTabs();
|
|
31
|
+
const hidden = selected !== value;
|
|
32
|
+
const panelRef = React.useRef(null);
|
|
33
|
+
const handleRef = useForkRef.useForkRef(panelRef, ref);
|
|
34
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
35
|
+
if (id) {
|
|
36
|
+
return registerPanel(id, value);
|
|
37
|
+
}
|
|
38
|
+
}, [value, id, registerPanel]);
|
|
39
|
+
const [hasFocusableChildren, setHasFocusableChildren] = React.useState(false);
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
const element = panelRef.current;
|
|
42
|
+
const mutationObserverCtor = targetWindow == null ? void 0 : targetWindow.MutationObserver;
|
|
43
|
+
if (!element || hidden) return;
|
|
44
|
+
let rafId = null;
|
|
45
|
+
const detectFocusableChildren = () => {
|
|
46
|
+
rafId = null;
|
|
47
|
+
const elements = tabbable.tabbable(element);
|
|
48
|
+
const nextHasFocusableChildren = elements.length > 0;
|
|
49
|
+
setHasFocusableChildren((prev) => {
|
|
50
|
+
return prev === nextHasFocusableChildren ? prev : nextHasFocusableChildren;
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const scheduleDetectFocusableChildren = () => {
|
|
54
|
+
if (rafId != null && targetWindow) {
|
|
55
|
+
targetWindow.cancelAnimationFrame(rafId);
|
|
56
|
+
}
|
|
57
|
+
if (!(targetWindow == null ? void 0 : targetWindow.requestAnimationFrame)) {
|
|
58
|
+
detectFocusableChildren();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
rafId = targetWindow.requestAnimationFrame(detectFocusableChildren);
|
|
62
|
+
};
|
|
63
|
+
const observer = mutationObserverCtor ? new mutationObserverCtor(() => {
|
|
64
|
+
scheduleDetectFocusableChildren();
|
|
65
|
+
}) : null;
|
|
66
|
+
scheduleDetectFocusableChildren();
|
|
67
|
+
observer == null ? void 0 : observer.observe(element, {
|
|
68
|
+
childList: true,
|
|
69
|
+
subtree: true,
|
|
70
|
+
attributes: true
|
|
71
|
+
});
|
|
72
|
+
return () => {
|
|
73
|
+
observer == null ? void 0 : observer.disconnect();
|
|
74
|
+
if (rafId != null && targetWindow) {
|
|
75
|
+
targetWindow.cancelAnimationFrame(rafId);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}, [hidden, targetWindow]);
|
|
79
|
+
const tabId = getTabId(value);
|
|
80
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
id,
|
|
84
|
+
ref: handleRef,
|
|
85
|
+
role: "tabpanel",
|
|
86
|
+
"aria-labelledby": tabId,
|
|
87
|
+
className: clsx.clsx(withBaseName(), className),
|
|
88
|
+
hidden: hidden || void 0,
|
|
89
|
+
tabIndex: hidden || hasFocusableChildren ? void 0 : 0,
|
|
90
|
+
...rest,
|
|
91
|
+
children
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
exports.TabPanel = TabPanel;
|
|
98
|
+
//# 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":["makePrefixer","forwardRef","TabPanel","useWindow","useComponentCssInjection","tabPanelCss","useId","useTabs","useRef","useForkRef","useIsomorphicLayoutEffect","useState","useEffect","tabbable","jsx","clsx"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
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";
|
|
4
|
+
|
|
5
|
+
module.exports = css_248z;
|
|
6
|
+
//# sourceMappingURL=TabTrigger.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TabTrigger.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var styles = require('@salt-ds/styles');
|
|
5
|
+
var window = require('@salt-ds/window');
|
|
6
|
+
var clsx = require('clsx');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var makePrefixer = require('../utils/makePrefixer.js');
|
|
9
|
+
var useIsomorphicLayoutEffect = require('../utils/useIsomorphicLayoutEffect.js');
|
|
10
|
+
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
11
|
+
var useForkRef = require('../utils/useForkRef.js');
|
|
12
|
+
require('../utils/useId.js');
|
|
13
|
+
require('../salt-provider/SaltProvider.js');
|
|
14
|
+
require('../viewport/ViewportProvider.js');
|
|
15
|
+
var TabContext = require('./internal/contexts/TabContext.js');
|
|
16
|
+
var TabListLayoutContext = require('./internal/contexts/TabListLayoutContext.js');
|
|
17
|
+
var TabsContext = require('./internal/contexts/TabsContext.js');
|
|
18
|
+
var TabTrigger$1 = require('./TabTrigger.css.js');
|
|
19
|
+
|
|
20
|
+
const withBaseName = makePrefixer.makePrefixer("saltTabTrigger");
|
|
21
|
+
function getAriaDescription(count) {
|
|
22
|
+
if (count < 1) {
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
if (count === 1) {
|
|
26
|
+
return "1 action available";
|
|
27
|
+
}
|
|
28
|
+
return `${count} actions available`;
|
|
29
|
+
}
|
|
30
|
+
const ariaActionSupported = typeof HTMLElement !== "undefined" && "ariaActions" in HTMLElement.prototype;
|
|
31
|
+
const TabTrigger = React.forwardRef(
|
|
32
|
+
function TabTrigger2(props, ref) {
|
|
33
|
+
const { children, className, onClick, onKeyDown, onFocus, ...rest } = props;
|
|
34
|
+
const targetWindow = window.useWindow();
|
|
35
|
+
styles.useComponentCssInjection({
|
|
36
|
+
testId: "salt-tab-trigger",
|
|
37
|
+
css: TabTrigger$1,
|
|
38
|
+
window: targetWindow
|
|
39
|
+
});
|
|
40
|
+
const {
|
|
41
|
+
setSelected,
|
|
42
|
+
registerTab,
|
|
43
|
+
updateTab,
|
|
44
|
+
updateRenderedTab,
|
|
45
|
+
getRenderedTabOrder,
|
|
46
|
+
getPanelId,
|
|
47
|
+
getTabId,
|
|
48
|
+
selected: selectedValue,
|
|
49
|
+
activeTab,
|
|
50
|
+
menuOpen,
|
|
51
|
+
setMenuOpen
|
|
52
|
+
} = TabsContext.useTabs();
|
|
53
|
+
const { selected, value, focused, disabled, tabId, actions } = TabContext.useTab();
|
|
54
|
+
const tabListLayout = TabListLayoutContext.useTabListLayout();
|
|
55
|
+
const tabRef = React.useRef(null);
|
|
56
|
+
const location = (tabListLayout == null ? void 0 : tabListLayout.getLocation(value)) ?? "main";
|
|
57
|
+
const selectionSource = location === "overflow" ? "overflow" : "main";
|
|
58
|
+
const hidden = location === "hidden";
|
|
59
|
+
const overflowOpen = location === "overflow" && menuOpen;
|
|
60
|
+
const renderOrder = getRenderedTabOrder(value);
|
|
61
|
+
const order = renderOrder >= 0 ? renderOrder : void 0;
|
|
62
|
+
const initialLocationRef = React.useRef(location);
|
|
63
|
+
const initialOrderRef = React.useRef(order);
|
|
64
|
+
const id = tabId;
|
|
65
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
66
|
+
if (id && tabRef.current) {
|
|
67
|
+
const item = {
|
|
68
|
+
id,
|
|
69
|
+
value,
|
|
70
|
+
element: tabRef.current,
|
|
71
|
+
location: initialLocationRef.current,
|
|
72
|
+
order: initialOrderRef.current
|
|
73
|
+
};
|
|
74
|
+
return registerTab(item);
|
|
75
|
+
}
|
|
76
|
+
}, [id, registerTab, value]);
|
|
77
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
78
|
+
if (!id) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
updateTab(id, {
|
|
82
|
+
element: tabRef.current,
|
|
83
|
+
location,
|
|
84
|
+
order
|
|
85
|
+
});
|
|
86
|
+
}, [id, location, order, updateTab]);
|
|
87
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
88
|
+
updateRenderedTab(value, {
|
|
89
|
+
trigger: tabRef.current
|
|
90
|
+
});
|
|
91
|
+
}, [updateRenderedTab, value]);
|
|
92
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
93
|
+
var _a;
|
|
94
|
+
if (!overflowOpen || (tabListLayout == null ? void 0 : tabListLayout.overflowActiveValue) !== value) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
(_a = tabRef.current) == null ? void 0 : _a.focus({ preventScroll: true });
|
|
98
|
+
}, [overflowOpen, tabListLayout == null ? void 0 : tabListLayout.overflowActiveValue, value]);
|
|
99
|
+
const handleClick = (event) => {
|
|
100
|
+
onClick == null ? void 0 : onClick(event);
|
|
101
|
+
setSelected(event, value, selectionSource);
|
|
102
|
+
};
|
|
103
|
+
const handleKeyDown = (event) => {
|
|
104
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
105
|
+
if (location === "overflow" && event.key === "Tab" && event.shiftKey) {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
setMenuOpen(false);
|
|
108
|
+
const doc = event.currentTarget.ownerDocument;
|
|
109
|
+
const overflowTrigger = doc.querySelector(
|
|
110
|
+
"[data-overflowbutton]"
|
|
111
|
+
);
|
|
112
|
+
const scheduleFocus = targetWindow == null ? void 0 : targetWindow.requestAnimationFrame;
|
|
113
|
+
if (scheduleFocus) {
|
|
114
|
+
scheduleFocus(() => overflowTrigger == null ? void 0 : overflowTrigger.focus({ preventScroll: true }));
|
|
115
|
+
} else {
|
|
116
|
+
queueMicrotask(() => overflowTrigger == null ? void 0 : overflowTrigger.focus({ preventScroll: true }));
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (location === "overflow" && tabListLayout && (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Home" || event.key === "End")) {
|
|
121
|
+
const moved = tabListLayout.moveOverflowFocus(event.key, value);
|
|
122
|
+
if (moved) {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (disabled) {
|
|
128
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
setSelected(event, value, selectionSource);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const handleFocus = (event) => {
|
|
139
|
+
var _a;
|
|
140
|
+
onFocus == null ? void 0 : onFocus(event);
|
|
141
|
+
if (id) {
|
|
142
|
+
activeTab.current = { value, id };
|
|
143
|
+
}
|
|
144
|
+
if (location === "overflow") {
|
|
145
|
+
tabListLayout == null ? void 0 : tabListLayout.setOverflowActiveValue(value);
|
|
146
|
+
}
|
|
147
|
+
(_a = event.currentTarget.parentElement) == null ? void 0 : _a.scrollIntoView({
|
|
148
|
+
block: "nearest",
|
|
149
|
+
inline: "nearest"
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
const handleRef = useForkRef.useForkRef(tabRef, ref);
|
|
153
|
+
const panelId = getPanelId(value);
|
|
154
|
+
const ariaActionsProps = ariaActionSupported ? {
|
|
155
|
+
"aria-actions": clsx.clsx(actions) || void 0
|
|
156
|
+
} : {};
|
|
157
|
+
const active = location === "overflow" && (tabListLayout == null ? void 0 : tabListLayout.overflowActiveValue) === value;
|
|
158
|
+
const hasSelectedTab = selectedValue !== void 0 && getTabId(selectedValue) != null;
|
|
159
|
+
const fallbackTabStop = !hasSelectedTab && location === "main" && order === 0;
|
|
160
|
+
const isTabStop = !hidden && (focused || selected || active || fallbackTabStop);
|
|
161
|
+
const shouldHandleKeyDown = location === "overflow" || !disabled;
|
|
162
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
163
|
+
"button",
|
|
164
|
+
{
|
|
165
|
+
"aria-selected": selected,
|
|
166
|
+
"aria-disabled": disabled,
|
|
167
|
+
"aria-controls": panelId,
|
|
168
|
+
...ariaActionsProps,
|
|
169
|
+
"aria-description": getAriaDescription(actions.length),
|
|
170
|
+
tabIndex: isTabStop ? 0 : -1,
|
|
171
|
+
role: "tab",
|
|
172
|
+
type: "button",
|
|
173
|
+
onClick: !disabled ? handleClick : void 0,
|
|
174
|
+
onKeyDown: shouldHandleKeyDown ? handleKeyDown : void 0,
|
|
175
|
+
onFocus: handleFocus,
|
|
176
|
+
className: clsx.clsx(withBaseName(), className),
|
|
177
|
+
id,
|
|
178
|
+
ref: handleRef,
|
|
179
|
+
"data-value": value,
|
|
180
|
+
...rest,
|
|
181
|
+
children
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
exports.TabTrigger = TabTrigger;
|
|
188
|
+
//# sourceMappingURL=TabTrigger.js.map
|