@redocly/theme 0.58.0 → 0.59.0-next.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/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +1 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +1 -1
- package/lib/components/Panel/variables.js +1 -0
- package/lib/components/Tag/Tag.d.ts +3 -2
- package/lib/components/Tag/Tag.js +21 -5
- package/lib/components/Tag/variables.dark.js +135 -0
- package/lib/components/Tag/variables.js +120 -58
- package/lib/core/hooks/use-tabs.d.ts +11 -6
- package/lib/core/hooks/use-tabs.js +117 -207
- package/lib/core/utils/index.d.ts +1 -0
- package/lib/core/utils/index.js +1 -0
- package/lib/core/utils/tabs.d.ts +1 -0
- package/lib/core/utils/tabs.js +8 -0
- package/lib/markdoc/components/Tabs/Tab.js +1 -1
- package/lib/markdoc/components/Tabs/TabList.d.ts +2 -14
- package/lib/markdoc/components/Tabs/TabList.js +63 -16
- package/lib/markdoc/components/Tabs/Tabs.d.ts +2 -2
- package/lib/markdoc/components/Tabs/Tabs.js +11 -87
- package/lib/markdoc/tags/tabs.js +5 -0
- package/package.json +3 -3
- package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
- package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
- package/src/components/Panel/variables.ts +1 -0
- package/src/components/Tag/Tag.tsx +33 -8
- package/src/components/Tag/variables.dark.ts +135 -0
- package/src/components/Tag/variables.ts +120 -58
- package/src/core/hooks/use-tabs.ts +160 -238
- package/src/core/utils/index.ts +1 -0
- package/src/core/utils/tabs.ts +4 -0
- package/src/markdoc/components/Tabs/Tab.tsx +1 -0
- package/src/markdoc/components/Tabs/TabList.tsx +84 -30
- package/src/markdoc/components/Tabs/Tabs.tsx +12 -125
- package/src/markdoc/tags/tabs.ts +5 -0
|
@@ -1,98 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useActiveTab = void 0;
|
|
3
4
|
exports.useTabs = useTabs;
|
|
4
5
|
const react_1 = require("react");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const [
|
|
6
|
+
const react_router_dom_1 = require("react-router-dom");
|
|
7
|
+
const MORE_BUTTON_WIDTH = 80;
|
|
8
|
+
const TABS_GAP = 8;
|
|
9
|
+
function useTabs({ activeTab, onTabChange, totalTabs, containerRef }) {
|
|
10
|
+
const [tabs, setTabs] = (0, react_1.useState)({
|
|
11
|
+
visible: Array.from({ length: totalTabs }, (_, i) => i),
|
|
12
|
+
overflow: [],
|
|
13
|
+
});
|
|
10
14
|
const tabRefs = (0, react_1.useRef)([]);
|
|
15
|
+
const tabWidthsRef = (0, react_1.useRef)([]);
|
|
11
16
|
const tabLabelsRef = (0, react_1.useRef)([]);
|
|
12
|
-
const
|
|
13
|
-
const [ready, setReady] = (0, react_1.useState)(false);
|
|
14
|
-
const hasCalculatedOnce = (0, react_1.useRef)(false);
|
|
15
|
-
const lastWidthRef = (0, react_1.useRef)(0);
|
|
16
|
-
const originalOrderRef = (0, react_1.useRef)([]);
|
|
17
|
-
(0, react_1.useEffect)(() => {
|
|
18
|
-
originalOrderRef.current = Array.from({ length: totalTabs }, (_, i) => i);
|
|
19
|
-
}, [totalTabs]);
|
|
17
|
+
const allTabsHidden = (0, react_1.useMemo)(() => tabs.visible.length === 0, [tabs.visible]);
|
|
20
18
|
const setTabRef = (0, react_1.useCallback)((element, index) => {
|
|
21
19
|
tabRefs.current[index] = element;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
const width = element === null || element === void 0 ? void 0 : element.offsetWidth;
|
|
21
|
+
if (width) {
|
|
22
|
+
tabWidthsRef.current[index] = width;
|
|
23
|
+
}
|
|
24
|
+
const label = element === null || element === void 0 ? void 0 : element.getAttribute('data-label');
|
|
25
|
+
if (label) {
|
|
26
|
+
tabLabelsRef.current[index] = label;
|
|
27
27
|
}
|
|
28
|
-
}, []);
|
|
29
|
-
const getTabId = (0, react_1.useCallback)((label, index) => {
|
|
30
|
-
const cleanLabel = label.replace(/\s+/g, '-').toLowerCase();
|
|
31
|
-
return `${cleanLabel}-${index}`;
|
|
32
28
|
}, []);
|
|
33
29
|
const focusTab = (index) => {
|
|
34
30
|
const currentElement = tabRefs.current[index];
|
|
35
|
-
|
|
36
|
-
currentElement.focus();
|
|
37
|
-
}
|
|
31
|
+
currentElement === null || currentElement === void 0 ? void 0 : currentElement.focus();
|
|
38
32
|
};
|
|
39
33
|
const onTabSelect = (0, react_1.useCallback)((index) => {
|
|
40
34
|
var _a;
|
|
41
35
|
focusTab(index);
|
|
42
36
|
const label = (_a = tabRefs.current[index]) === null || _a === void 0 ? void 0 : _a.getAttribute('data-label');
|
|
43
37
|
if (label)
|
|
44
|
-
|
|
45
|
-
}, []);
|
|
46
|
-
const onTabClick = (0, react_1.useCallback)((labelOrIndex) => {
|
|
47
|
-
var _a;
|
|
48
|
-
let clickedIndex;
|
|
49
|
-
if (typeof labelOrIndex === 'string') {
|
|
50
|
-
clickedIndex = tabRefs.current.findIndex((ref) => (ref === null || ref === void 0 ? void 0 : ref.getAttribute('data-label')) === labelOrIndex);
|
|
51
|
-
if (clickedIndex === -1)
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
clickedIndex = labelOrIndex;
|
|
56
|
-
}
|
|
57
|
-
if (allTabsHidden) {
|
|
58
|
-
const label = tabLabelsRef.current[clickedIndex];
|
|
59
|
-
if (label) {
|
|
60
|
-
setActiveTab(label);
|
|
61
|
-
focusTab(clickedIndex);
|
|
62
|
-
}
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (overflowTabs.includes(clickedIndex)) {
|
|
66
|
-
const newVisibleTabs = [...visibleTabs];
|
|
67
|
-
const newOverflowTabs = [...overflowTabs];
|
|
68
|
-
const clickedIdxInOverflow = newOverflowTabs.indexOf(clickedIndex);
|
|
69
|
-
if (clickedIdxInOverflow !== -1) {
|
|
70
|
-
newOverflowTabs.splice(clickedIdxInOverflow, 1);
|
|
71
|
-
}
|
|
72
|
-
const lastVisible = newVisibleTabs.pop();
|
|
73
|
-
if (lastVisible !== undefined) {
|
|
74
|
-
newOverflowTabs.unshift(lastVisible);
|
|
75
|
-
}
|
|
76
|
-
newVisibleTabs.push(clickedIndex);
|
|
77
|
-
setVisibleTabs(newVisibleTabs);
|
|
78
|
-
setOverflowTabs(newOverflowTabs);
|
|
79
|
-
requestAnimationFrame(() => {
|
|
80
|
-
var _a;
|
|
81
|
-
const label = (_a = tabRefs.current[clickedIndex]) === null || _a === void 0 ? void 0 : _a.getAttribute('data-label');
|
|
82
|
-
if (label) {
|
|
83
|
-
setActiveTab(label);
|
|
84
|
-
focusTab(clickedIndex);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
const label = (_a = tabRefs.current[clickedIndex]) === null || _a === void 0 ? void 0 : _a.getAttribute('data-label');
|
|
90
|
-
if (label) {
|
|
91
|
-
setActiveTab(label);
|
|
92
|
-
focusTab(clickedIndex);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}, [visibleTabs, overflowTabs, allTabsHidden]);
|
|
38
|
+
onTabChange(label);
|
|
39
|
+
}, [onTabChange]);
|
|
96
40
|
const handleKeyboard = (0, react_1.useCallback)((event, index) => {
|
|
97
41
|
let newIndex = index;
|
|
98
42
|
if (event.key === 'ArrowRight') {
|
|
@@ -114,168 +58,134 @@ function useTabs({ initialTab, totalTabs, containerRef }) {
|
|
|
114
58
|
}
|
|
115
59
|
onTabSelect(newIndex);
|
|
116
60
|
}, [totalTabs, onTabSelect]);
|
|
61
|
+
const replaceLastVisibleTabWithClickedOverflowTab = (0, react_1.useCallback)((clickedIndex) => {
|
|
62
|
+
const { visible: visibleTabs, overflow: overflowTabs } = tabs;
|
|
63
|
+
// Indexes of visible tabs should be sorted(asc), to replace the last visible tab with the clicked tab
|
|
64
|
+
const newVisibleTabs = [...visibleTabs].sort((a, b) => a - b);
|
|
65
|
+
const newOverflowTabs = [...overflowTabs];
|
|
66
|
+
const clickedIdxInOverflow = newOverflowTabs.indexOf(clickedIndex);
|
|
67
|
+
if (clickedIdxInOverflow !== -1) {
|
|
68
|
+
const lastVisible = newVisibleTabs[newVisibleTabs.length - 1];
|
|
69
|
+
newOverflowTabs.splice(clickedIdxInOverflow, 1);
|
|
70
|
+
newOverflowTabs.unshift(lastVisible);
|
|
71
|
+
newVisibleTabs.splice(newVisibleTabs.length - 1, 1);
|
|
72
|
+
newVisibleTabs.unshift(clickedIndex);
|
|
73
|
+
}
|
|
74
|
+
setTabs({
|
|
75
|
+
visible: newVisibleTabs,
|
|
76
|
+
overflow: newOverflowTabs,
|
|
77
|
+
});
|
|
78
|
+
}, [tabs]);
|
|
79
|
+
const onTabClick = (0, react_1.useCallback)((labelOrIndex) => {
|
|
80
|
+
const clickedIndex = typeof labelOrIndex === 'string'
|
|
81
|
+
? tabRefs.current.findIndex((ref) => (ref === null || ref === void 0 ? void 0 : ref.getAttribute('data-label')) === labelOrIndex)
|
|
82
|
+
: labelOrIndex;
|
|
83
|
+
if (clickedIndex === -1)
|
|
84
|
+
return;
|
|
85
|
+
const hasOverflowTabs = tabs.overflow.length > 0;
|
|
86
|
+
if (hasOverflowTabs && !allTabsHidden && tabs.overflow.includes(clickedIndex)) {
|
|
87
|
+
replaceLastVisibleTabWithClickedOverflowTab(clickedIndex);
|
|
88
|
+
}
|
|
89
|
+
const label = tabLabelsRef.current[clickedIndex];
|
|
90
|
+
if (label) {
|
|
91
|
+
onTabChange(label);
|
|
92
|
+
focusTab(clickedIndex);
|
|
93
|
+
}
|
|
94
|
+
}, [allTabsHidden, tabs.overflow, onTabChange, replaceLastVisibleTabWithClickedOverflowTab]);
|
|
117
95
|
const calculateVisibleTabs = (0, react_1.useCallback)(() => {
|
|
118
96
|
const container = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current;
|
|
119
97
|
if (!container)
|
|
120
98
|
return;
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
setVisibleTabs(Array.from({ length: totalTabs }, (_, i) => i));
|
|
124
|
-
setOverflowTabs([]);
|
|
125
|
-
setAllTabsHidden(false);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const containerWidth = container.offsetWidth - 60;
|
|
129
|
-
const tabElements = container.querySelectorAll('[role="tab"]');
|
|
130
|
-
const moreButtonWidth = 80;
|
|
131
|
-
const safetyMargin = 20;
|
|
132
|
-
const tabWidths = Array.from(tabElements).map((el) => el.offsetWidth);
|
|
133
|
-
const tabLabels = Array.from(tabElements).map((el) => el.getAttribute('data-label') || '');
|
|
134
|
-
const tabTypes = Array.from(tabElements).map((el) => el.getAttribute('data-type') || '');
|
|
135
|
-
const hasLongLabels = tabLabels.some((label) => label.length > 30);
|
|
136
|
-
const minVisibleTabs = hasLongLabels ? 1 : 2;
|
|
99
|
+
const containerWidth = container.offsetWidth;
|
|
100
|
+
const tabWidths = tabWidthsRef.current;
|
|
137
101
|
const activeTabIndex = tabRefs.current.findIndex((ref) => (ref === null || ref === void 0 ? void 0 : ref.getAttribute('data-label')) === activeTab);
|
|
138
|
-
|
|
139
|
-
|
|
102
|
+
// Active tab should always be visible, so we include it at the beginning of the array
|
|
103
|
+
let tabsWidth = activeTabIndex !== -1 ? tabWidths[activeTabIndex] : 0;
|
|
104
|
+
const visible = activeTabIndex !== -1 ? [activeTabIndex] : [];
|
|
140
105
|
const overflow = [];
|
|
141
|
-
let
|
|
142
|
-
|
|
143
|
-
if (i
|
|
144
|
-
|
|
106
|
+
for (let i = 0; i < tabWidths.length; i++) {
|
|
107
|
+
// Skip active tab, it was added initially
|
|
108
|
+
if (i === activeTabIndex) {
|
|
109
|
+
continue;
|
|
145
110
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const tabsByType = new Map();
|
|
154
|
-
Array.from({ length: totalTabs }).forEach((_, i) => {
|
|
155
|
-
var _a;
|
|
156
|
-
const type = tabTypes[i] || 'default';
|
|
157
|
-
if (!tabsByType.has(type)) {
|
|
158
|
-
tabsByType.set(type, []);
|
|
111
|
+
const tabWidthWithGap = tabWidths[i] + TABS_GAP;
|
|
112
|
+
const projectedWidth = tabsWidth + tabWidthWithGap;
|
|
113
|
+
if (projectedWidth <= containerWidth) {
|
|
114
|
+
visible.push(i);
|
|
115
|
+
tabsWidth += tabWidthWithGap;
|
|
159
116
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const projectedWidth = typeCurrentWidth +
|
|
169
|
-
tabWidth +
|
|
170
|
-
(typeVisible.length > 0 ? moreButtonWidth + safetyMargin : 0);
|
|
171
|
-
if (projectedWidth <= containerWidth) {
|
|
172
|
-
typeVisible.push(tabIndex);
|
|
173
|
-
typeCurrentWidth += tabWidth;
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
typeOverflow.push(tabIndex);
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
tabIndices.slice(minVisibleTabs).forEach((tabIndex) => {
|
|
180
|
-
const tabWidth = tabWidths[tabIndex];
|
|
181
|
-
const projectedWidth = typeCurrentWidth + tabWidth + moreButtonWidth + safetyMargin;
|
|
182
|
-
if (projectedWidth <= containerWidth) {
|
|
183
|
-
typeVisible.push(tabIndex);
|
|
184
|
-
typeCurrentWidth += tabWidth;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
typeOverflow.push(tabIndex);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
visible.push(...typeVisible);
|
|
191
|
-
overflow.push(...typeOverflow);
|
|
192
|
-
currentWidth = typeCurrentWidth;
|
|
193
|
-
});
|
|
194
|
-
if (activeTabIndex !== -1 && !visible.includes(activeTabIndex)) {
|
|
195
|
-
if (visible.length > 0) {
|
|
117
|
+
else {
|
|
118
|
+
overflow.push(i);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (overflow.length > 0) {
|
|
122
|
+
tabsWidth += MORE_BUTTON_WIDTH;
|
|
123
|
+
// Remove tabs starting from the end of the array until the width of the visible tabs is less than the container width
|
|
124
|
+
while (tabsWidth > containerWidth && visible.length) {
|
|
196
125
|
const removed = visible.pop();
|
|
197
126
|
if (removed !== undefined) {
|
|
198
127
|
overflow.unshift(removed);
|
|
128
|
+
tabsWidth -= tabWidths[removed];
|
|
199
129
|
}
|
|
200
130
|
}
|
|
201
|
-
visible.push(activeTabIndex);
|
|
202
|
-
const activeOverflowIndex = overflow.indexOf(activeTabIndex);
|
|
203
|
-
if (activeOverflowIndex !== -1)
|
|
204
|
-
overflow.splice(activeOverflowIndex, 1);
|
|
205
131
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}, [containerRef,
|
|
132
|
+
setTabs({
|
|
133
|
+
visible,
|
|
134
|
+
overflow,
|
|
135
|
+
});
|
|
136
|
+
}, [containerRef, activeTab]);
|
|
211
137
|
(0, react_1.useEffect)(() => {
|
|
212
138
|
if (!(containerRef === null || containerRef === void 0 ? void 0 : containerRef.current))
|
|
213
139
|
return;
|
|
214
|
-
|
|
215
|
-
const allTabsReady = tabRefs.current.length === totalTabs && tabRefs.current.every((tab) => tab === null || tab === void 0 ? void 0 : tab.offsetWidth);
|
|
216
|
-
if (!allTabsReady) {
|
|
217
|
-
resizeTimeoutRef.current = requestAnimationFrame(ensureTabsReady);
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
calculateVisibleTabs();
|
|
221
|
-
hasCalculatedOnce.current = true;
|
|
222
|
-
};
|
|
223
|
-
resizeTimeoutRef.current = requestAnimationFrame(ensureTabsReady);
|
|
224
|
-
let resizeTimeout;
|
|
140
|
+
let resizeTimeout = requestAnimationFrame(calculateVisibleTabs);
|
|
225
141
|
const handleResize = () => {
|
|
226
|
-
if (!hasCalculatedOnce.current)
|
|
227
|
-
return;
|
|
228
142
|
if (resizeTimeout) {
|
|
229
143
|
cancelAnimationFrame(resizeTimeout);
|
|
230
144
|
}
|
|
231
|
-
resizeTimeout = requestAnimationFrame(
|
|
232
|
-
if (resizeTimeoutRef.current) {
|
|
233
|
-
cancelAnimationFrame(resizeTimeoutRef.current);
|
|
234
|
-
}
|
|
235
|
-
resizeTimeoutRef.current = requestAnimationFrame(() => {
|
|
236
|
-
const container = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current;
|
|
237
|
-
if (!container)
|
|
238
|
-
return;
|
|
239
|
-
const currentWidth = container.offsetWidth;
|
|
240
|
-
if (Math.abs(lastWidthRef.current - currentWidth) > 5) {
|
|
241
|
-
lastWidthRef.current = currentWidth;
|
|
242
|
-
calculateVisibleTabs();
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
});
|
|
145
|
+
resizeTimeout = requestAnimationFrame(calculateVisibleTabs);
|
|
246
146
|
};
|
|
247
|
-
const resizeObserver = new ResizeObserver(handleResize);
|
|
248
|
-
resizeObserver.observe(containerRef.current);
|
|
249
147
|
window.addEventListener('resize', handleResize);
|
|
250
148
|
return () => {
|
|
251
|
-
resizeObserver.disconnect();
|
|
252
149
|
window.removeEventListener('resize', handleResize);
|
|
253
|
-
|
|
254
|
-
cancelAnimationFrame(resizeTimeoutRef.current);
|
|
255
|
-
}
|
|
256
|
-
if (resizeTimeout) {
|
|
257
|
-
cancelAnimationFrame(resizeTimeout);
|
|
258
|
-
}
|
|
150
|
+
cancelAnimationFrame(resizeTimeout);
|
|
259
151
|
};
|
|
260
152
|
}, [containerRef, totalTabs, calculateVisibleTabs]);
|
|
261
|
-
(0, react_1.useEffect)(() => {
|
|
262
|
-
const raf = requestAnimationFrame(() => {
|
|
263
|
-
setReady(true);
|
|
264
|
-
calculateVisibleTabs();
|
|
265
|
-
});
|
|
266
|
-
return () => cancelAnimationFrame(raf);
|
|
267
|
-
}, [calculateVisibleTabs]);
|
|
268
153
|
return {
|
|
269
|
-
activeTab,
|
|
270
|
-
setActiveTab,
|
|
271
154
|
setTabRef,
|
|
272
155
|
onTabClick,
|
|
273
156
|
handleKeyboard,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
overflowTabs,
|
|
277
|
-
ready,
|
|
157
|
+
visibleTabs: tabs.visible,
|
|
158
|
+
overflowTabs: tabs.overflow,
|
|
278
159
|
allTabsHidden,
|
|
279
160
|
};
|
|
280
161
|
}
|
|
162
|
+
const useActiveTab = ({ initialTab, tabsId }) => {
|
|
163
|
+
const [searchParams, setSearchParams] = (0, react_router_dom_1.useSearchParams)();
|
|
164
|
+
const [activeTab, setActiveTab] = (0, react_1.useState)(getInitialTab({ initialTab, searchParams, tabsId }));
|
|
165
|
+
const prevActiveTabRef = (0, react_1.useRef)(activeTab);
|
|
166
|
+
(0, react_1.useEffect)(() => {
|
|
167
|
+
const hasActiveTabChanged = prevActiveTabRef.current !== activeTab;
|
|
168
|
+
if (!tabsId || !hasActiveTabChanged) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
prevActiveTabRef.current = activeTab;
|
|
172
|
+
setSearchParams((searchParams) => {
|
|
173
|
+
searchParams.set(tabsId, activeTab);
|
|
174
|
+
return searchParams;
|
|
175
|
+
});
|
|
176
|
+
}, [activeTab, setSearchParams, tabsId]);
|
|
177
|
+
return {
|
|
178
|
+
activeTab,
|
|
179
|
+
setActiveTab,
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
exports.useActiveTab = useActiveTab;
|
|
183
|
+
const getInitialTab = ({ initialTab, searchParams, tabsId }) => {
|
|
184
|
+
let resultTab = initialTab;
|
|
185
|
+
if (tabsId) {
|
|
186
|
+
const tabFromUrl = searchParams.get(tabsId);
|
|
187
|
+
resultTab = tabFromUrl ? tabFromUrl : resultTab;
|
|
188
|
+
}
|
|
189
|
+
return resultTab;
|
|
190
|
+
};
|
|
281
191
|
//# sourceMappingURL=use-tabs.js.map
|
package/lib/core/utils/index.js
CHANGED
|
@@ -53,4 +53,5 @@ __exportStar(require("./lang-to-name"), exports);
|
|
|
53
53
|
__exportStar(require("./enhanced-smoothstep"), exports);
|
|
54
54
|
__exportStar(require("./icon-resolver"), exports);
|
|
55
55
|
__exportStar(require("./dynamic"), exports);
|
|
56
|
+
__exportStar(require("./tabs"), exports);
|
|
56
57
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getTabId(label: string, index: number): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTabId = getTabId;
|
|
4
|
+
function getTabId(label, index) {
|
|
5
|
+
const cleanLabel = label.replace(/\s+/g, '-').toLowerCase();
|
|
6
|
+
return `${cleanLabel}-${index}`;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=tabs.js.map
|
|
@@ -11,7 +11,7 @@ const TabList_1 = require("../../../markdoc/components/Tabs/TabList");
|
|
|
11
11
|
const GenericIcon_1 = require("../../../icons/GenericIcon/GenericIcon");
|
|
12
12
|
function TabComponent({ tabId, label, size, disabled, setRef, onKeyDown, onClick, icon, iconRawContent, }) {
|
|
13
13
|
return (react_1.default.createElement(TabList_1.TabItem, { "data-component-name": "Markdoc/Tabs/Tab", size: size, tabIndex: 0 },
|
|
14
|
-
react_1.default.createElement(TabList_1.TabButtonLink, { id: `tab-${tabId}`, role: "tab", "aria-selected": "false", "aria-controls": `panel-${tabId}`, tabIndex: -1, size: size, disabled: disabled, ref: setRef, onKeyDown: onKeyDown, onClick: onClick },
|
|
14
|
+
react_1.default.createElement(TabList_1.TabButtonLink, { id: `tab-${tabId}`, "data-label": label, role: "tab", "aria-selected": "false", "aria-controls": `panel-${tabId}`, tabIndex: -1, size: size, disabled: disabled, ref: setRef, onKeyDown: onKeyDown, onClick: onClick },
|
|
15
15
|
react_1.default.createElement(LabelWrapper, null,
|
|
16
16
|
react_1.default.createElement(GenericIcon_1.GenericIcon, { icon: icon, rawContent: iconRawContent }),
|
|
17
17
|
label))));
|
|
@@ -4,22 +4,10 @@ import { TabItemProps, TabsSize } from '../../../markdoc/components/Tabs/Tabs';
|
|
|
4
4
|
type TabListProps = {
|
|
5
5
|
childrenArray: React.ReactElement<TabItemProps>[];
|
|
6
6
|
size: TabsSize;
|
|
7
|
-
overflowTabs: number[];
|
|
8
|
-
visibleTabs: number[];
|
|
9
|
-
setTabRef: (element: HTMLButtonElement | null, index: number) => void;
|
|
10
|
-
onTabClick: (labelOrIndex: string | number) => void;
|
|
11
|
-
handleKeyboard: (event: React.KeyboardEvent<HTMLButtonElement>, index: number) => void;
|
|
12
|
-
getTabId: (label: string, index: number) => string;
|
|
13
7
|
activeTab: string;
|
|
14
|
-
|
|
15
|
-
highlightStyle: {
|
|
16
|
-
left: number;
|
|
17
|
-
width: number;
|
|
18
|
-
};
|
|
19
|
-
allTabsHidden: boolean;
|
|
20
|
-
tabsContainerRef: React.RefObject<HTMLUListElement | null>;
|
|
8
|
+
onTabChange: (tab: string) => void;
|
|
21
9
|
};
|
|
22
|
-
export declare function TabList({ childrenArray, size,
|
|
10
|
+
export declare function TabList({ childrenArray, size, activeTab, onTabChange, }: TabListProps): JSX.Element;
|
|
23
11
|
export declare const TabListContainer: import("styled-components").StyledComponent<"ul", any, {}, never>;
|
|
24
12
|
export declare const TabItem: import("styled-components").StyledComponent<"li", any, {
|
|
25
13
|
active?: boolean;
|
|
@@ -22,35 +22,42 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
26
|
exports.TabButtonLink = exports.TabItem = exports.TabListContainer = void 0;
|
|
30
27
|
exports.TabList = TabList;
|
|
31
|
-
const react_1 =
|
|
28
|
+
const react_1 = __importStar(require("react"));
|
|
32
29
|
const styled_components_1 = __importStar(require("styled-components"));
|
|
33
30
|
const Tab_1 = require("../../../markdoc/components/Tabs/Tab");
|
|
34
31
|
const Dropdown_1 = require("../../../components/Dropdown/Dropdown");
|
|
35
32
|
const DropdownMenu_1 = require("../../../components/Dropdown/DropdownMenu");
|
|
36
33
|
const DropdownMenuItem_1 = require("../../../components/Dropdown/DropdownMenuItem");
|
|
37
34
|
const Button_1 = require("../../../components/Button/Button");
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const hooks_1 = require("../../../core/hooks");
|
|
36
|
+
const utils_1 = require("../../../core/utils");
|
|
37
|
+
function TabList({ childrenArray, size, activeTab, onTabChange, }) {
|
|
38
|
+
const tabsContainerRef = (0, react_1.useRef)(null);
|
|
39
|
+
const { allTabsHidden, overflowTabs, visibleTabs, handleKeyboard, onTabClick, setTabRef } = (0, hooks_1.useTabs)({
|
|
40
|
+
activeTab,
|
|
41
|
+
onTabChange,
|
|
42
|
+
containerRef: tabsContainerRef,
|
|
43
|
+
totalTabs: childrenArray.length,
|
|
44
|
+
});
|
|
45
|
+
const { highlightStyle } = useHighlightBarAnimation({
|
|
46
|
+
activeTab,
|
|
47
|
+
childrenArray,
|
|
48
|
+
overflowTabs,
|
|
49
|
+
tabsContainerRef,
|
|
50
|
+
visibleTabs,
|
|
51
|
+
});
|
|
52
|
+
return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: tabsContainerRef },
|
|
53
|
+
react_1.default.createElement(HighlightBar, { size: size, style: highlightStyle },
|
|
41
54
|
react_1.default.createElement("div", null)),
|
|
42
55
|
childrenArray.map((child, index) => {
|
|
43
56
|
if (!visibleTabs.includes(index))
|
|
44
57
|
return null;
|
|
45
58
|
const { label, icon } = child.props;
|
|
46
|
-
const tabId = getTabId(label, index);
|
|
47
|
-
return (react_1.default.createElement(Tab_1.Tab, { key: `key-${tabId}`, tabId: tabId, label: label, icon: icon, size: size, disabled: child.props.disable, setRef: (el) => {
|
|
48
|
-
setTabRef(el, index);
|
|
49
|
-
if (el) {
|
|
50
|
-
el.setAttribute('data-label', label);
|
|
51
|
-
el.setAttribute('data-animating', isAnimating.toString());
|
|
52
|
-
}
|
|
53
|
-
}, onKeyDown: (event) => handleKeyboard(event, index), onClick: () => {
|
|
59
|
+
const tabId = (0, utils_1.getTabId)(label, index);
|
|
60
|
+
return (react_1.default.createElement(Tab_1.Tab, { key: `key-${tabId}`, tabId: tabId, label: label, icon: icon, size: size, disabled: child.props.disable, setRef: (el) => setTabRef(el, index), onKeyDown: (event) => handleKeyboard(event, index), onClick: () => {
|
|
54
61
|
var _a, _b;
|
|
55
62
|
(_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
56
63
|
onTabClick(label);
|
|
@@ -61,7 +68,7 @@ function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, on
|
|
|
61
68
|
: undefined }, allTabsHidden ? activeTab : 'More'), alignment: "start", withArrow: true },
|
|
62
69
|
react_1.default.createElement(DropdownMenu_1.DropdownMenu, null, overflowTabs.map((index) => {
|
|
63
70
|
const { label } = childrenArray[index].props;
|
|
64
|
-
const tabId = getTabId(label, index);
|
|
71
|
+
const tabId = (0, utils_1.getTabId)(label, index);
|
|
65
72
|
return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: `more-${tabId}`, active: activeTab === label, onAction: () => {
|
|
66
73
|
var _a, _b;
|
|
67
74
|
(_b = (_a = childrenArray[index].props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
@@ -69,6 +76,46 @@ function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, on
|
|
|
69
76
|
}, disabled: childrenArray[index].props.disable }, label));
|
|
70
77
|
})))))));
|
|
71
78
|
}
|
|
79
|
+
const useHighlightBarAnimation = (props) => {
|
|
80
|
+
const { childrenArray, activeTab, tabsContainerRef, visibleTabs, overflowTabs } = props;
|
|
81
|
+
const [highlightStyle, setHighlightStyle] = react_1.default.useState({
|
|
82
|
+
left: 0,
|
|
83
|
+
width: 0,
|
|
84
|
+
});
|
|
85
|
+
(0, react_1.useEffect)(() => {
|
|
86
|
+
const activeIndex = childrenArray.findIndex((child) => child.props.label === activeTab);
|
|
87
|
+
const container = tabsContainerRef.current;
|
|
88
|
+
if (!container || activeIndex === -1) {
|
|
89
|
+
setHighlightStyle({ left: 0, width: 0 });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const activeTabElement = container.querySelector(`[data-label="${activeTab}"]`);
|
|
93
|
+
if (!activeTabElement)
|
|
94
|
+
return;
|
|
95
|
+
container.querySelectorAll('[data-label]').forEach((el) => {
|
|
96
|
+
el.classList.remove('active');
|
|
97
|
+
});
|
|
98
|
+
const { offsetLeft, offsetWidth } = activeTabElement;
|
|
99
|
+
if (visibleTabs.includes(activeIndex)) {
|
|
100
|
+
activeTabElement.classList.add('active');
|
|
101
|
+
setHighlightStyle({ left: offsetLeft, width: offsetWidth });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (overflowTabs.includes(activeIndex)) {
|
|
105
|
+
const moreButton = container.querySelector('button');
|
|
106
|
+
if (!moreButton)
|
|
107
|
+
return;
|
|
108
|
+
const moreButtonRect = moreButton.getBoundingClientRect();
|
|
109
|
+
const containerRect = container.getBoundingClientRect();
|
|
110
|
+
setHighlightStyle({
|
|
111
|
+
left: moreButtonRect.left - containerRect.left,
|
|
112
|
+
width: moreButtonRect.width,
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}, [activeTab, childrenArray, visibleTabs, overflowTabs, tabsContainerRef]);
|
|
117
|
+
return { highlightStyle };
|
|
118
|
+
};
|
|
72
119
|
exports.TabListContainer = styled_components_1.default.ul `
|
|
73
120
|
position: relative;
|
|
74
121
|
display: flex;
|
|
@@ -12,12 +12,12 @@ export type TabItemProps = {
|
|
|
12
12
|
icon?: React.ReactNode | string;
|
|
13
13
|
};
|
|
14
14
|
type TabsProps = {
|
|
15
|
+
id?: string;
|
|
15
16
|
children: React.ReactElement<TabItemProps>[];
|
|
16
17
|
className?: string;
|
|
17
18
|
size: TabsSize;
|
|
18
|
-
forceReady?: boolean;
|
|
19
19
|
initialTab?: string;
|
|
20
20
|
};
|
|
21
|
-
export declare function Tabs({ children, className, size,
|
|
21
|
+
export declare function Tabs({ id, children, className, size, initialTab: propInitialTab, }: TabsProps): JSX.Element;
|
|
22
22
|
export declare const TabContent: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
23
23
|
export {};
|