@salt-ds/lab 1.0.0-alpha.88 → 1.0.0-alpha.89
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 +14 -0
- package/css/salt-lab.css +53 -25
- package/dist-cjs/list-deprecated/ListStateContext.js +1 -1
- package/dist-cjs/list-deprecated/ListStateContext.js.map +1 -1
- package/dist-cjs/tabs-next/TabBar.css.js +1 -1
- package/dist-cjs/tabs-next/TabBar.js +1 -1
- package/dist-cjs/tabs-next/TabBar.js.map +1 -1
- package/dist-cjs/tabs-next/TabListLayoutContext.js +13 -0
- package/dist-cjs/tabs-next/TabListLayoutContext.js.map +1 -0
- package/dist-cjs/tabs-next/TabListNext.css.js +1 -1
- package/dist-cjs/tabs-next/TabListNext.js +179 -33
- package/dist-cjs/tabs-next/TabListNext.js.map +1 -1
- package/dist-cjs/tabs-next/TabNext.js +111 -7
- package/dist-cjs/tabs-next/TabNext.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextAction.js +25 -2
- package/dist-cjs/tabs-next/TabNextAction.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextPanel.js +31 -16
- package/dist-cjs/tabs-next/TabNextPanel.js.map +1 -1
- package/dist-cjs/tabs-next/TabNextTrigger.js +110 -9
- package/dist-cjs/tabs-next/TabNextTrigger.js.map +1 -1
- package/dist-cjs/tabs-next/TabOverflowList.css.js +1 -1
- package/dist-cjs/tabs-next/TabOverflowList.js +168 -64
- package/dist-cjs/tabs-next/TabOverflowList.js.map +1 -1
- package/dist-cjs/tabs-next/TabSlot.js +30 -0
- package/dist-cjs/tabs-next/TabSlot.js.map +1 -0
- package/dist-cjs/tabs-next/TabSlotRegistryContext.js +16 -0
- package/dist-cjs/tabs-next/TabSlotRegistryContext.js.map +1 -0
- package/dist-cjs/tabs-next/TabsNext.css.js +6 -0
- package/dist-cjs/tabs-next/TabsNext.css.js.map +1 -0
- package/dist-cjs/tabs-next/TabsNext.js +113 -47
- package/dist-cjs/tabs-next/TabsNext.js.map +1 -1
- package/dist-cjs/tabs-next/TabsNextContext.js +17 -3
- package/dist-cjs/tabs-next/TabsNextContext.js.map +1 -1
- package/dist-cjs/tabs-next/domUtils.js +13 -0
- package/dist-cjs/tabs-next/domUtils.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/overflowMath.js +86 -0
- package/dist-cjs/tabs-next/hooks/overflowMath.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useCollection.js +147 -41
- package/dist-cjs/tabs-next/hooks/useCollection.js.map +1 -1
- package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js +64 -0
- package/dist-cjs/tabs-next/hooks/useFocusWithRetry.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useOverflow.js +240 -156
- package/dist-cjs/tabs-next/hooks/useOverflow.js.map +1 -1
- package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js +99 -0
- package/dist-cjs/tabs-next/hooks/useOverflowLayoutState.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js +60 -0
- package/dist-cjs/tabs-next/hooks/useOverflowSelectionState.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js +92 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabWidth.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js +200 -0
- package/dist-cjs/tabs-next/hooks/useRenderedTabsRegistry.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useTabListRecovery.js +76 -0
- package/dist-cjs/tabs-next/hooks/useTabListRecovery.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js +165 -0
- package/dist-cjs/tabs-next/hooks/useTabRemovalHandler.js.map +1 -0
- package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js +80 -0
- package/dist-cjs/tabs-next/hooks/useTabSelectionFocus.js.map +1 -0
- package/dist-cjs/tabs-next/widthMeasurement.js +42 -0
- package/dist-cjs/tabs-next/widthMeasurement.js.map +1 -0
- package/dist-cjs/tree/Tree.css.js +1 -1
- package/dist-cjs/tree/TreeNode.css.js +1 -1
- package/dist-cjs/tree/TreeNode.js +1 -1
- package/dist-cjs/tree/TreeNode.js.map +1 -1
- package/dist-cjs/tree/TreeNodeExpansionIcon.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.js +2 -2
- package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
- package/dist-cjs/utils/useEventCallback.js +5 -5
- package/dist-cjs/utils/useEventCallback.js.map +1 -1
- package/dist-es/list-deprecated/ListStateContext.js +1 -1
- package/dist-es/list-deprecated/ListStateContext.js.map +1 -1
- package/dist-es/tabs-next/TabBar.css.js +1 -1
- package/dist-es/tabs-next/TabBar.js +1 -1
- package/dist-es/tabs-next/TabBar.js.map +1 -1
- package/dist-es/tabs-next/TabListLayoutContext.js +10 -0
- package/dist-es/tabs-next/TabListLayoutContext.js.map +1 -0
- package/dist-es/tabs-next/TabListNext.css.js +1 -1
- package/dist-es/tabs-next/TabListNext.js +182 -36
- package/dist-es/tabs-next/TabListNext.js.map +1 -1
- package/dist-es/tabs-next/TabNext.js +113 -9
- package/dist-es/tabs-next/TabNext.js.map +1 -1
- package/dist-es/tabs-next/TabNextAction.js +25 -2
- package/dist-es/tabs-next/TabNextAction.js.map +1 -1
- package/dist-es/tabs-next/TabNextPanel.js +31 -16
- package/dist-es/tabs-next/TabNextPanel.js.map +1 -1
- package/dist-es/tabs-next/TabNextTrigger.js +110 -9
- package/dist-es/tabs-next/TabNextTrigger.js.map +1 -1
- package/dist-es/tabs-next/TabOverflowList.css.js +1 -1
- package/dist-es/tabs-next/TabOverflowList.js +172 -68
- package/dist-es/tabs-next/TabOverflowList.js.map +1 -1
- package/dist-es/tabs-next/TabSlot.js +28 -0
- package/dist-es/tabs-next/TabSlot.js.map +1 -0
- package/dist-es/tabs-next/TabSlotRegistryContext.js +13 -0
- package/dist-es/tabs-next/TabSlotRegistryContext.js.map +1 -0
- package/dist-es/tabs-next/TabsNext.css.js +4 -0
- package/dist-es/tabs-next/TabsNext.css.js.map +1 -0
- package/dist-es/tabs-next/TabsNext.js +114 -48
- package/dist-es/tabs-next/TabsNext.js.map +1 -1
- package/dist-es/tabs-next/TabsNextContext.js +17 -3
- package/dist-es/tabs-next/TabsNextContext.js.map +1 -1
- package/dist-es/tabs-next/domUtils.js +11 -0
- package/dist-es/tabs-next/domUtils.js.map +1 -0
- package/dist-es/tabs-next/hooks/overflowMath.js +82 -0
- package/dist-es/tabs-next/hooks/overflowMath.js.map +1 -0
- package/dist-es/tabs-next/hooks/useCollection.js +148 -42
- package/dist-es/tabs-next/hooks/useCollection.js.map +1 -1
- package/dist-es/tabs-next/hooks/useFocusWithRetry.js +62 -0
- package/dist-es/tabs-next/hooks/useFocusWithRetry.js.map +1 -0
- package/dist-es/tabs-next/hooks/useOverflow.js +242 -158
- package/dist-es/tabs-next/hooks/useOverflow.js.map +1 -1
- package/dist-es/tabs-next/hooks/useOverflowLayoutState.js +97 -0
- package/dist-es/tabs-next/hooks/useOverflowLayoutState.js.map +1 -0
- package/dist-es/tabs-next/hooks/useOverflowSelectionState.js +58 -0
- package/dist-es/tabs-next/hooks/useOverflowSelectionState.js.map +1 -0
- package/dist-es/tabs-next/hooks/useRenderedTabWidth.js +90 -0
- package/dist-es/tabs-next/hooks/useRenderedTabWidth.js.map +1 -0
- package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js +198 -0
- package/dist-es/tabs-next/hooks/useRenderedTabsRegistry.js.map +1 -0
- package/dist-es/tabs-next/hooks/useTabListRecovery.js +74 -0
- package/dist-es/tabs-next/hooks/useTabListRecovery.js.map +1 -0
- package/dist-es/tabs-next/hooks/useTabRemovalHandler.js +163 -0
- package/dist-es/tabs-next/hooks/useTabRemovalHandler.js.map +1 -0
- package/dist-es/tabs-next/hooks/useTabSelectionFocus.js +78 -0
- package/dist-es/tabs-next/hooks/useTabSelectionFocus.js.map +1 -0
- package/dist-es/tabs-next/widthMeasurement.js +36 -0
- package/dist-es/tabs-next/widthMeasurement.js.map +1 -0
- package/dist-es/tree/Tree.css.js +1 -1
- package/dist-es/tree/TreeNode.css.js +1 -1
- package/dist-es/tree/TreeNode.js +1 -1
- package/dist-es/tree/TreeNode.js.map +1 -1
- package/dist-es/tree/TreeNodeExpansionIcon.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.js +2 -2
- package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
- package/dist-es/utils/useEventCallback.js +5 -5
- package/dist-es/utils/useEventCallback.js.map +1 -1
- package/dist-types/cascading-menu/internal/useMenuTriggerHandlers.d.ts +1 -1
- package/dist-types/list-deprecated/ListStateContext.d.ts +7 -2
- package/dist-types/tabs-next/TabListLayoutContext.d.ts +9 -0
- package/dist-types/tabs-next/TabNext.d.ts +1 -1
- package/dist-types/tabs-next/TabNextPanel.d.ts +2 -1
- package/dist-types/tabs-next/TabOverflowList.d.ts +3 -4
- package/dist-types/tabs-next/TabSlot.d.ts +6 -0
- package/dist-types/tabs-next/TabSlotRegistryContext.d.ts +5 -0
- package/dist-types/tabs-next/TabsNext.d.ts +2 -1
- package/dist-types/tabs-next/TabsNextContext.d.ts +26 -4
- package/dist-types/tabs-next/domUtils.d.ts +1 -0
- package/dist-types/tabs-next/hooks/overflowMath.d.ts +18 -0
- package/dist-types/tabs-next/hooks/useCollection.d.ts +15 -3
- package/dist-types/tabs-next/hooks/useFocusWithRetry.d.ts +9 -0
- package/dist-types/tabs-next/hooks/useOverflow.d.ts +5 -5
- package/dist-types/tabs-next/hooks/useOverflowLayoutState.d.ts +13 -0
- package/dist-types/tabs-next/hooks/useOverflowSelectionState.d.ts +13 -0
- package/dist-types/tabs-next/hooks/useRenderedTabWidth.d.ts +12 -0
- package/dist-types/tabs-next/hooks/useRenderedTabsRegistry.d.ts +12 -0
- package/dist-types/tabs-next/hooks/useTabListRecovery.d.ts +12 -0
- package/dist-types/tabs-next/hooks/useTabRemovalHandler.d.ts +32 -0
- package/dist-types/tabs-next/hooks/useTabSelectionFocus.d.ts +15 -0
- package/dist-types/tabs-next/widthMeasurement.d.ts +5 -0
- package/dist-types/utils/useEventCallback.d.ts +1 -1
- package/package.json +2 -2
- package/dist-cjs/tabs-next/hooks/useFocusOutside.js +0 -25
- package/dist-cjs/tabs-next/hooks/useFocusOutside.js.map +0 -1
- package/dist-cjs/tabs-next/hooks/useRestoreActiveTab.js +0 -93
- package/dist-cjs/tabs-next/hooks/useRestoreActiveTab.js.map +0 -1
- package/dist-es/tabs-next/hooks/useFocusOutside.js +0 -23
- package/dist-es/tabs-next/hooks/useFocusOutside.js.map +0 -1
- package/dist-es/tabs-next/hooks/useRestoreActiveTab.js +0 -91
- package/dist-es/tabs-next/hooks/useRestoreActiveTab.js.map +0 -1
- package/dist-types/tabs-next/hooks/useFocusOutside.d.ts +0 -2
- package/dist-types/tabs-next/hooks/useRestoreActiveTab.d.ts +0 -10
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { makePrefixer, useForkRef,
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { makePrefixer, useForkRef, useAriaAnnouncer, useIsomorphicLayoutEffect, capitalize } from '@salt-ds/core';
|
|
3
3
|
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
4
|
import { useWindow } from '@salt-ds/window';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
|
-
import { forwardRef, useRef } from 'react';
|
|
6
|
+
import { forwardRef, useRef, useState, useEffect, useCallback, useMemo } from 'react';
|
|
7
|
+
import { useFocusWithRetry } from './hooks/useFocusWithRetry.js';
|
|
7
8
|
import { useOverflow } from './hooks/useOverflow.js';
|
|
8
|
-
import {
|
|
9
|
+
import { useOverflowLayoutState } from './hooks/useOverflowLayoutState.js';
|
|
10
|
+
import { useTabListRecovery } from './hooks/useTabListRecovery.js';
|
|
11
|
+
import { useTabRemovalHandler } from './hooks/useTabRemovalHandler.js';
|
|
12
|
+
import { useTabSelectionFocus } from './hooks/useTabSelectionFocus.js';
|
|
13
|
+
import { TabListLayoutContext } from './TabListLayoutContext.js';
|
|
9
14
|
import css_248z from './TabListNext.css.js';
|
|
10
15
|
import { TabOverflowList } from './TabOverflowList.js';
|
|
16
|
+
import { TabSlot } from './TabSlot.js';
|
|
17
|
+
import { TabSlotRegistryContext } from './TabSlotRegistryContext.js';
|
|
11
18
|
import { useTabsNext } from './TabsNextContext.js';
|
|
12
19
|
|
|
13
20
|
const withBaseName = makePrefixer("saltTabListNext");
|
|
21
|
+
const MAX_FOCUS_RETRY_ATTEMPTS = 120;
|
|
14
22
|
const TabListNext = forwardRef(
|
|
15
|
-
function
|
|
23
|
+
function TabListNext2(props, ref) {
|
|
16
24
|
const {
|
|
17
25
|
appearance = "bordered",
|
|
18
26
|
activeColor = "primary",
|
|
19
|
-
"aria-describedby": ariaDescribedBy,
|
|
20
27
|
children,
|
|
21
28
|
className,
|
|
22
29
|
onKeyDown,
|
|
@@ -29,61 +36,185 @@ const TabListNext = forwardRef(
|
|
|
29
36
|
window: targetWindow
|
|
30
37
|
});
|
|
31
38
|
const {
|
|
39
|
+
renderMode,
|
|
32
40
|
selected,
|
|
41
|
+
setSelected,
|
|
42
|
+
setBootstrapOverflowReady,
|
|
33
43
|
getNext,
|
|
34
44
|
getPrevious,
|
|
35
45
|
getFirst,
|
|
36
46
|
getLast,
|
|
37
|
-
|
|
47
|
+
getIndex,
|
|
48
|
+
item,
|
|
49
|
+
itemAt,
|
|
38
50
|
activeTab,
|
|
51
|
+
selectionFromOverflowValueRef,
|
|
39
52
|
menuOpen,
|
|
40
53
|
setMenuOpen,
|
|
41
|
-
|
|
54
|
+
sortItems,
|
|
55
|
+
getRemovedItems,
|
|
56
|
+
getRenderedTab,
|
|
57
|
+
renderedTabs,
|
|
58
|
+
removalVersion
|
|
42
59
|
} = useTabsNext();
|
|
43
60
|
const tabstripRef = useRef(null);
|
|
61
|
+
const overflowListRef = useRef(null);
|
|
62
|
+
const slotMapRef = useRef(/* @__PURE__ */ new Map());
|
|
63
|
+
const removalRecoveryRafRef = useRef(null);
|
|
64
|
+
const pendingRemovalRecoveryRef = useRef(false);
|
|
65
|
+
const pendingRemovalRecoveryRetriesRef = useRef(0);
|
|
66
|
+
const [slotVersion, setSlotVersion] = useState(0);
|
|
44
67
|
const handleRef = useForkRef(tabstripRef, ref);
|
|
45
68
|
const overflowButtonRef = useRef(null);
|
|
46
|
-
const
|
|
69
|
+
const { announce } = useAriaAnnouncer();
|
|
70
|
+
const overflowMenuOpen = renderMode === "portal" ? menuOpen : false;
|
|
71
|
+
const [visibleValues, hiddenValues, isMeasuring] = useOverflow({
|
|
47
72
|
container: tabstripRef,
|
|
48
|
-
|
|
49
|
-
children,
|
|
73
|
+
menuOpen: overflowMenuOpen,
|
|
50
74
|
selected,
|
|
75
|
+
tabs: renderedTabs,
|
|
51
76
|
overflowButton: overflowButtonRef
|
|
52
77
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
setBootstrapOverflowReady(
|
|
80
|
+
renderMode === "inline" && renderedTabs.length > 0 && !isMeasuring
|
|
81
|
+
);
|
|
82
|
+
}, [
|
|
83
|
+
isMeasuring,
|
|
84
|
+
renderMode,
|
|
85
|
+
renderedTabs.length,
|
|
86
|
+
setBootstrapOverflowReady
|
|
87
|
+
]);
|
|
88
|
+
const { resolvedOverflowActiveValue, tabListLayoutContext } = useOverflowLayoutState({
|
|
89
|
+
hiddenValues,
|
|
90
|
+
menuOpen,
|
|
91
|
+
overflowMenuOpen,
|
|
92
|
+
visibleValues
|
|
58
93
|
});
|
|
94
|
+
const registerSlot = useCallback(
|
|
95
|
+
(slotId, element) => {
|
|
96
|
+
const currentElement = slotMapRef.current.get(slotId) ?? null;
|
|
97
|
+
if (currentElement === element) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (element) {
|
|
101
|
+
slotMapRef.current.set(slotId, element);
|
|
102
|
+
} else {
|
|
103
|
+
slotMapRef.current.delete(slotId);
|
|
104
|
+
}
|
|
105
|
+
setSlotVersion((currentVersion) => currentVersion + 1);
|
|
106
|
+
},
|
|
107
|
+
[]
|
|
108
|
+
);
|
|
109
|
+
const slotRegistryContext = useMemo(
|
|
110
|
+
() => ({ registerSlot }),
|
|
111
|
+
[registerSlot]
|
|
112
|
+
);
|
|
113
|
+
const slotAssignments = useMemo(() => {
|
|
114
|
+
const nextAssignments = /* @__PURE__ */ new Map();
|
|
115
|
+
for (const value of visibleValues) {
|
|
116
|
+
nextAssignments.set(value, `main:${value}`);
|
|
117
|
+
}
|
|
118
|
+
for (const value of hiddenValues) {
|
|
119
|
+
nextAssignments.set(
|
|
120
|
+
value,
|
|
121
|
+
menuOpen ? `overflow:${value}` : `measure:${value}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
map: nextAssignments,
|
|
126
|
+
version: slotVersion
|
|
127
|
+
};
|
|
128
|
+
}, [hiddenValues, menuOpen, slotVersion, visibleValues]);
|
|
129
|
+
useIsomorphicLayoutEffect(() => {
|
|
130
|
+
var _a;
|
|
131
|
+
if (renderMode !== "portal") {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
for (const [value, slotId] of slotAssignments.map) {
|
|
135
|
+
const host = (_a = getRenderedTab(value)) == null ? void 0 : _a.host;
|
|
136
|
+
const slot = slotMapRef.current.get(slotId);
|
|
137
|
+
if (host && slot && host.parentElement !== slot) {
|
|
138
|
+
slot.appendChild(host);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}, [getRenderedTab, renderMode, slotAssignments]);
|
|
59
142
|
const handleKeyDown = (event) => {
|
|
60
|
-
var _a, _b
|
|
143
|
+
var _a, _b;
|
|
61
144
|
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
145
|
+
if (menuOpen) return;
|
|
62
146
|
const actionMap = {
|
|
63
147
|
ArrowRight: getNext,
|
|
64
148
|
ArrowLeft: getPrevious,
|
|
65
149
|
Home: getFirst,
|
|
66
|
-
End: getLast
|
|
67
|
-
ArrowUp: menuOpen ? getPrevious : void 0,
|
|
68
|
-
ArrowDown: menuOpen ? getNext : void 0
|
|
150
|
+
End: getLast
|
|
69
151
|
};
|
|
70
152
|
const action = actionMap[event.key];
|
|
71
153
|
if (action) {
|
|
72
154
|
event.preventDefault();
|
|
155
|
+
sortItems();
|
|
73
156
|
const activeTabId = (_a = activeTab.current) == null ? void 0 : _a.id;
|
|
74
157
|
if (!activeTabId) return;
|
|
75
158
|
const nextItem = action(activeTabId);
|
|
76
159
|
if (nextItem) {
|
|
77
|
-
(
|
|
78
|
-
block: "nearest",
|
|
79
|
-
inline: "nearest"
|
|
80
|
-
});
|
|
81
|
-
(_d = nextItem.element) == null ? void 0 : _d.focus({ preventScroll: true });
|
|
160
|
+
(_b = nextItem.element) == null ? void 0 : _b.focus({ preventScroll: true });
|
|
82
161
|
}
|
|
83
162
|
}
|
|
84
163
|
};
|
|
85
|
-
const
|
|
86
|
-
|
|
164
|
+
const getSelectedTabElement = useCallback(() => {
|
|
165
|
+
var _a, _b, _c;
|
|
166
|
+
return ((_a = tabstripRef.current) == null ? void 0 : _a.querySelector(
|
|
167
|
+
'[role="tab"][aria-selected="true"]'
|
|
168
|
+
)) ?? ((_c = item((_b = activeTab.current) == null ? void 0 : _b.id)) == null ? void 0 : _c.element);
|
|
169
|
+
}, [item, activeTab]);
|
|
170
|
+
const { focusElementWithRetry } = useFocusWithRetry({
|
|
171
|
+
maxAttempts: MAX_FOCUS_RETRY_ATTEMPTS,
|
|
172
|
+
targetWindow
|
|
173
|
+
});
|
|
174
|
+
useTabSelectionFocus({
|
|
175
|
+
announce,
|
|
176
|
+
focusElementWithRetry,
|
|
177
|
+
getRenderedTab,
|
|
178
|
+
getSelectedTabElement,
|
|
179
|
+
menuOpen,
|
|
180
|
+
resolvedOverflowActiveValue,
|
|
181
|
+
selected,
|
|
182
|
+
selectionFromOverflowValueRef,
|
|
183
|
+
targetWindow
|
|
184
|
+
});
|
|
185
|
+
const handleTabRemoval = useTabRemovalHandler({
|
|
186
|
+
activeTab,
|
|
187
|
+
focusElementWithRetry,
|
|
188
|
+
getFirst,
|
|
189
|
+
getIndex,
|
|
190
|
+
getLast,
|
|
191
|
+
getRemovedItems,
|
|
192
|
+
getRenderedTab,
|
|
193
|
+
getSelectedTabElement,
|
|
194
|
+
item,
|
|
195
|
+
itemAt,
|
|
196
|
+
maxRetryAttempts: MAX_FOCUS_RETRY_ATTEMPTS,
|
|
197
|
+
menuOpen,
|
|
198
|
+
overflowButtonRef,
|
|
199
|
+
overflowListRef,
|
|
200
|
+
pendingRemovalRecoveryRef,
|
|
201
|
+
pendingRemovalRecoveryRetriesRef,
|
|
202
|
+
removalRecoveryRafRef,
|
|
203
|
+
selected,
|
|
204
|
+
setSelected,
|
|
205
|
+
tabstripRef,
|
|
206
|
+
targetWindow
|
|
207
|
+
});
|
|
208
|
+
useTabListRecovery({
|
|
209
|
+
removalVersion,
|
|
210
|
+
targetWindow,
|
|
211
|
+
tabstripRef,
|
|
212
|
+
overflowListRef,
|
|
213
|
+
handleTabRemoval,
|
|
214
|
+
pendingRemovalRecoveryRef,
|
|
215
|
+
pendingRemovalRecoveryRetriesRef
|
|
216
|
+
});
|
|
217
|
+
return /* @__PURE__ */ jsx(
|
|
87
218
|
"div",
|
|
88
219
|
{
|
|
89
220
|
role: "tablist",
|
|
@@ -94,26 +225,41 @@ const TabListNext = forwardRef(
|
|
|
94
225
|
withBaseName(`activeColor${capitalize(activeColor)}`),
|
|
95
226
|
className
|
|
96
227
|
),
|
|
97
|
-
"data-ismeasuring": isMeasuring ? true : void 0,
|
|
228
|
+
"data-ismeasuring": renderMode === "portal" && isMeasuring ? true : void 0,
|
|
98
229
|
ref: handleRef,
|
|
99
230
|
onKeyDown: handleKeyDown,
|
|
100
|
-
"aria-describedby": clsx(ariaDescribedBy, warningId) || void 0,
|
|
101
231
|
...rest,
|
|
102
|
-
children: [
|
|
103
|
-
|
|
104
|
-
|
|
232
|
+
children: renderMode === "inline" ? children : /* @__PURE__ */ jsx(TabSlotRegistryContext.Provider, { value: slotRegistryContext, children: /* @__PURE__ */ jsxs(TabListLayoutContext.Provider, { value: tabListLayoutContext, children: [
|
|
233
|
+
children,
|
|
234
|
+
visibleValues.map((value) => /* @__PURE__ */ jsx(TabSlot, { slotId: `main:${value}`, value }, value)),
|
|
235
|
+
!menuOpen && hiddenValues.length > 0 ? /* @__PURE__ */ jsx(
|
|
236
|
+
"div",
|
|
237
|
+
{
|
|
238
|
+
"aria-hidden": "true",
|
|
239
|
+
role: "presentation",
|
|
240
|
+
className: withBaseName("measureContainer"),
|
|
241
|
+
children: hiddenValues.map((value) => /* @__PURE__ */ jsx(
|
|
242
|
+
TabSlot,
|
|
243
|
+
{
|
|
244
|
+
slotId: `measure:${value}`,
|
|
245
|
+
value
|
|
246
|
+
},
|
|
247
|
+
`measure-${value}`
|
|
248
|
+
))
|
|
249
|
+
}
|
|
250
|
+
) : null,
|
|
105
251
|
/* @__PURE__ */ jsx(
|
|
106
252
|
TabOverflowList,
|
|
107
253
|
{
|
|
108
|
-
isMeasuring,
|
|
109
254
|
buttonRef: overflowButtonRef,
|
|
110
|
-
|
|
255
|
+
hiddenValues,
|
|
111
256
|
open: menuOpen,
|
|
257
|
+
order: renderedTabs.length,
|
|
112
258
|
setOpen: setMenuOpen,
|
|
113
|
-
|
|
259
|
+
ref: overflowListRef
|
|
114
260
|
}
|
|
115
261
|
)
|
|
116
|
-
]
|
|
262
|
+
] }) })
|
|
117
263
|
}
|
|
118
264
|
);
|
|
119
265
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabListNext.js","sources":["../src/tabs-next/TabListNext.tsx"],"sourcesContent":["import { capitalize, makePrefixer, useForkRef, useId } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type KeyboardEvent,\n useRef,\n} from \"react\";\nimport { useOverflow } from \"./hooks/useOverflow\";\nimport { useRestoreActiveTab } from \"./hooks/useRestoreActiveTab\";\nimport tablistNextCss from \"./TabListNext.css\";\nimport { TabOverflowList } from \"./TabOverflowList\";\nimport { useTabsNext } from \"./TabsNextContext\";\n\nconst withBaseName = makePrefixer(\"saltTabListNext\");\n\nexport interface TabListNextProps\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 TabListNext = forwardRef<HTMLDivElement, TabListNextProps>(\n function TabstripNext(props, ref) {\n const {\n appearance = \"bordered\",\n activeColor = \"primary\",\n \"aria-describedby\": ariaDescribedBy,\n children,\n className,\n onKeyDown,\n ...rest\n } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tablist-next\",\n css: tablistNextCss,\n window: targetWindow,\n });\n\n const {\n selected,\n getNext,\n getPrevious,\n getFirst,\n getLast,\n items,\n activeTab,\n menuOpen,\n setMenuOpen,\n removedActiveTabRef,\n } = useTabsNext();\n\n const tabstripRef = useRef<HTMLDivElement>(null);\n const handleRef = useForkRef(tabstripRef, ref);\n const overflowButtonRef = useRef<HTMLButtonElement>(null);\n\n const [visible, hidden, isMeasuring, realSelectedIndexRef] = useOverflow({\n container: tabstripRef,\n tabs: items,\n children,\n selected,\n overflowButton: overflowButtonRef,\n });\n\n useRestoreActiveTab({\n container: tabstripRef,\n tabs: items,\n realSelectedIndex: realSelectedIndexRef,\n removedActiveTabRef,\n });\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n const actionMap = {\n ArrowRight: getNext,\n ArrowLeft: getPrevious,\n Home: getFirst,\n End: getLast,\n ArrowUp: menuOpen ? getPrevious : undefined,\n ArrowDown: menuOpen ? getNext : undefined,\n };\n\n const action = actionMap[event.key as keyof typeof actionMap];\n\n if (action) {\n event.preventDefault();\n const activeTabId = activeTab.current?.id;\n if (!activeTabId) return;\n const nextItem = action(activeTabId);\n if (nextItem) {\n nextItem.element?.parentElement?.scrollIntoView({\n block: \"nearest\",\n inline: \"nearest\",\n });\n nextItem.element?.focus({ preventScroll: true });\n }\n }\n };\n\n const warningId = useId();\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={isMeasuring ? true : undefined}\n ref={handleRef}\n onKeyDown={handleKeyDown}\n aria-describedby={clsx(ariaDescribedBy, warningId) || undefined}\n {...rest}\n >\n {!isMeasuring && hidden.length > 0 && (\n <span id={warningId} className={withBaseName(\"overflowWarning\")}>\n Note: This tab list includes overflow; tab positions may be\n inaccurate or change when a tab is selected\n </span>\n )}\n {visible}\n <TabOverflowList\n isMeasuring={isMeasuring}\n buttonRef={overflowButtonRef}\n tabstripRef={tabstripRef}\n open={menuOpen}\n setOpen={setMenuOpen}\n >\n {hidden}\n </TabOverflowList>\n </div>\n );\n },\n);\n"],"names":["tablistNextCss"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TabListNext.js","sources":["../src/tabs-next/TabListNext.tsx"],"sourcesContent":["import {\n capitalize,\n makePrefixer,\n useAriaAnnouncer,\n useForkRef,\n useIsomorphicLayoutEffect,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useFocusWithRetry } from \"./hooks/useFocusWithRetry\";\nimport { useOverflow } from \"./hooks/useOverflow\";\nimport { useOverflowLayoutState } from \"./hooks/useOverflowLayoutState\";\nimport { useTabListRecovery } from \"./hooks/useTabListRecovery\";\nimport { useTabRemovalHandler } from \"./hooks/useTabRemovalHandler\";\nimport { useTabSelectionFocus } from \"./hooks/useTabSelectionFocus\";\nimport { TabListLayoutContext } from \"./TabListLayoutContext\";\nimport tablistNextCss from \"./TabListNext.css\";\nimport { TabOverflowList } from \"./TabOverflowList\";\nimport { TabSlot } from \"./TabSlot\";\nimport { TabSlotRegistryContext } from \"./TabSlotRegistryContext\";\nimport { useTabsNext } from \"./TabsNextContext\";\n\nconst withBaseName = makePrefixer(\"saltTabListNext\");\nconst MAX_FOCUS_RETRY_ATTEMPTS = 120;\n\nexport interface TabListNextProps\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 TabListNext = forwardRef<HTMLDivElement, TabListNextProps>(\n function TabListNext(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-tablist-next\",\n css: tablistNextCss,\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 } = useTabsNext();\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":["TabListNext","tablistNextCss"],"mappings":"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"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { makePrefixer, useId } from '@salt-ds/core';
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { makePrefixer, useId, useIsomorphicLayoutEffect, useForkRef } from '@salt-ds/core';
|
|
3
3
|
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
4
4
|
import { useWindow } from '@salt-ds/window';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
6
|
import { forwardRef, useRef, useState, useCallback, useMemo } from 'react';
|
|
7
|
+
import { createPortal } from 'react-dom';
|
|
8
|
+
import { useRenderedTabWidth } from './hooks/useRenderedTabWidth.js';
|
|
7
9
|
import css_248z from './TabNext.css.js';
|
|
8
10
|
import { TabNextContext } from './TabNextContext.js';
|
|
9
11
|
import { useTabsNext } from './TabsNextContext.js';
|
|
12
|
+
import { getIntrinsicMeasuredWidth } from './widthMeasurement.js';
|
|
10
13
|
|
|
11
14
|
const withBaseName = makePrefixer("saltTabNext");
|
|
12
15
|
const TabNext = forwardRef(
|
|
@@ -29,15 +32,26 @@ const TabNext = forwardRef(
|
|
|
29
32
|
css: css_248z,
|
|
30
33
|
window: targetWindow
|
|
31
34
|
});
|
|
32
|
-
const {
|
|
35
|
+
const {
|
|
36
|
+
selected,
|
|
37
|
+
activeTab,
|
|
38
|
+
renderMode,
|
|
39
|
+
registerBootstrapTab,
|
|
40
|
+
setBootstrapTabReady,
|
|
41
|
+
registerRenderedTab,
|
|
42
|
+
updateRenderedTab
|
|
43
|
+
} = useTabsNext();
|
|
33
44
|
const disabled = !!disabledProp;
|
|
34
45
|
const id = useId(idProp);
|
|
35
46
|
const wasMouseDown = useRef(false);
|
|
36
47
|
const [focusVisible, setFocusVisible] = useState(false);
|
|
37
48
|
const [focused, setFocused] = useState(false);
|
|
49
|
+
const [hostElement, setHostElement] = useState(null);
|
|
50
|
+
const markerRef = useRef(null);
|
|
51
|
+
const tabRootRef = useRef(null);
|
|
38
52
|
const handleFocusCapture = (event) => {
|
|
39
53
|
onFocusCapture == null ? void 0 : onFocusCapture(event);
|
|
40
|
-
if (
|
|
54
|
+
if (id) {
|
|
41
55
|
activeTab.current = { value, id };
|
|
42
56
|
}
|
|
43
57
|
};
|
|
@@ -56,15 +70,33 @@ const TabNext = forwardRef(
|
|
|
56
70
|
};
|
|
57
71
|
const handleMouseDown = (event) => {
|
|
58
72
|
onMouseDown == null ? void 0 : onMouseDown(event);
|
|
73
|
+
if (id) {
|
|
74
|
+
activeTab.current = { value, id };
|
|
75
|
+
}
|
|
59
76
|
wasMouseDown.current = true;
|
|
60
77
|
};
|
|
61
|
-
const [
|
|
78
|
+
const [actionIds, setActionIds] = useState(() => /* @__PURE__ */ new Set());
|
|
62
79
|
const registerAction = useCallback((id2) => {
|
|
63
|
-
|
|
80
|
+
setActionIds((old) => {
|
|
81
|
+
if (old.has(id2)) {
|
|
82
|
+
return old;
|
|
83
|
+
}
|
|
84
|
+
const next = new Set(old);
|
|
85
|
+
next.add(id2);
|
|
86
|
+
return next;
|
|
87
|
+
});
|
|
64
88
|
return () => {
|
|
65
|
-
|
|
89
|
+
setActionIds((old) => {
|
|
90
|
+
if (!old.has(id2)) {
|
|
91
|
+
return old;
|
|
92
|
+
}
|
|
93
|
+
const next = new Set(old);
|
|
94
|
+
next.delete(id2);
|
|
95
|
+
return next;
|
|
96
|
+
});
|
|
66
97
|
};
|
|
67
98
|
}, []);
|
|
99
|
+
const actions = useMemo(() => Array.from(actionIds), [actionIds]);
|
|
68
100
|
const context = useMemo(
|
|
69
101
|
() => ({
|
|
70
102
|
tabId: id,
|
|
@@ -77,7 +109,66 @@ const TabNext = forwardRef(
|
|
|
77
109
|
}),
|
|
78
110
|
[id, selected, value, focused, disabled, actions, registerAction]
|
|
79
111
|
);
|
|
80
|
-
|
|
112
|
+
useIsomorphicLayoutEffect(() => {
|
|
113
|
+
const doc = targetWindow == null ? void 0 : targetWindow.document;
|
|
114
|
+
if (!doc) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const host = doc.createElement("div");
|
|
118
|
+
host.dataset.tabHost = value;
|
|
119
|
+
host.role = "presentation";
|
|
120
|
+
host.style.display = "contents";
|
|
121
|
+
setHostElement(host);
|
|
122
|
+
return () => {
|
|
123
|
+
host.remove();
|
|
124
|
+
};
|
|
125
|
+
}, [targetWindow, value]);
|
|
126
|
+
useIsomorphicLayoutEffect(() => {
|
|
127
|
+
if (renderMode !== "inline") {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
return registerBootstrapTab(value);
|
|
131
|
+
}, [registerBootstrapTab, renderMode, value]);
|
|
132
|
+
useIsomorphicLayoutEffect(() => {
|
|
133
|
+
setBootstrapTabReady(value, hostElement != null);
|
|
134
|
+
return () => {
|
|
135
|
+
setBootstrapTabReady(value, false);
|
|
136
|
+
};
|
|
137
|
+
}, [hostElement, setBootstrapTabReady, value]);
|
|
138
|
+
useIsomorphicLayoutEffect(() => {
|
|
139
|
+
if (!hostElement || !id) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
return registerRenderedTab({
|
|
143
|
+
host: hostElement,
|
|
144
|
+
id,
|
|
145
|
+
marker: markerRef.current,
|
|
146
|
+
root: tabRootRef.current,
|
|
147
|
+
trigger: null,
|
|
148
|
+
value,
|
|
149
|
+
width: getIntrinsicMeasuredWidth(tabRootRef.current)
|
|
150
|
+
});
|
|
151
|
+
}, [hostElement, id, registerRenderedTab, value]);
|
|
152
|
+
useIsomorphicLayoutEffect(() => {
|
|
153
|
+
const updates = {
|
|
154
|
+
marker: markerRef.current,
|
|
155
|
+
root: tabRootRef.current
|
|
156
|
+
};
|
|
157
|
+
if (renderMode === "inline") {
|
|
158
|
+
updates.width = getIntrinsicMeasuredWidth(tabRootRef.current);
|
|
159
|
+
}
|
|
160
|
+
updateRenderedTab(value, updates);
|
|
161
|
+
}, [renderMode, updateRenderedTab, value]);
|
|
162
|
+
useRenderedTabWidth({
|
|
163
|
+
hostElement,
|
|
164
|
+
renderMode,
|
|
165
|
+
tabRootRef,
|
|
166
|
+
targetWindow,
|
|
167
|
+
updateRenderedTab,
|
|
168
|
+
value
|
|
169
|
+
});
|
|
170
|
+
const handleTabRootRef = useForkRef(tabRootRef, ref);
|
|
171
|
+
const tabMarkup = /* @__PURE__ */ jsx(TabNextContext.Provider, { value: context, children: /* @__PURE__ */ jsx(
|
|
81
172
|
"div",
|
|
82
173
|
{
|
|
83
174
|
className: clsx(
|
|
@@ -90,7 +181,8 @@ const TabNext = forwardRef(
|
|
|
90
181
|
className
|
|
91
182
|
),
|
|
92
183
|
"data-overflowitem": "true",
|
|
93
|
-
|
|
184
|
+
"data-value": value,
|
|
185
|
+
ref: handleTabRootRef,
|
|
94
186
|
onMouseDown: handleMouseDown,
|
|
95
187
|
onFocusCapture: handleFocusCapture,
|
|
96
188
|
onFocus: handleFocus,
|
|
@@ -100,6 +192,18 @@ const TabNext = forwardRef(
|
|
|
100
192
|
children
|
|
101
193
|
}
|
|
102
194
|
) });
|
|
195
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
196
|
+
/* @__PURE__ */ jsx(
|
|
197
|
+
"span",
|
|
198
|
+
{
|
|
199
|
+
role: "presentation",
|
|
200
|
+
"data-tabnext-marker": "",
|
|
201
|
+
hidden: true,
|
|
202
|
+
ref: markerRef
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
renderMode === "inline" ? tabMarkup : hostElement ? createPortal(tabMarkup, hostElement) : null
|
|
206
|
+
] });
|
|
103
207
|
}
|
|
104
208
|
);
|
|
105
209
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabNext.js","sources":["../src/tabs-next/TabNext.tsx"],"sourcesContent":["import { makePrefixer, useId } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type MouseEvent,\n type ReactElement,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport tabCss from \"./TabNext.css\";\nimport { TabNextContext } from \"./TabNextContext\";\nimport { useTabsNext } from \"./TabsNextContext\";\n\nconst withBaseName = makePrefixer(\"saltTabNext\");\n\nexport interface TabNextProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * If `true`, the tab will be disabled.\n */\n disabled?: boolean;\n /**\n * The value of the tab.\n */\n value: string;\n}\n\nexport const TabNext = forwardRef<HTMLDivElement, TabNextProps>(\n function Tab(props, ref): ReactElement<TabNextProps> {\n const {\n children,\n className,\n disabled: disabledProp,\n onBlur,\n onMouseDown,\n onFocus,\n onFocusCapture,\n value,\n id: idProp,\n ...rest\n } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tab-next\",\n css: tabCss,\n window: targetWindow,\n });\n\n const { selected, activeTab } = useTabsNext();\n\n const disabled = !!disabledProp;\n\n const id = useId(idProp);\n\n const wasMouseDown = useRef(false);\n const [focusVisible, setFocusVisible] = useState(false);\n const [focused, setFocused] = useState(false);\n\n const handleFocusCapture = (event: FocusEvent<HTMLDivElement>) => {\n onFocusCapture?.(event);\n if (value && id) {\n activeTab.current = { value, id };\n }\n };\n\n const handleFocus = (event: FocusEvent<HTMLDivElement>) => {\n onFocus?.(event);\n\n setFocused(true);\n\n if (\n !wasMouseDown.current &&\n event.target.getAttribute(\"role\") === \"tab\"\n ) {\n setFocusVisible(true);\n }\n\n wasMouseDown.current = false;\n };\n\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n onBlur?.(event);\n setFocused(false);\n setFocusVisible(false);\n };\n\n const handleMouseDown = (event: MouseEvent<HTMLDivElement>) => {\n onMouseDown?.(event);\n wasMouseDown.current = true;\n };\n\n const [actions, setActions] = useState<string[]>([]);\n\n const registerAction = useCallback((id: string) => {\n setActions((old) => old.concat(id));\n\n return () => {\n setActions((old) => old.filter((action) => action !== id));\n };\n }, []);\n\n const context = useMemo(\n () => ({\n tabId: id,\n selected: selected === value,\n focused,\n value,\n disabled,\n actions,\n registerAction,\n }),\n [id, selected, value, focused, disabled, actions, registerAction],\n );\n\n return (\n <TabNextContext.Provider value={context}>\n <div\n className={clsx(\n withBaseName(),\n {\n [withBaseName(\"selected\")]: selected === value,\n [withBaseName(\"disabled\")]: disabled,\n [withBaseName(\"focusVisible\")]: focusVisible,\n },\n className,\n )}\n data-overflowitem=\"true\"\n ref={ref}\n onMouseDown={handleMouseDown}\n onFocusCapture={handleFocusCapture}\n onFocus={handleFocus}\n onBlur={handleBlur}\n role=\"presentation\"\n {...rest}\n >\n {children}\n </div>\n </TabNextContext.Provider>\n );\n },\n);\n"],"names":["tabCss","id"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TabNext.js","sources":["../src/tabs-next/TabNext.tsx"],"sourcesContent":["import {\n makePrefixer,\n useForkRef,\n useId,\n useIsomorphicLayoutEffect,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type MouseEvent,\n type ReactElement,\n useCallback,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { useRenderedTabWidth } from \"./hooks/useRenderedTabWidth\";\nimport tabCss from \"./TabNext.css\";\nimport { TabNextContext } from \"./TabNextContext\";\nimport { useTabsNext } from \"./TabsNextContext\";\nimport { getIntrinsicMeasuredWidth } from \"./widthMeasurement\";\n\nconst withBaseName = makePrefixer(\"saltTabNext\");\n\nexport interface TabNextProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * If `true`, the tab will be disabled.\n */\n disabled?: boolean;\n /**\n * The value of the tab. This must be unique within a `TabsNext` instance.\n */\n value: string;\n}\n\nexport const TabNext = forwardRef<HTMLDivElement, TabNextProps>(\n function Tab(props, ref): ReactElement<TabNextProps> {\n const {\n children,\n className,\n disabled: disabledProp,\n onBlur,\n onMouseDown,\n onFocus,\n onFocusCapture,\n value,\n id: idProp,\n ...rest\n } = props;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tab-next\",\n css: tabCss,\n window: targetWindow,\n });\n\n const {\n selected,\n activeTab,\n renderMode,\n registerBootstrapTab,\n setBootstrapTabReady,\n registerRenderedTab,\n updateRenderedTab,\n } = useTabsNext();\n\n const disabled = !!disabledProp;\n\n const id = useId(idProp);\n\n const wasMouseDown = useRef(false);\n const [focusVisible, setFocusVisible] = useState(false);\n const [focused, setFocused] = useState(false);\n const [hostElement, setHostElement] = useState<HTMLDivElement | null>(null);\n const markerRef = useRef<HTMLSpanElement>(null);\n const tabRootRef = useRef<HTMLDivElement>(null);\n\n const handleFocusCapture = (event: FocusEvent<HTMLDivElement>) => {\n onFocusCapture?.(event);\n if (id) {\n activeTab.current = { value, id };\n }\n };\n\n const handleFocus = (event: FocusEvent<HTMLDivElement>) => {\n onFocus?.(event);\n\n setFocused(true);\n\n if (\n !wasMouseDown.current &&\n event.target.getAttribute(\"role\") === \"tab\"\n ) {\n setFocusVisible(true);\n }\n\n wasMouseDown.current = false;\n };\n\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n onBlur?.(event);\n setFocused(false);\n setFocusVisible(false);\n };\n\n const handleMouseDown = (event: MouseEvent<HTMLDivElement>) => {\n onMouseDown?.(event);\n if (id) {\n activeTab.current = { value, id };\n }\n wasMouseDown.current = true;\n };\n\n const [actionIds, setActionIds] = useState(() => new Set<string>());\n\n const registerAction = useCallback((id: string) => {\n setActionIds((old) => {\n if (old.has(id)) {\n return old;\n }\n\n const next = new Set(old);\n next.add(id);\n return next;\n });\n\n return () => {\n setActionIds((old) => {\n if (!old.has(id)) {\n return old;\n }\n\n const next = new Set(old);\n next.delete(id);\n return next;\n });\n };\n }, []);\n\n const actions = useMemo(() => Array.from(actionIds), [actionIds]);\n\n const context = useMemo(\n () => ({\n tabId: id,\n selected: selected === value,\n focused,\n value,\n disabled,\n actions,\n registerAction,\n }),\n [id, selected, value, focused, disabled, actions, registerAction],\n );\n\n useIsomorphicLayoutEffect(() => {\n const doc = targetWindow?.document;\n if (!doc) {\n return;\n }\n\n const host = doc.createElement(\"div\");\n host.dataset.tabHost = value;\n host.role = \"presentation\";\n host.style.display = \"contents\";\n setHostElement(host);\n\n return () => {\n host.remove();\n };\n }, [targetWindow, value]);\n\n useIsomorphicLayoutEffect(() => {\n if (renderMode !== \"inline\") {\n return;\n }\n\n return registerBootstrapTab(value);\n }, [registerBootstrapTab, renderMode, value]);\n\n useIsomorphicLayoutEffect(() => {\n setBootstrapTabReady(value, hostElement != null);\n\n return () => {\n setBootstrapTabReady(value, false);\n };\n }, [hostElement, setBootstrapTabReady, value]);\n\n useIsomorphicLayoutEffect(() => {\n if (!hostElement || !id) {\n return;\n }\n\n return registerRenderedTab({\n host: hostElement,\n id,\n marker: markerRef.current,\n root: tabRootRef.current,\n trigger: null,\n value,\n width: getIntrinsicMeasuredWidth(tabRootRef.current),\n });\n }, [hostElement, id, registerRenderedTab, value]);\n\n useIsomorphicLayoutEffect(() => {\n const updates = {\n marker: markerRef.current,\n root: tabRootRef.current,\n } as Partial<{\n host: HTMLDivElement;\n id: string;\n marker: HTMLElement | null;\n root: HTMLElement | null;\n trigger: HTMLButtonElement | null;\n width: number;\n }>;\n\n if (renderMode === \"inline\") {\n updates.width = getIntrinsicMeasuredWidth(tabRootRef.current);\n }\n\n updateRenderedTab(value, updates);\n }, [renderMode, updateRenderedTab, value]);\n\n useRenderedTabWidth({\n hostElement,\n renderMode,\n tabRootRef,\n targetWindow,\n updateRenderedTab,\n value,\n });\n\n const handleTabRootRef = useForkRef(tabRootRef, ref);\n\n const tabMarkup = (\n <TabNextContext.Provider value={context}>\n <div\n className={clsx(\n withBaseName(),\n {\n [withBaseName(\"selected\")]: selected === value,\n [withBaseName(\"disabled\")]: disabled,\n [withBaseName(\"focusVisible\")]: focusVisible,\n },\n className,\n )}\n data-overflowitem=\"true\"\n data-value={value}\n ref={handleTabRootRef}\n onMouseDown={handleMouseDown}\n onFocusCapture={handleFocusCapture}\n onFocus={handleFocus}\n onBlur={handleBlur}\n role=\"presentation\"\n {...rest}\n >\n {children}\n </div>\n </TabNextContext.Provider>\n );\n\n return (\n <>\n <span\n role=\"presentation\"\n data-tabnext-marker=\"\"\n hidden\n ref={markerRef}\n />\n {renderMode === \"inline\"\n ? tabMarkup\n : hostElement\n ? createPortal(tabMarkup, hostElement)\n : null}\n </>\n );\n },\n);\n"],"names":["tabCss","id"],"mappings":"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"}
|
|
@@ -3,17 +3,38 @@ import { useId, useIsomorphicLayoutEffect, Button } from '@salt-ds/core';
|
|
|
3
3
|
import { clsx } from 'clsx';
|
|
4
4
|
import { forwardRef } from 'react';
|
|
5
5
|
import { useTabNext } from './TabNextContext.js';
|
|
6
|
+
import { useTabsNext } from './TabsNextContext.js';
|
|
6
7
|
|
|
7
8
|
const TabNextAction = forwardRef(
|
|
8
9
|
function TabNextAction2(props, ref) {
|
|
9
|
-
const {
|
|
10
|
+
const {
|
|
11
|
+
"aria-labelledby": ariaLabelledBy,
|
|
12
|
+
id: idProp,
|
|
13
|
+
onFocus,
|
|
14
|
+
onMouseDown,
|
|
15
|
+
...rest
|
|
16
|
+
} = props;
|
|
10
17
|
const id = useId(idProp);
|
|
11
|
-
const { focused, selected, tabId, registerAction } = useTabNext();
|
|
18
|
+
const { focused, selected, tabId, registerAction, value } = useTabNext();
|
|
19
|
+
const { activeTab } = useTabsNext();
|
|
12
20
|
useIsomorphicLayoutEffect(() => {
|
|
13
21
|
if (id) {
|
|
14
22
|
return registerAction(id);
|
|
15
23
|
}
|
|
16
24
|
}, [registerAction, id]);
|
|
25
|
+
const setActiveTab = () => {
|
|
26
|
+
if (tabId) {
|
|
27
|
+
activeTab.current = { id: tabId, value };
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const handleFocus = (event) => {
|
|
31
|
+
onFocus == null ? void 0 : onFocus(event);
|
|
32
|
+
setActiveTab();
|
|
33
|
+
};
|
|
34
|
+
const handleMouseDown = (event) => {
|
|
35
|
+
onMouseDown == null ? void 0 : onMouseDown(event);
|
|
36
|
+
setActiveTab();
|
|
37
|
+
};
|
|
17
38
|
return /* @__PURE__ */ jsx(
|
|
18
39
|
Button,
|
|
19
40
|
{
|
|
@@ -23,6 +44,8 @@ const TabNextAction = forwardRef(
|
|
|
23
44
|
appearance: "transparent",
|
|
24
45
|
sentiment: "neutral",
|
|
25
46
|
ref,
|
|
47
|
+
onFocus: handleFocus,
|
|
48
|
+
onMouseDown: handleMouseDown,
|
|
26
49
|
...rest
|
|
27
50
|
}
|
|
28
51
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabNextAction.js","sources":["../src/tabs-next/TabNextAction.tsx"],"sourcesContent":["import {\n Button,\n type ButtonProps,\n useId,\n useIsomorphicLayoutEffect,\n} from \"@salt-ds/core\";\nimport { clsx } from \"clsx\";\nimport { forwardRef } from \"react\";\nimport { useTabNext } from \"./TabNextContext\";\n\nexport interface TabNextActionProps extends ButtonProps {}\n\nexport const TabNextAction = forwardRef<HTMLButtonElement, TabNextActionProps>(\n function TabNextAction(props, ref) {\n const {
|
|
1
|
+
{"version":3,"file":"TabNextAction.js","sources":["../src/tabs-next/TabNextAction.tsx"],"sourcesContent":["import {\n Button,\n type ButtonProps,\n useId,\n useIsomorphicLayoutEffect,\n} from \"@salt-ds/core\";\nimport { clsx } from \"clsx\";\nimport { type FocusEvent, forwardRef, type MouseEvent } from \"react\";\nimport { useTabNext } from \"./TabNextContext\";\nimport { useTabsNext } from \"./TabsNextContext\";\n\nexport interface TabNextActionProps extends ButtonProps {}\n\nexport const TabNextAction = forwardRef<HTMLButtonElement, TabNextActionProps>(\n function TabNextAction(props, ref) {\n const {\n \"aria-labelledby\": ariaLabelledBy,\n id: idProp,\n onFocus,\n onMouseDown,\n ...rest\n } = props;\n\n const id = useId(idProp);\n const { focused, selected, tabId, registerAction, value } = useTabNext();\n const { activeTab } = useTabsNext();\n\n useIsomorphicLayoutEffect(() => {\n if (id) {\n return registerAction(id);\n }\n }, [registerAction, id]);\n\n const setActiveTab = () => {\n if (tabId) {\n activeTab.current = { id: tabId, value };\n }\n };\n\n const handleFocus = (event: FocusEvent<HTMLButtonElement>) => {\n onFocus?.(event);\n setActiveTab();\n };\n\n const handleMouseDown = (event: MouseEvent<HTMLButtonElement>) => {\n onMouseDown?.(event);\n setActiveTab();\n };\n\n return (\n <Button\n id={id}\n aria-labelledby={clsx(ariaLabelledBy, tabId, id)}\n tabIndex={focused || selected ? undefined : -1}\n appearance=\"transparent\"\n sentiment=\"neutral\"\n ref={ref}\n onFocus={handleFocus}\n onMouseDown={handleMouseDown}\n {...rest}\n />\n );\n },\n);\n"],"names":["TabNextAction"],"mappings":";;;;;;;AAaO,MAAM,aAAA,GAAgB,UAAA;AAAA,EAC3B,SAASA,cAAAA,CAAc,KAAA,EAAO,GAAA,EAAK;AACjC,IAAA,MAAM;AAAA,MACJ,iBAAA,EAAmB,cAAA;AAAA,MACnB,EAAA,EAAI,MAAA;AAAA,MACJ,OAAA;AAAA,MACA,WAAA;AAAA,MACA,GAAG;AAAA,KACL,GAAI,KAAA;AAEJ,IAAA,MAAM,EAAA,GAAK,MAAM,MAAM,CAAA;AACvB,IAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,OAAO,cAAA,EAAgB,KAAA,KAAU,UAAA,EAAW;AACvE,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,WAAA,EAAY;AAElC,IAAA,yBAAA,CAA0B,MAAM;AAC9B,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,OAAO,eAAe,EAAE,CAAA;AAAA,MAC1B;AAAA,IACF,CAAA,EAAG,CAAC,cAAA,EAAgB,EAAE,CAAC,CAAA;AAEvB,IAAA,MAAM,eAAe,MAAM;AACzB,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,SAAA,CAAU,OAAA,GAAU,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAM;AAAA,MACzC;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAyC;AAC5D,MAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAU,KAAA,CAAA;AACV,MAAA,YAAA,EAAa;AAAA,IACf,CAAA;AAEA,IAAA,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAyC;AAChE,MAAA,WAAA,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAc,KAAA,CAAA;AACd,MAAA,YAAA,EAAa;AAAA,IACf,CAAA;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,EAAA;AAAA,QACA,iBAAA,EAAiB,IAAA,CAAK,cAAA,EAAgB,KAAA,EAAO,EAAE,CAAA;AAAA,QAC/C,QAAA,EAAU,OAAA,IAAW,QAAA,GAAW,MAAA,GAAY,EAAA;AAAA,QAC5C,UAAA,EAAW,aAAA;AAAA,QACX,SAAA,EAAU,SAAA;AAAA,QACV,GAAA;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,WAAA,EAAa,eAAA;AAAA,QACZ,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF;;;;"}
|