@redocly/theme 0.59.0-next.2 → 0.59.0-rc.1

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 (53) 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/Catalog/CatalogTagsWithTooltip.js +1 -1
  4. package/lib/components/Dropdown/Dropdown.d.ts +2 -16
  5. package/lib/components/Dropdown/Dropdown.js +5 -5
  6. package/lib/components/Menu/MenuItem.js +1 -1
  7. package/lib/components/OpenApiDocs/hooks/AdditionalOverviewInfo.d.ts +1 -0
  8. package/lib/components/OpenApiDocs/hooks/AdditionalOverviewInfo.js +11 -0
  9. package/lib/components/OpenApiDocs/hooks/AfterOpenApiDescription.d.ts +1 -0
  10. package/lib/components/OpenApiDocs/hooks/AfterOpenApiDescription.js +5 -0
  11. package/lib/components/Search/SearchAiConversationInput.d.ts +1 -2
  12. package/lib/components/Search/SearchAiConversationInput.js +3 -11
  13. package/lib/components/Search/SearchDialog.js +3 -6
  14. package/lib/components/Search/variables.js +1 -5
  15. package/lib/components/Select/variables.js +2 -2
  16. package/lib/components/Tag/Tag.js +4 -4
  17. package/lib/core/constants/search.d.ts +4 -5
  18. package/lib/core/constants/search.js +5 -4
  19. package/lib/core/hooks/use-tabs.d.ts +2 -3
  20. package/lib/core/hooks/use-tabs.js +57 -115
  21. package/lib/core/types/hooks.d.ts +2 -2
  22. package/lib/ext/process-scorecard.d.ts +5 -0
  23. package/lib/ext/process-scorecard.js +11 -0
  24. package/lib/icons/AiStarsIcon/AiStarsIcon.js +2 -11
  25. package/lib/icons/RedoclyIcon/RedoclyIcon.js +7 -4
  26. package/lib/index.d.ts +2 -0
  27. package/lib/index.js +2 -0
  28. package/lib/markdoc/components/Tabs/TabList.d.ts +1 -3
  29. package/lib/markdoc/components/Tabs/TabList.js +47 -197
  30. package/lib/markdoc/components/Tabs/Tabs.d.ts +1 -2
  31. package/lib/markdoc/components/Tabs/Tabs.js +12 -57
  32. package/package.json +3 -3
  33. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
  34. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
  35. package/src/components/Catalog/CatalogTagsWithTooltip.tsx +5 -1
  36. package/src/components/Dropdown/Dropdown.tsx +79 -84
  37. package/src/components/Menu/MenuItem.tsx +0 -1
  38. package/src/components/OpenApiDocs/hooks/AdditionalOverviewInfo.tsx +9 -0
  39. package/src/components/OpenApiDocs/hooks/AfterOpenApiDescription.tsx +1 -0
  40. package/src/components/Search/SearchAiConversationInput.tsx +2 -12
  41. package/src/components/Search/SearchDialog.tsx +3 -6
  42. package/src/components/Search/variables.ts +1 -5
  43. package/src/components/Select/variables.ts +2 -2
  44. package/src/components/Tag/Tag.tsx +6 -6
  45. package/src/core/constants/search.ts +4 -8
  46. package/src/core/hooks/use-tabs.ts +86 -168
  47. package/src/core/types/hooks.ts +1 -5
  48. package/src/ext/process-scorecard.ts +13 -0
  49. package/src/icons/AiStarsIcon/AiStarsIcon.tsx +2 -11
  50. package/src/icons/RedoclyIcon/RedoclyIcon.tsx +22 -4
  51. package/src/index.ts +2 -0
  52. package/src/markdoc/components/Tabs/TabList.tsx +105 -312
  53. package/src/markdoc/components/Tabs/Tabs.tsx +11 -136
@@ -44,144 +44,47 @@ const DropdownMenuItem_1 = require("../../../components/Dropdown/DropdownMenuIte
44
44
  const Button_1 = require("../../../components/Button/Button");
45
45
  const hooks_1 = require("../../../core/hooks");
46
46
  const utils_1 = require("../../../core/utils");
47
- /**
48
- * Calculates optimal dropdown position relative to viewport to ensure visibility.
49
- * Positions below the button by default, but moves above if insufficient space.
50
- * Adjusts horizontal position to prevent overflow off screen edges.
51
- */
52
- const calculateDropdownPosition = (buttonRect, dropdownRect) => {
53
- const gap = 4;
54
- const margin = 16;
55
- const spaceBelow = window.innerHeight - buttonRect.bottom;
56
- const spaceAbove = buttonRect.top;
57
- // Position below button, or above if dropdown doesn't fit below
58
- const top = spaceBelow < dropdownRect.height + gap && spaceAbove > spaceBelow
59
- ? buttonRect.top - gap
60
- : buttonRect.bottom + gap;
61
- // Align with button left edge, adjust if overflows screen
62
- const idealLeft = buttonRect.left;
63
- const rightEdge = idealLeft + dropdownRect.width;
64
- const overflowsRight = rightEdge > window.innerWidth - margin;
65
- const left = overflowsRight
66
- ? window.innerWidth - dropdownRect.width - margin
67
- : Math.max(margin, idealLeft);
68
- return { top, left };
69
- };
70
- /**
71
- * Manages dropdown positioning and updates on scroll/resize events for TabList.
72
- */
73
- const useDropdownPosition = (hasOverflow, dropdownRef) => {
74
- const [dropdownPosition, setDropdownPosition] = (0, react_1.useState)({});
75
- const [isDropdownOpen, setIsDropdownOpen] = (0, react_1.useState)(false);
76
- const updateDropdownPosition = (0, react_1.useCallback)(() => {
77
- if (!dropdownRef.current)
78
- return;
79
- const button = dropdownRef.current.querySelector('button');
80
- const dropdownMenu = dropdownRef.current.querySelector('div:last-child');
81
- if (!button || !dropdownMenu)
82
- return;
83
- const buttonRect = button.getBoundingClientRect();
84
- const dropdownRect = dropdownMenu.getBoundingClientRect();
85
- const position = calculateDropdownPosition(buttonRect, dropdownRect);
86
- setDropdownPosition(position);
87
- }, [dropdownRef]);
88
- // Track when dropdown menu appears and recalculate position
89
- (0, react_1.useEffect)(() => {
90
- if (!hasOverflow || !isDropdownOpen || !dropdownRef.current)
91
- return;
92
- const dropdownMenu = dropdownRef.current.querySelector('div:last-child');
93
- if (!dropdownMenu)
94
- return;
95
- // ResizeObserver tracks both initial render and size changes
96
- const resizeObserver = new ResizeObserver(() => {
97
- updateDropdownPosition();
98
- });
99
- resizeObserver.observe(dropdownMenu);
100
- return () => resizeObserver.disconnect();
101
- }, [hasOverflow, isDropdownOpen, dropdownRef, updateDropdownPosition]);
102
- // Update position on scroll/resize
103
- (0, react_1.useEffect)(() => {
104
- if (!hasOverflow || !isDropdownOpen)
105
- return;
106
- window.addEventListener('scroll', updateDropdownPosition, true);
107
- window.addEventListener('resize', updateDropdownPosition);
108
- return () => {
109
- window.removeEventListener('scroll', updateDropdownPosition, true);
110
- window.removeEventListener('resize', updateDropdownPosition);
111
- };
112
- }, [hasOverflow, isDropdownOpen, updateDropdownPosition]);
113
- return {
114
- dropdownPosition,
115
- isDropdownOpen,
116
- setIsDropdownOpen,
117
- setDropdownPosition,
118
- updateDropdownPosition,
119
- };
120
- };
121
- const renderTab = (child, index, size, setTabRef, handleKeyboard, onTabClick) => {
122
- const { label, icon } = child.props;
123
- const tabId = (0, utils_1.getTabId)(label, index);
124
- 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: () => {
125
- var _a, _b;
126
- (_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
127
- onTabClick(label);
128
- } }));
129
- };
130
- function TabList({ childrenArray, size, activeTab, onTabChange, containerRef, onReadyChange, }) {
131
- const dropdownRef = (0, react_1.useRef)(null);
132
- const totalTabs = childrenArray.length;
133
- const { overflowTabs, visibleTabs, handleKeyboard, onTabClick, setTabRef, isReady } = (0, hooks_1.useTabs)({
47
+ function TabList({ childrenArray, size, activeTab, onTabChange, }) {
48
+ const tabsContainerRef = (0, react_1.useRef)(null);
49
+ const { allTabsHidden, overflowTabs, visibleTabs, handleKeyboard, onTabClick, setTabRef } = (0, hooks_1.useTabs)({
134
50
  activeTab,
135
51
  onTabChange,
136
- containerRef,
137
- totalTabs,
52
+ containerRef: tabsContainerRef,
53
+ totalTabs: childrenArray.length,
138
54
  });
139
- (0, react_1.useEffect)(() => {
140
- onReadyChange === null || onReadyChange === void 0 ? void 0 : onReadyChange(isReady);
141
- }, [isReady, onReadyChange]);
142
55
  const { highlightStyle } = useHighlightBarAnimation({
143
56
  activeTab,
144
57
  childrenArray,
145
58
  overflowTabs,
146
- tabsContainerRef: containerRef,
59
+ tabsContainerRef,
147
60
  visibleTabs,
148
61
  });
149
- const hasOverflow = overflowTabs.length > 0;
150
- const isMoreActive = hasOverflow &&
151
- overflowTabs.some((i) => childrenArray[i] && activeTab === childrenArray[i].props.label);
152
- // Show as selector when no visible tabs (all tabs in dropdown)
153
- const showAsSelector = visibleTabs.length === 0 && hasOverflow;
154
- const { dropdownPosition, setIsDropdownOpen, setDropdownPosition } = useDropdownPosition(hasOverflow, dropdownRef);
155
- return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: containerRef },
62
+ return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: tabsContainerRef },
156
63
  react_1.default.createElement(HighlightBar, { size: size, style: highlightStyle },
157
64
  react_1.default.createElement("div", null)),
158
65
  childrenArray.map((child, index) => {
159
- // Show all tabs before ready (for measurement), then only visible ones
160
- const shouldRender = !isReady || visibleTabs.includes(index);
161
- if (!shouldRender)
66
+ if (!visibleTabs.includes(index))
162
67
  return null;
163
- return renderTab(child, index, size, setTabRef, handleKeyboard, onTabClick);
68
+ const { label, icon } = child.props;
69
+ const tabId = (0, utils_1.getTabId)(label, index);
70
+ 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: () => {
71
+ var _a, _b;
72
+ (_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
73
+ onTabClick(label);
74
+ } }));
164
75
  }),
165
- hasOverflow && (react_1.default.createElement(exports.TabItem, { size: size, active: isMoreActive || showAsSelector, tabIndex: 0, className: "dropdown-tab" },
166
- react_1.default.createElement(DropdownWrapper, { "$top": dropdownPosition.top, "$left": dropdownPosition.left, onClickCapture: () => {
167
- setIsDropdownOpen(true);
168
- } },
169
- react_1.default.createElement(FixedPositionDropdown, { ref: dropdownRef, trigger: react_1.default.createElement(exports.TabButtonLink, { size: size, className: isMoreActive || showAsSelector ? 'active' : undefined }, showAsSelector ? react_1.default.createElement(TabButtonText, null, activeTab) : 'More'), alignment: "start", withArrow: true, onClose: () => {
170
- setIsDropdownOpen(false);
171
- setDropdownPosition({});
172
- } },
173
- react_1.default.createElement(DropdownMenu_1.DropdownMenu, null, overflowTabs.map((index) => {
174
- const child = childrenArray[index];
175
- if (!child)
176
- return null;
177
- const { label } = child.props;
178
- const tabId = (0, utils_1.getTabId)(label, index);
179
- return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: `more-${tabId}`, active: activeTab === label, onAction: () => {
180
- var _a, _b;
181
- (_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
182
- onTabClick(index);
183
- }, disabled: child.props.disable }, label));
184
- }))))))));
76
+ react_1.default.createElement(exports.TabItem, { size: size, active: overflowTabs.some((index) => activeTab === childrenArray[index].props.label), tabIndex: 0 }, overflowTabs.length > 0 && (react_1.default.createElement(Dropdown_1.Dropdown, { trigger: react_1.default.createElement(exports.TabButtonLink, { size: size, className: overflowTabs.some((index) => activeTab === childrenArray[index].props.label)
77
+ ? 'active'
78
+ : undefined }, allTabsHidden ? activeTab : 'More'), alignment: "start", withArrow: true },
79
+ react_1.default.createElement(DropdownMenu_1.DropdownMenu, null, overflowTabs.map((index) => {
80
+ const { label } = childrenArray[index].props;
81
+ const tabId = (0, utils_1.getTabId)(label, index);
82
+ return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: `more-${tabId}`, active: activeTab === label, onAction: () => {
83
+ var _a, _b;
84
+ (_b = (_a = childrenArray[index].props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
85
+ onTabClick(index);
86
+ }, disabled: childrenArray[index].props.disable }, label));
87
+ })))))));
185
88
  }
186
89
  const useHighlightBarAnimation = (props) => {
187
90
  const { childrenArray, activeTab, tabsContainerRef, visibleTabs, overflowTabs } = props;
@@ -196,11 +99,18 @@ const useHighlightBarAnimation = (props) => {
196
99
  setHighlightStyle({ left: 0, width: 0 });
197
100
  return;
198
101
  }
199
- // Remove active class from all tabs first
102
+ const activeTabElement = container.querySelector(`[data-label="${activeTab}"]`);
103
+ if (!activeTabElement)
104
+ return;
200
105
  container.querySelectorAll('[data-label]').forEach((el) => {
201
106
  el.classList.remove('active');
202
107
  });
203
- // Check if active tab is in overflow first
108
+ const { offsetLeft, offsetWidth } = activeTabElement;
109
+ if (visibleTabs.includes(activeIndex)) {
110
+ activeTabElement.classList.add('active');
111
+ setHighlightStyle({ left: offsetLeft, width: offsetWidth });
112
+ return;
113
+ }
204
114
  if (overflowTabs.includes(activeIndex)) {
205
115
  const moreButton = container.querySelector('button');
206
116
  if (!moreButton)
@@ -213,16 +123,6 @@ const useHighlightBarAnimation = (props) => {
213
123
  });
214
124
  return;
215
125
  }
216
- // Active tab is visible, find its element
217
- const activeTabElement = container.querySelector(`[data-label="${activeTab}"]`);
218
- if (!activeTabElement)
219
- return;
220
- const { offsetLeft, offsetWidth } = activeTabElement;
221
- if (visibleTabs.includes(activeIndex)) {
222
- activeTabElement.classList.add('active');
223
- setHighlightStyle({ left: offsetLeft, width: offsetWidth });
224
- return;
225
- }
226
126
  }, [activeTab, childrenArray, visibleTabs, overflowTabs, tabsContainerRef]);
227
127
  return { highlightStyle };
228
128
  };
@@ -232,11 +132,15 @@ exports.TabListContainer = styled_components_1.default.ul `
232
132
  gap: var(--md-tabs-gap);
233
133
  width: 100%;
234
134
  min-width: 0;
135
+ position: relative;
235
136
 
236
137
  &::before {
237
138
  content: '';
238
139
  position: absolute;
239
- inset: 0;
140
+ top: 0px;
141
+ left: 0px;
142
+ right: 0px;
143
+ bottom: 0px;
240
144
  border: var(--md-tabs-border);
241
145
  border-width: var(--md-tabs-border-width);
242
146
  pointer-events: none;
@@ -244,17 +148,11 @@ exports.TabListContainer = styled_components_1.default.ul `
244
148
 
245
149
  && {
246
150
  padding: var(--md-tabs-padding);
151
+ margin-block-end: 0;
247
152
  margin: 0;
248
153
 
249
154
  & > li {
250
- margin-bottom: 0;
251
- flex-shrink: 0;
252
-
253
- &.dropdown-tab {
254
- flex-shrink: 1;
255
- min-width: 0;
256
- max-width: 100%;
257
- }
155
+ margin-bottom: 0px;
258
156
  }
259
157
  }
260
158
  `;
@@ -264,7 +162,7 @@ exports.TabItem = styled_components_1.default.li `
264
162
  cursor: pointer;
265
163
  align-items: center;
266
164
  padding: var(--md-tabs-tab-wrapper-padding);
267
- z-index: var(--z-index-surface);
165
+ z-index: 1;
268
166
 
269
167
  ${({ active, size }) => active
270
168
  ? (0, styled_components_1.css) `
@@ -301,46 +199,6 @@ exports.TabItem = styled_components_1.default.li `
301
199
  }
302
200
  }
303
201
  `;
304
- const DropdownWrapper = styled_components_1.default.div.attrs((props) => ({
305
- style: Object.assign(Object.assign({}, (props.$top !== undefined && { '--dropdown-top': `${props.$top}px` })), (props.$left !== undefined && { '--dropdown-left': `${props.$left}px` })),
306
- })) `
307
- position: static;
308
- z-index: var(--z-index-raised);
309
- width: 100%;
310
- min-width: 0;
311
- `;
312
- const FixedPositionDropdown = (0, styled_components_1.default)(Dropdown_1.Dropdown) `
313
- position: static;
314
- width: 100%;
315
- min-width: 0;
316
-
317
- > div:first-child {
318
- width: 100%;
319
- min-width: 0;
320
- }
321
-
322
- > div:last-child {
323
- position: fixed;
324
- top: var(--dropdown-top, 0);
325
- left: var(--dropdown-left, 0);
326
- right: auto;
327
- bottom: auto;
328
- transform: none;
329
- padding-top: 0;
330
- max-width: min(400px, calc(100vw - 32px));
331
- max-height: calc(100vh - var(--dropdown-top, 0) - 32px);
332
- overflow-y: auto;
333
- z-index: var(--z-index-raised);
334
-
335
- ul {
336
- li {
337
- overflow: hidden;
338
- text-overflow: ellipsis;
339
- white-space: nowrap;
340
- }
341
- }
342
- }
343
- `;
344
202
  const HighlightBar = styled_components_1.default.div `
345
203
  position: absolute;
346
204
  top: 0;
@@ -360,19 +218,11 @@ const HighlightBar = styled_components_1.default.div `
360
218
  border-radius: var(--md-tabs-${({ size }) => size}-active-tab-border-radius);
361
219
  }
362
220
  `;
363
- const TabButtonText = styled_components_1.default.span `
364
- overflow: hidden;
365
- text-overflow: ellipsis;
366
- white-space: nowrap;
367
- flex: 1;
368
- min-width: 0;
369
- `;
370
221
  exports.TabButtonLink = (0, styled_components_1.default)(Button_1.Button) `
371
222
  color: var(--md-tabs-tab-text-color);
372
223
  font-family: var(--md-tabs-tab-font-family);
373
224
  font-style: var(--md-tabs-tab-font-style);
374
225
  background-color: var(--md-tabs-tab-bg-color);
375
- width: 100%;
376
226
 
377
227
  transition:
378
228
  background-color 300ms ease-in-out,
@@ -391,9 +241,9 @@ exports.TabButtonLink = (0, styled_components_1.default)(Button_1.Button) `
391
241
 
392
242
  &.active {
393
243
  color: var(--md-tabs-active-tab-text-color);
244
+ font-size: var(--md-tabs-${({ size }) => size}-active-tab-font-size);
394
245
  font-family: var(--md-tabs-active-tab-font-family);
395
246
  font-style: var(--md-tabs-active-tab-font-style);
396
- font-size: var(--md-tabs-${({ size }) => size}-active-tab-font-size);
397
247
  font-weight: var(--md-tabs-${({ size }) => size}-active-tab-font-weight);
398
248
  line-height: var(--md-tabs-${({ size }) => size}-active-tab-line-height);
399
249
  background-color: var(--md-tabs-active-tab-bg-color);
@@ -403,12 +253,12 @@ exports.TabButtonLink = (0, styled_components_1.default)(Button_1.Button) `
403
253
 
404
254
  &:hover {
405
255
  color: var(--md-tabs-hover-tab-text-color);
256
+ font-size: var(--md-tabs-${({ size }) => size}-hover-tab-font-size);
406
257
  font-family: var(--md-tabs-hover-tab-font-family);
407
258
  font-style: var(--md-tabs-hover-tab-font-style);
408
- font-size: var(--md-tabs-${({ size }) => size}-hover-tab-font-size);
409
259
  font-weight: var(--md-tabs-${({ size }) => size}-hover-tab-font-weight);
410
- line-height: var(--md-tabs-${({ size }) => size}-hover-tab-line-height);
411
260
  background-color: var(--md-tabs-hover-tab-bg-color);
261
+ line-height: var(--md-tabs-${({ size }) => size}-hover-tab-line-height);
412
262
  border-radius: var(--md-tabs-${({ size }) => size}-hover-tab-border-radius);
413
263
  padding: var(--md-tabs-${({ size }) => size}-hover-tab-padding);
414
264
  }
@@ -17,8 +17,7 @@ type TabsProps = {
17
17
  className?: string;
18
18
  size: TabsSize;
19
19
  initialTab?: string;
20
- forceReady?: boolean;
21
20
  };
22
- export declare function Tabs({ id, children, className, size, initialTab: propInitialTab, forceReady, }: TabsProps): JSX.Element;
21
+ export declare function Tabs({ id, children, className, size, initialTab: propInitialTab, }: TabsProps): JSX.Element;
23
22
  export declare const TabContent: import("styled-components").StyledComponent<"div", any, {}, never>;
24
23
  export {};
@@ -32,12 +32,14 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.TabContent = exports.TabsSize = void 0;
37
40
  exports.Tabs = Tabs;
38
41
  const react_1 = __importStar(require("react"));
39
- const react_router_dom_1 = require("react-router-dom");
40
- const styled_components_1 = __importStar(require("styled-components"));
42
+ const styled_components_1 = __importDefault(require("styled-components"));
41
43
  const hooks_1 = require("../../../core/hooks");
42
44
  const TabList_1 = require("../../../markdoc/components/Tabs/TabList");
43
45
  const utils_1 = require("../../../core/utils");
@@ -46,62 +48,22 @@ var TabsSize;
46
48
  TabsSize["SMALL"] = "small";
47
49
  TabsSize["MEDIUM"] = "medium";
48
50
  })(TabsSize || (exports.TabsSize = TabsSize = {}));
49
- function Tabs({ id, children, className, size, initialTab: propInitialTab, forceReady = false, }) {
51
+ function Tabs({ id, children, className, size, initialTab: propInitialTab, }) {
50
52
  var _a, _b;
51
- const childrenArray = react_1.default.Children.toArray(children);
52
- const [isReady, setIsReady] = (0, react_1.useState)(false);
53
- const containerRef = (0, react_1.useRef)(null);
53
+ const [childrenArray, setChildrenArray] = (0, react_1.useState)(react_1.default.Children.toArray(children));
54
54
  const initialTab = (_b = propInitialTab !== null && propInitialTab !== void 0 ? propInitialTab : (_a = childrenArray[0]) === null || _a === void 0 ? void 0 : _a.props.label) !== null && _b !== void 0 ? _b : '';
55
- const labelsHash = childrenArray.map((c) => c.props.label).join('|');
56
- const handleReadyChange = (0, react_1.useCallback)((ready) => {
57
- setIsReady(ready);
58
- }, []);
59
- // Reset isReady when children change (new page/tabs)
60
- // Use useLayoutEffect to run synchronously before paint
61
- (0, react_1.useLayoutEffect)(() => {
62
- setIsReady(false);
63
- }, [labelsHash]);
64
- const inRouter = (0, react_router_dom_1.useInRouterContext)();
65
- return (react_1.default.createElement(TabsView, { id: id, className: className, size: size, childrenArray: childrenArray, initialTab: initialTab, useActiveTab: inRouter ? useActiveTabWithRouter : useActiveTabWithoutRouter, isReady: isReady || forceReady, labelsHash: labelsHash, containerRef: containerRef, onReadyChange: handleReadyChange }));
66
- }
67
- function TabsView({ id, className, size, childrenArray, useActiveTab, initialTab, isReady, labelsHash, containerRef, onReadyChange, }) {
68
- const { activeTab, setActiveTab } = useActiveTab(initialTab, id, childrenArray);
69
- return (react_1.default.createElement(TabsContainer, { "data-component-name": "Markdoc/Tabs/Tabs", className: className, key: id, "$isReady": isReady },
70
- react_1.default.createElement(TabList_1.TabList, { key: labelsHash, size: size, childrenArray: childrenArray, activeTab: activeTab, onTabChange: setActiveTab, containerRef: containerRef, onReadyChange: onReadyChange }),
55
+ const { activeTab, setActiveTab } = (0, hooks_1.useActiveTab)({ tabsId: id, initialTab });
56
+ (0, react_1.useEffect)(() => {
57
+ setChildrenArray(react_1.default.Children.toArray(children));
58
+ }, [children]);
59
+ return (react_1.default.createElement(TabsContainer, { "data-component-name": "Markdoc/Tabs/Tabs", className: className, key: id },
60
+ react_1.default.createElement(TabList_1.TabList, { size: size, childrenArray: childrenArray, activeTab: activeTab, onTabChange: setActiveTab }),
71
61
  childrenArray.map((child, index) => {
72
62
  const { label } = child.props;
73
63
  const tabId = (0, utils_1.getTabId)(label, index);
74
64
  return label === activeTab ? (react_1.default.createElement(exports.TabContent, { key: `content-${tabId}`, id: `panel-${tabId}`, "aria-labelledby": `tab-${tabId}`, tabIndex: 0, role: "tabpanel" }, child.props.children)) : null;
75
65
  })));
76
66
  }
77
- /**
78
- * Validates that the active tab exists in children and resets to initial tab if not found.
79
- * Ensures tab state remains consistent when tab structure changes.
80
- */
81
- function useValidateActiveTab(activeTab, setActiveTab, childrenArray, initialTab) {
82
- (0, react_1.useEffect)(() => {
83
- const availableLabels = childrenArray.map((child) => child.props.label);
84
- if (activeTab && !availableLabels.includes(activeTab) && availableLabels.length > 0) {
85
- setActiveTab(initialTab);
86
- }
87
- }, [childrenArray, activeTab, initialTab, setActiveTab]);
88
- }
89
- const useActiveTabWithRouter = (initialTab, tabsId, childrenArray) => {
90
- const { activeTab, setActiveTab } = (0, hooks_1.useActiveTab)({ initialTab, tabsId });
91
- useValidateActiveTab(activeTab, setActiveTab, childrenArray, initialTab);
92
- return {
93
- activeTab,
94
- setActiveTab,
95
- };
96
- };
97
- const useActiveTabWithoutRouter = (initialTab, _tabsId, childrenArray) => {
98
- const [activeTab, setActiveTab] = (0, react_1.useState)(initialTab);
99
- useValidateActiveTab(activeTab, setActiveTab, childrenArray, initialTab);
100
- return {
101
- activeTab,
102
- setActiveTab,
103
- };
104
- };
105
67
  const TabsContainer = styled_components_1.default.div `
106
68
  position: relative;
107
69
  color: var(--md-tabs-container-text-color);
@@ -118,13 +80,6 @@ const TabsContainer = styled_components_1.default.div `
118
80
  margin: 0;
119
81
  padding: 0;
120
82
  }
121
-
122
- ${({ $isReady }) => !$isReady &&
123
- (0, styled_components_1.css) `
124
- opacity: 0;
125
- pointer-events: none;
126
- overflow: hidden;
127
- `}
128
83
  `;
129
84
  exports.TabContent = styled_components_1.default.div `
130
85
  color: var(--md-tabs-content-text-color);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.59.0-next.2",
3
+ "version": "0.59.0-rc.1",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -84,10 +84,10 @@
84
84
  "lodash.debounce": "^4.0.8",
85
85
  "lodash.throttle": "4.1.1",
86
86
  "nprogress": "0.2.0",
87
- "openapi-sampler": "1.6.2",
87
+ "openapi-sampler": "1.6.1",
88
88
  "react-calendar": "5.1.0",
89
89
  "react-date-picker": "11.0.0",
90
- "@redocly/config": "0.36.0",
90
+ "@redocly/config": "0.36.0-rc.1",
91
91
  "@redocly/realm-asyncapi-sdk": "0.5.0-next.0"
92
92
  },
93
93
  "scripts": {
@@ -46,7 +46,7 @@ export function CatalogEntityApiDescriptionRelations({
46
46
  }: CatalogEntityApiDescriptionRelationsProps): JSX.Element {
47
47
  return (
48
48
  <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations">
49
- <Tabs key={entity.id} forceReady={relations.length > 0} size={TabsSize.MEDIUM}>
49
+ <Tabs key={entity.id} size={TabsSize.MEDIUM}>
50
50
  <TabItem
51
51
  label="Operations"
52
52
  icon={<MoleculesIcon />}
@@ -74,7 +74,7 @@ export function CatalogEntityTeamRelations({
74
74
  }: CatalogEntityTeamRelationsProps): JSX.Element {
75
75
  return (
76
76
  <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations">
77
- <Tabs forceReady={relations.length > 0} size={TabsSize.MEDIUM}>
77
+ <Tabs size={TabsSize.MEDIUM}>
78
78
  <TabItem label="Members" icon={<PeopleIcon />} onClick={() => setFilter('type:user')}>
79
79
  <CatalogEntityRelationsTable
80
80
  key="members-table"
@@ -23,7 +23,11 @@ export function CatalogTagsWithTooltip({
23
23
  if (showPlaceholder) {
24
24
  return (
25
25
  <CatalogTagsWrapper data-component-name="Catalog/CatalogTagsWithTooltip">
26
- <Tag style={{ backgroundColor: 'var(--catalog-tags-placeholder-bg-color)' }} color="grey">
26
+ <Tag
27
+ variant="outline"
28
+ style={{ backgroundColor: 'var(--catalog-tags-placeholder-bg-color)' }}
29
+ color="grey"
30
+ >
27
31
  N/A
28
32
  </Tag>
29
33
  </CatalogTagsWrapper>