@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.
Files changed (33) hide show
  1. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +1 -1
  2. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +1 -1
  3. package/lib/components/Panel/variables.js +1 -0
  4. package/lib/components/Tag/Tag.d.ts +3 -2
  5. package/lib/components/Tag/Tag.js +21 -5
  6. package/lib/components/Tag/variables.dark.js +135 -0
  7. package/lib/components/Tag/variables.js +120 -58
  8. package/lib/core/hooks/use-tabs.d.ts +11 -6
  9. package/lib/core/hooks/use-tabs.js +117 -207
  10. package/lib/core/utils/index.d.ts +1 -0
  11. package/lib/core/utils/index.js +1 -0
  12. package/lib/core/utils/tabs.d.ts +1 -0
  13. package/lib/core/utils/tabs.js +8 -0
  14. package/lib/markdoc/components/Tabs/Tab.js +1 -1
  15. package/lib/markdoc/components/Tabs/TabList.d.ts +2 -14
  16. package/lib/markdoc/components/Tabs/TabList.js +63 -16
  17. package/lib/markdoc/components/Tabs/Tabs.d.ts +2 -2
  18. package/lib/markdoc/components/Tabs/Tabs.js +11 -87
  19. package/lib/markdoc/tags/tabs.js +5 -0
  20. package/package.json +3 -3
  21. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
  22. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
  23. package/src/components/Panel/variables.ts +1 -0
  24. package/src/components/Tag/Tag.tsx +33 -8
  25. package/src/components/Tag/variables.dark.ts +135 -0
  26. package/src/components/Tag/variables.ts +120 -58
  27. package/src/core/hooks/use-tabs.ts +160 -238
  28. package/src/core/utils/index.ts +1 -0
  29. package/src/core/utils/tabs.ts +4 -0
  30. package/src/markdoc/components/Tabs/Tab.tsx +1 -0
  31. package/src/markdoc/components/Tabs/TabList.tsx +84 -30
  32. package/src/markdoc/components/Tabs/Tabs.tsx +12 -125
  33. 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
- function useTabs({ initialTab, totalTabs, containerRef }) {
6
- const [activeTab, setActiveTab] = (0, react_1.useState)(initialTab);
7
- const [visibleTabs, setVisibleTabs] = (0, react_1.useState)(Array.from({ length: totalTabs }, (_, i) => i));
8
- const [overflowTabs, setOverflowTabs] = (0, react_1.useState)([]);
9
- const [allTabsHidden, setAllTabsHidden] = (0, react_1.useState)(false);
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 resizeTimeoutRef = (0, react_1.useRef)(undefined);
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
- if (element) {
23
- const label = element.getAttribute('data-label');
24
- if (label) {
25
- tabLabelsRef.current[index] = label;
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
- if (currentElement) {
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
- setActiveTab(label);
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 contentWrapper = container.closest('div');
122
- if (!contentWrapper) {
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
- let currentWidth = 0;
139
- const visible = [];
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 minTabsWidth = 0;
142
- Array.from({ length: minVisibleTabs }).forEach((_, i) => {
143
- if (i < tabWidths.length) {
144
- minTabsWidth += tabWidths[i] + (i > 0 ? moreButtonWidth + safetyMargin : 0);
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
- if (minTabsWidth > containerWidth) {
148
- setVisibleTabs([]);
149
- setOverflowTabs(Array.from({ length: totalTabs }, (_, i) => i));
150
- setAllTabsHidden(true);
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
- (_a = tabsByType.get(type)) === null || _a === void 0 ? void 0 : _a.push(i);
161
- });
162
- tabsByType.forEach((tabIndices) => {
163
- let typeCurrentWidth = currentWidth;
164
- const typeVisible = [];
165
- const typeOverflow = [];
166
- tabIndices.slice(0, minVisibleTabs).forEach((tabIndex) => {
167
- const tabWidth = tabWidths[tabIndex];
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
- setVisibleTabs(visible);
207
- setOverflowTabs(overflow);
208
- setAllTabsHidden(visible.length === 0);
209
- // eslint-disable-next-line react-hooks/exhaustive-deps
210
- }, [containerRef, totalTabs]);
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
- const ensureTabsReady = () => {
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
- if (resizeTimeoutRef.current) {
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
- getTabId,
275
- visibleTabs,
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
@@ -37,3 +37,4 @@ export * from './lang-to-name';
37
37
  export * from './enhanced-smoothstep';
38
38
  export * from './icon-resolver';
39
39
  export * from './dynamic';
40
+ export * from './tabs';
@@ -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
- isAnimating: boolean;
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, overflowTabs, visibleTabs, setTabRef, onTabClick, handleKeyboard, getTabId, activeTab, isAnimating, highlightStyle, allTabsHidden, tabsContainerRef, }: TabListProps): JSX.Element;
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 = __importDefault(require("react"));
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
- function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, onTabClick, handleKeyboard, getTabId, activeTab, isAnimating, highlightStyle, allTabsHidden, tabsContainerRef, }) {
39
- return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: tabsContainerRef, "data-animating": isAnimating },
40
- react_1.default.createElement(HighlightBar, { size: size, style: { left: highlightStyle.left, width: highlightStyle.width } },
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, forceReady, initialTab: propInitialTab, }: TabsProps): JSX.Element;
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 {};