@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
@@ -13,75 +13,39 @@ type Tabs = {
13
13
  overflow: number[];
14
14
  };
15
15
 
16
- type UseTabsReturn = {
17
- setTabRef: (element: HTMLButtonElement | null, index: number) => void;
18
- onTabClick: (labelOrIndex: string | number) => void;
19
- handleKeyboard: (event: React.KeyboardEvent, index: number) => void;
20
- visibleTabs: number[];
21
- overflowTabs: number[];
22
- isReady: boolean;
23
- };
24
-
25
- type UseActiveTabProps = {
26
- initialTab: string;
27
- tabsId?: string;
28
- };
29
-
30
16
  const MORE_BUTTON_WIDTH = 80;
31
17
  const TABS_GAP = 8;
32
18
 
33
- export function useTabs({
34
- activeTab,
35
- onTabChange,
36
- totalTabs,
37
- containerRef,
38
- }: UseTabsProps): UseTabsReturn {
19
+ export function useTabs({ activeTab, onTabChange, totalTabs, containerRef }: UseTabsProps) {
39
20
  const [tabs, setTabs] = useState<Tabs>({
40
21
  visible: Array.from({ length: totalTabs }, (_, i) => i),
41
22
  overflow: [],
42
23
  });
43
- const [isReady, setIsReady] = useState(false);
44
- const isFirstCalculation = useRef(true);
24
+
45
25
  const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);
46
26
  const tabWidthsRef = useRef<number[]>([]);
47
27
  const tabLabelsRef = useRef<string[]>([]);
48
- const activeTabRef = useRef(activeTab);
49
- const calculateVisibleTabsRef = useRef<(() => void) | null>(null);
50
28
 
51
- // Synchronously update ref before any callbacks or effects run
52
- activeTabRef.current = activeTab;
29
+ const allTabsHidden = useMemo(() => tabs.visible.length === 0, [tabs.visible]);
53
30
 
54
- const setTabRef = useCallback(
55
- (element: HTMLButtonElement | null, index: number) => {
56
- tabRefs.current[index] = element;
31
+ const setTabRef = useCallback((element: HTMLButtonElement | null, index: number) => {
32
+ tabRefs.current[index] = element;
57
33
 
58
- const width = element?.offsetWidth;
59
- if (width) {
60
- tabWidthsRef.current[index] = width;
61
- }
62
-
63
- const label = element?.getAttribute('data-label');
64
- if (label) {
65
- tabLabelsRef.current[index] = label;
66
- }
34
+ const width = element?.offsetWidth;
35
+ if (width) {
36
+ tabWidthsRef.current[index] = width;
37
+ }
67
38
 
68
- // Trigger calculation once all tabs are registered
69
- if (
70
- isFirstCalculation.current &&
71
- tabWidthsRef.current.length >= totalTabs &&
72
- tabLabelsRef.current.length >= totalTabs &&
73
- calculateVisibleTabsRef.current
74
- ) {
75
- requestAnimationFrame(calculateVisibleTabsRef.current);
76
- }
77
- },
78
- [totalTabs],
79
- );
39
+ const label = element?.getAttribute('data-label');
40
+ if (label) {
41
+ tabLabelsRef.current[index] = label;
42
+ }
43
+ }, []);
80
44
 
81
- const focusTab = useCallback((index: number) => {
45
+ const focusTab = (index: number) => {
82
46
  const currentElement = tabRefs.current[index];
83
47
  currentElement?.focus();
84
- }, []);
48
+ };
85
49
 
86
50
  const onTabSelect = useCallback(
87
51
  (index: number) => {
@@ -89,7 +53,7 @@ export function useTabs({
89
53
  const label = tabRefs.current[index]?.getAttribute('data-label');
90
54
  if (label) onTabChange(label);
91
55
  },
92
- [onTabChange, focusTab],
56
+ [onTabChange],
93
57
  );
94
58
 
95
59
  const handleKeyboard = useCallback(
@@ -113,19 +77,30 @@ export function useTabs({
113
77
  [totalTabs, onTabSelect],
114
78
  );
115
79
 
116
- const replaceLastVisibleTabWithClickedOverflowTab = useCallback((clickedIndex: number) => {
117
- setTabs((prevTabs) => {
118
- const { visible: visibleTabs, overflow: overflowTabs } = prevTabs;
119
-
120
- const sortedVisible = [...visibleTabs].sort((a, b) => a - b);
121
- const lastVisible = sortedVisible[sortedVisible.length - 1];
80
+ const replaceLastVisibleTabWithClickedOverflowTab = useCallback(
81
+ (clickedIndex: number) => {
82
+ const { visible: visibleTabs, overflow: overflowTabs } = tabs;
83
+
84
+ // Indexes of visible tabs should be sorted(asc), to replace the last visible tab with the clicked tab
85
+ const newVisibleTabs = [...visibleTabs].sort((a, b) => a - b);
86
+ const newOverflowTabs = [...overflowTabs];
87
+
88
+ const clickedIdxInOverflow = newOverflowTabs.indexOf(clickedIndex);
89
+ if (clickedIdxInOverflow !== -1) {
90
+ const lastVisible = newVisibleTabs[newVisibleTabs.length - 1];
91
+ newOverflowTabs.splice(clickedIdxInOverflow, 1);
92
+ newOverflowTabs.unshift(lastVisible);
93
+ newVisibleTabs.splice(newVisibleTabs.length - 1, 1);
94
+ newVisibleTabs.unshift(clickedIndex);
95
+ }
122
96
 
123
- return {
124
- visible: visibleTabs.map((idx) => (idx === lastVisible ? clickedIndex : idx)),
125
- overflow: overflowTabs.map((idx) => (idx === clickedIndex ? lastVisible : idx)),
126
- };
127
- });
128
- }, []);
97
+ setTabs({
98
+ visible: newVisibleTabs,
99
+ overflow: newOverflowTabs,
100
+ });
101
+ },
102
+ [tabs],
103
+ );
129
104
 
130
105
  const onTabClick = useCallback(
131
106
  (labelOrIndex: string | number) => {
@@ -136,18 +111,18 @@ export function useTabs({
136
111
 
137
112
  if (clickedIndex === -1) return;
138
113
 
139
- const label = tabLabelsRef.current[clickedIndex];
140
- if (!label) return;
141
-
142
- // If this is an overflow tab, replace it with a visible one
143
- if (tabs.overflow.includes(clickedIndex)) {
114
+ const hasOverflowTabs = tabs.overflow.length > 0;
115
+ if (hasOverflowTabs && !allTabsHidden && tabs.overflow.includes(clickedIndex)) {
144
116
  replaceLastVisibleTabWithClickedOverflowTab(clickedIndex);
145
117
  }
146
118
 
147
- onTabChange(label);
148
- focusTab(clickedIndex);
119
+ const label = tabLabelsRef.current[clickedIndex];
120
+ if (label) {
121
+ onTabChange(label);
122
+ focusTab(clickedIndex);
123
+ }
149
124
  },
150
- [tabs.overflow, onTabChange, replaceLastVisibleTabWithClickedOverflowTab, focusTab],
125
+ [allTabsHidden, tabs.overflow, onTabChange, replaceLastVisibleTabWithClickedOverflowTab],
151
126
  );
152
127
 
153
128
  const calculateVisibleTabs = useCallback(() => {
@@ -156,141 +131,87 @@ export function useTabs({
156
131
 
157
132
  const containerWidth = container.offsetWidth;
158
133
  const tabWidths = tabWidthsRef.current;
159
- const tabLabels = tabLabelsRef.current;
160
-
161
- // Wait until all tabs are registered before calculating
162
- if (tabWidths.length < totalTabs || tabLabels.length < totalTabs) {
163
- return;
164
- }
165
-
166
- // Check if container has proper width (not zero)
167
- if (containerWidth === 0) {
168
- return;
169
- }
170
-
171
- // Find active tab index by label in tabLabelsRef, not by DOM element
172
- // because tab might not be rendered if it's in overflow
173
- const activeTabIndex = tabLabels.findIndex((label) => label === activeTabRef.current);
134
+ const activeTabIndex = tabRefs.current.findIndex(
135
+ (ref) => ref?.getAttribute('data-label') === activeTab,
136
+ );
174
137
 
138
+ // Active tab should always be visible, so we include it at the beginning of the array
175
139
  let tabsWidth = activeTabIndex !== -1 ? tabWidths[activeTabIndex] : 0;
176
- const visibleTabs = activeTabIndex !== -1 ? [activeTabIndex] : [];
177
- const overflowTabs = [];
140
+ const visible = activeTabIndex !== -1 ? [activeTabIndex] : [];
141
+ const overflow = [];
178
142
 
179
143
  for (let i = 0; i < tabWidths.length; i++) {
180
- if (i === activeTabIndex) continue;
144
+ // Skip active tab, it was added initially
145
+ if (i === activeTabIndex) {
146
+ continue;
147
+ }
181
148
 
182
149
  const tabWidthWithGap = tabWidths[i] + TABS_GAP;
183
150
  const projectedWidth = tabsWidth + tabWidthWithGap;
184
151
 
185
152
  if (projectedWidth <= containerWidth) {
186
- visibleTabs.push(i);
153
+ visible.push(i);
187
154
  tabsWidth += tabWidthWithGap;
188
155
  } else {
189
- overflowTabs.push(i);
156
+ overflow.push(i);
190
157
  }
191
158
  }
192
159
 
193
- if (overflowTabs.length > 0) {
160
+ if (overflow.length > 0) {
194
161
  tabsWidth += MORE_BUTTON_WIDTH;
195
162
 
196
- while (tabsWidth > containerWidth && visibleTabs.length > 1) {
197
- const removed = visibleTabs.pop();
198
- // Never remove the active tab - it should always stay visible or be the last one
199
- if (removed !== undefined && removed !== activeTabIndex) {
200
- overflowTabs.unshift(removed);
163
+ // Remove tabs starting from the end of the array until the width of the visible tabs is less than the container width
164
+ while (tabsWidth > containerWidth && visible.length) {
165
+ const removed = visible.pop();
166
+ if (removed !== undefined) {
167
+ overflow.unshift(removed);
201
168
  tabsWidth -= tabWidths[removed];
202
- } else if (removed === activeTabIndex) {
203
- // Put it back if we accidentally removed the active tab
204
- visibleTabs.push(removed);
205
- break;
206
169
  }
207
170
  }
208
-
209
- // If even with only the active tab visible, it doesn't fit with More button,
210
- // move all tabs to overflow (show only dropdown)
211
- if (tabsWidth > containerWidth && visibleTabs.length === 1) {
212
- overflowTabs.unshift(...visibleTabs);
213
- visibleTabs.length = 0;
214
- }
215
171
  }
216
172
 
217
173
  setTabs({
218
- visible: visibleTabs,
219
- overflow: overflowTabs,
174
+ visible,
175
+ overflow,
220
176
  });
177
+ }, [containerRef, activeTab]);
221
178
 
222
- // Set ready state on first calculation
223
- if (isFirstCalculation.current) {
224
- isFirstCalculation.current = false;
225
- setIsReady(true);
226
- }
227
- }, [containerRef, totalTabs]);
228
-
229
- // Store calculateVisibleTabs in ref for use in setTabRef
230
- calculateVisibleTabsRef.current = calculateVisibleTabs;
231
-
232
- // Reset isFirstCalculation when totalTabs changes (new page/tabs)
233
- useEffect(() => {
234
- isFirstCalculation.current = true;
235
- setIsReady(false);
236
- // Clear refs so we wait for new tabs to register
237
- tabWidthsRef.current = [];
238
- tabLabelsRef.current = [];
239
- }, [totalTabs]);
240
-
241
- // Call calculateVisibleTabs on first render and resize
242
179
  useEffect(() => {
243
- const container = containerRef?.current;
244
- if (!container) return;
245
-
246
- let resizeTimeout: number | null = null;
247
-
248
- // Use ResizeObserver to wait until container has proper size
249
- const resizeObserver = new ResizeObserver(() => {
250
- if (resizeTimeout) cancelAnimationFrame(resizeTimeout);
251
- resizeTimeout = requestAnimationFrame(calculateVisibleTabs);
252
- });
253
-
254
- resizeObserver.observe(container);
180
+ if (!containerRef?.current) return;
255
181
 
182
+ let resizeTimeout = requestAnimationFrame(calculateVisibleTabs);
256
183
  const handleResize = () => {
257
- if (resizeTimeout) cancelAnimationFrame(resizeTimeout);
184
+ if (resizeTimeout) {
185
+ cancelAnimationFrame(resizeTimeout);
186
+ }
258
187
  resizeTimeout = requestAnimationFrame(calculateVisibleTabs);
259
188
  };
260
189
 
261
190
  window.addEventListener('resize', handleResize);
262
-
263
191
  return () => {
264
- resizeObserver.disconnect();
265
192
  window.removeEventListener('resize', handleResize);
266
- if (resizeTimeout) cancelAnimationFrame(resizeTimeout);
193
+ cancelAnimationFrame(resizeTimeout);
267
194
  };
268
195
  }, [containerRef, totalTabs, calculateVisibleTabs]);
269
196
 
270
- // Recalculate when activeTab changes to ensure it's visible
271
- useEffect(() => {
272
- if (!containerRef?.current || isFirstCalculation.current) return;
273
- requestAnimationFrame(calculateVisibleTabs);
274
- }, [activeTab, containerRef, calculateVisibleTabs]);
275
-
276
197
  return {
277
198
  setTabRef,
278
199
  onTabClick,
279
200
  handleKeyboard,
280
201
  visibleTabs: tabs.visible,
281
202
  overflowTabs: tabs.overflow,
282
- isReady,
203
+ allTabsHidden,
283
204
  };
284
205
  }
285
206
 
207
+ type UseActiveTabProps = {
208
+ initialTab: string;
209
+ tabsId?: string;
210
+ };
211
+
286
212
  export const useActiveTab = ({ initialTab, tabsId }: UseActiveTabProps) => {
287
213
  const [searchParams, setSearchParams] = useSearchParams();
288
- const initialTabValue = useMemo(
289
- () => getInitialTab({ initialTab, searchParams, tabsId }),
290
- // eslint-disable-next-line react-hooks/exhaustive-deps
291
- [],
292
- );
293
- const [activeTab, setActiveTab] = useState(initialTabValue);
214
+ const [activeTab, setActiveTab] = useState(getInitialTab({ initialTab, searchParams, tabsId }));
294
215
  const prevActiveTabRef = useRef(activeTab);
295
216
 
296
217
  useEffect(() => {
@@ -307,13 +228,10 @@ export const useActiveTab = ({ initialTab, tabsId }: UseActiveTabProps) => {
307
228
  });
308
229
  }, [activeTab, setSearchParams, tabsId]);
309
230
 
310
- return useMemo(
311
- () => ({
312
- activeTab,
313
- setActiveTab,
314
- }),
315
- [activeTab],
316
- );
231
+ return {
232
+ activeTab,
233
+ setActiveTab,
234
+ };
317
235
  };
318
236
 
319
237
  type GetInitialTabProps = {
@@ -86,7 +86,6 @@ export type ThemeHooks = {
86
86
  useSearch: (
87
87
  product?: string,
88
88
  autoSearchDisabled?: boolean,
89
- searchSessionId?: string,
90
89
  ) => {
91
90
  query: string;
92
91
  setQuery: React.Dispatch<React.SetStateAction<string>>;
@@ -108,10 +107,7 @@ export type ThemeHooks = {
108
107
  advancedSearch?: boolean;
109
108
  askAi?: boolean;
110
109
  };
111
- useAiSearch: (
112
- options?: { filter?: SearchFilterItem[] },
113
- searchSessionId?: string,
114
- ) => {
110
+ useAiSearch: (options?: { filter?: SearchFilterItem[] }) => {
115
111
  askQuestion: (question: string, history?: AiSearchConversationItem[]) => void;
116
112
  isGeneratingResponse: boolean;
117
113
  question: string;
@@ -0,0 +1,13 @@
1
+ import { useCallback } from 'react';
2
+
3
+ import type { CatalogItem } from '@redocly/theme';
4
+
5
+ export function useProcessScorecard(): {
6
+ processScorecard: <T = any>(scorecard: T, api: CatalogItem) => T;
7
+ processInfo: <T>(info: T) => T;
8
+ } {
9
+ return {
10
+ processScorecard: useCallback((scorecard) => scorecard, []),
11
+ processInfo: useCallback((info) => info, []),
12
+ };
13
+ }
@@ -35,28 +35,19 @@ export const AiStarsIcon = styled(Icon).attrs(() => ({
35
35
  height: ${({ size }) => size || '16px'};
36
36
  width: ${({ size }) => size || '16px'};
37
37
 
38
- ${({ background, borderRadius, margin, padding, size }) =>
38
+ ${({ background, borderRadius, margin }) =>
39
39
  background &&
40
40
  `
41
41
  display: flex;
42
42
  align-items: center;
43
43
  justify-content: center;
44
- flex-shrink: 0;
45
44
 
46
45
  background: ${getCssColorVariable(background)};
47
- width: ${size || '16px'};
48
- height: ${size || '16px'};
49
46
 
50
- padding: ${padding || 'var(--spacing-xs)'};
47
+ padding: var(--spacing-xs);
51
48
  margin: ${margin || '0'};
52
49
 
53
50
  border-radius: ${background && borderRadius ? borderRadius : 'none'};
54
-
55
- svg {
56
- width: calc(${size || '16px'} - 2 * (${padding || 'var(--spacing-xs)'}));
57
- height: calc(${size || '16px'} - 2 * (${padding || 'var(--spacing-xs)'}));
58
- flex-shrink: 0;
59
- }
60
51
  `}
61
52
 
62
53
  color: ${({ color }) => color && getCssColorVariable(color)};
@@ -6,11 +6,29 @@ import type { IconProps } from '@redocly/theme/icons/types';
6
6
  import { getCssColorVariable } from '@redocly/theme/core/utils';
7
7
 
8
8
  const Icon = (props: IconProps) => (
9
- <svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" {...props}>
10
- <g>
11
- <path d="M14.625 6.19973C14.625 8.69176 12.6173 10.712 10.1406 10.712H2.8125V10.2717C5.04753 10.2717 6.85938 8.44864 6.85938 6.19973C6.85938 3.95082 5.04753 2.12772 2.8125 2.12772V1.6875H10.1406C12.6173 1.6875 14.625 3.70769 14.625 6.19973Z" />
12
- <path d="M14.625 16.875C14.625 14.383 12.6173 12.3628 10.1406 12.3628H2.8125V12.803C5.04753 12.803 6.85938 14.6261 6.85938 16.875H14.625Z" />
9
+ <svg
10
+ width="18"
11
+ height="18"
12
+ viewBox="0 0 18 18"
13
+ fill="none"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ {...props}
16
+ >
17
+ <g clipPath="url(#clip0_4053_1165)">
18
+ <path
19
+ d="M14.625 6.19973C14.625 8.69176 12.6173 10.712 10.1406 10.712H2.8125V10.2717C5.04753 10.2717 6.85938 8.44864 6.85938 6.19973C6.85938 3.95082 5.04753 2.12772 2.8125 2.12772V1.6875H10.1406C12.6173 1.6875 14.625 3.70769 14.625 6.19973Z"
20
+ fill="#2467F2"
21
+ />
22
+ <path
23
+ d="M14.625 16.875C14.625 14.383 12.6173 12.3628 10.1406 12.3628H2.8125V12.803C5.04753 12.803 6.85938 14.6261 6.85938 16.875H14.625Z"
24
+ fill="#2467F2"
25
+ />
13
26
  </g>
27
+ <defs>
28
+ <clipPath id="clip0_4053_1165">
29
+ <rect width="18" height="18" fill="white" />
30
+ </clipPath>
31
+ </defs>
14
32
  </svg>
15
33
  );
16
34
 
package/src/index.ts CHANGED
@@ -93,9 +93,11 @@ export * from '@redocly/theme/components/Sidebar/Sidebar';
93
93
  /* OpenApiDocs */
94
94
  export * from '@redocly/theme/components/OpenApiDocs/hooks/AfterOpenApiOperation';
95
95
  export * from '@redocly/theme/components/OpenApiDocs/hooks/AfterOpenApiTitle';
96
+ export * from '@redocly/theme/components/OpenApiDocs/hooks/AfterOpenApiDescription';
96
97
  export * from '@redocly/theme/components/OpenApiDocs/hooks/BeforeOpenApiOperation';
97
98
  export * from '@redocly/theme/components/OpenApiDocs/hooks/OpenApiFooter';
98
99
  export * from '@redocly/theme/components/OpenApiDocs/hooks/OpenApiHeader';
100
+ export * from '@redocly/theme/components/OpenApiDocs/hooks/AdditionalOverviewInfo';
99
101
  /* SidebarActions */
100
102
  export * from '@redocly/theme/components/SidebarActions/ChangeViewButton';
101
103
  export * from '@redocly/theme/components/SidebarActions/SidebarActions';