docusaurus-theme-openapi-docs 2.1.3 → 3.0.0-beta.10

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 (95) hide show
  1. package/lib/markdown/utils.d.ts +2 -1
  2. package/lib/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/index.d.ts +13 -0
  3. package/lib/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/index.js +199 -124
  4. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.d.ts +4 -0
  5. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.js +25 -19
  6. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/Element.d.ts +4 -0
  7. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/Element.js +27 -16
  8. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.d.ts +4 -0
  9. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.js +116 -97
  10. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.d.ts +3 -0
  11. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.js +115 -54
  12. package/lib/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.d.ts +6 -0
  13. package/lib/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.js +41 -30
  14. package/lib/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.d.ts +14 -0
  15. package/lib/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.js +201 -121
  16. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.d.ts +3 -0
  17. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.js +36 -24
  18. package/lib/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.d.ts +7 -0
  19. package/lib/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.js +35 -28
  20. package/lib/theme/ApiExplorer/ApiCodeBlock/index.d.ts +3 -0
  21. package/lib/theme/ApiExplorer/ApiCodeBlock/index.js +72 -14
  22. package/lib/theme/ApiExplorer/CodeSnippets/languages.json +1290 -0
  23. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +4 -2
  24. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +15 -0
  25. package/lib/theme/ApiExplorer/CodeTabs/index.js +122 -76
  26. package/lib/theme/ApiExplorer/FloatingButton/_FloatingButton.scss +3 -1
  27. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +4 -4
  28. package/lib/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +2 -1
  29. package/lib/theme/ApiExplorer/Request/_Request.scss +4 -6
  30. package/lib/theme/ApiExplorer/Response/_Response.scss +4 -2
  31. package/lib/theme/ApiExplorer/Response/index.js +19 -19
  32. package/lib/theme/ApiExplorer/index.js +0 -4
  33. package/lib/theme/ApiItem/Layout/index.js +3 -0
  34. package/lib/theme/ApiItem/index.js +6 -5
  35. package/lib/theme/ApiLogo/index.d.ts +2 -2
  36. package/lib/theme/ApiTabs/_ApiTabs.scss +3 -1
  37. package/lib/theme/ApiTabs/index.d.ts +7 -0
  38. package/lib/theme/ApiTabs/index.js +152 -98
  39. package/lib/theme/DiscriminatorTabs/index.d.ts +3 -0
  40. package/lib/theme/DiscriminatorTabs/index.js +146 -94
  41. package/lib/theme/MimeTabs/index.d.ts +6 -0
  42. package/lib/theme/MimeTabs/index.js +163 -114
  43. package/lib/theme/OperationTabs/_OperationTabs.scss +4 -1
  44. package/lib/theme/OperationTabs/index.d.ts +3 -0
  45. package/lib/theme/OperationTabs/index.js +148 -103
  46. package/lib/theme/ParamsItem/index.d.ts +23 -0
  47. package/lib/theme/ParamsItem/index.js +168 -123
  48. package/lib/theme/ResponseSamples/index.d.ts +8 -0
  49. package/lib/theme/ResponseSamples/index.js +18 -13
  50. package/lib/theme/SchemaItem/index.d.ts +12 -0
  51. package/lib/theme/SchemaItem/index.js +123 -88
  52. package/lib/theme/SchemaTabs/_SchemaTabs.scss +0 -4
  53. package/lib/theme/SchemaTabs/index.d.ts +3 -0
  54. package/lib/theme/SchemaTabs/index.js +142 -91
  55. package/lib/theme/styles.scss +4 -0
  56. package/package.json +8 -7
  57. package/src/markdown/utils.ts +4 -2
  58. package/src/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/{index.js → index.tsx} +21 -8
  59. package/src/theme/ApiExplorer/ApiCodeBlock/Container/{index.js → index.tsx} +6 -3
  60. package/src/theme/ApiExplorer/ApiCodeBlock/Content/{Element.js → Element.tsx} +5 -1
  61. package/src/theme/ApiExplorer/ApiCodeBlock/Content/{String.js → String.tsx} +5 -5
  62. package/src/theme/ApiExplorer/ApiCodeBlock/CopyButton/{index.js → index.tsx} +8 -3
  63. package/src/theme/ApiExplorer/ApiCodeBlock/ExitButton/{index.js → index.tsx} +9 -1
  64. package/src/theme/ApiExplorer/ApiCodeBlock/ExpandButton/{index.js → index.tsx} +13 -3
  65. package/src/theme/ApiExplorer/ApiCodeBlock/Line/{index.js → index.tsx} +2 -1
  66. package/src/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/{index.js → index.tsx} +11 -1
  67. package/src/theme/ApiExplorer/ApiCodeBlock/{index.js → index.tsx} +10 -5
  68. package/src/theme/ApiExplorer/CodeSnippets/languages.json +1290 -0
  69. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +4 -2
  70. package/src/theme/ApiExplorer/CodeTabs/{index.js → index.tsx} +56 -26
  71. package/src/theme/ApiExplorer/FloatingButton/_FloatingButton.scss +3 -1
  72. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +4 -4
  73. package/src/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +2 -1
  74. package/src/theme/ApiExplorer/Request/_Request.scss +4 -6
  75. package/src/theme/ApiExplorer/Response/_Response.scss +4 -2
  76. package/src/theme/ApiExplorer/Response/index.tsx +2 -2
  77. package/src/theme/ApiExplorer/index.tsx +0 -3
  78. package/src/theme/ApiItem/Layout/index.tsx +3 -0
  79. package/src/theme/ApiItem/index.tsx +3 -4
  80. package/src/theme/ApiLogo/index.tsx +1 -1
  81. package/src/theme/ApiTabs/_ApiTabs.scss +3 -1
  82. package/src/theme/ApiTabs/{index.js → index.tsx} +60 -26
  83. package/src/theme/DiscriminatorTabs/{index.js → index.tsx} +57 -24
  84. package/src/theme/MimeTabs/{index.js → index.tsx} +58 -26
  85. package/src/theme/OperationTabs/_OperationTabs.scss +4 -1
  86. package/src/theme/OperationTabs/{index.js → index.tsx} +54 -25
  87. package/src/theme/ParamsItem/{index.js → index.tsx} +31 -14
  88. package/src/theme/ResponseSamples/{index.js → index.tsx} +10 -1
  89. package/src/theme/SchemaItem/{index.js → index.tsx} +18 -9
  90. package/src/theme/SchemaTabs/_SchemaTabs.scss +0 -4
  91. package/src/theme/SchemaTabs/{index.js → index.tsx} +56 -25
  92. package/src/theme/styles.scss +4 -0
  93. package/src/theme-classic.d.ts +69 -2
  94. package/src/theme-openapi.d.ts +2 -0
  95. package/tsconfig.json +4 -1
@@ -5,31 +5,55 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { cloneElement, useRef, useEffect, useState } from "react";
8
+ import React, {
9
+ cloneElement,
10
+ useRef,
11
+ useEffect,
12
+ useState,
13
+ ReactElement,
14
+ } from "react";
9
15
 
10
16
  import {
17
+ sanitizeTabsChildren,
18
+ TabProps,
11
19
  useScrollPositionBlocker,
12
20
  useTabs,
13
21
  } from "@docusaurus/theme-common/internal";
22
+ import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
14
23
  import useIsBrowser from "@docusaurus/useIsBrowser";
15
24
  import clsx from "clsx";
16
25
  import flatten from "lodash/flatten";
17
26
 
18
- function TabList({ className, block, selectedValue, selectValue, tabValues }) {
19
- const tabRefs = [];
27
+ function TabList({
28
+ className,
29
+ block,
30
+ selectedValue,
31
+ selectValue,
32
+ tabValues,
33
+ }: TabProps & ReturnType<typeof useTabs>) {
34
+ const tabRefs: (HTMLLIElement | null)[] = [];
20
35
  const { blockElementScrollPositionUntilNextRender } =
21
36
  useScrollPositionBlocker();
22
- const handleTabChange = (event) => {
37
+
38
+ const handleTabChange = (
39
+ event:
40
+ | React.FocusEvent<HTMLLIElement>
41
+ | React.MouseEvent<HTMLLIElement>
42
+ | React.KeyboardEvent<HTMLLIElement>
43
+ ) => {
23
44
  const newTab = event.currentTarget;
24
45
  const newTabIndex = tabRefs.indexOf(newTab);
25
- const newTabValue = tabValues[newTabIndex].value;
46
+ const newTabValue = tabValues[newTabIndex]!.value;
47
+
26
48
  if (newTabValue !== selectedValue) {
27
49
  blockElementScrollPositionUntilNextRender(newTab);
28
50
  selectValue(newTabValue);
29
51
  }
30
52
  };
31
- const handleKeydown = (event) => {
53
+
54
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
32
55
  let focusElement = null;
56
+
33
57
  switch (event.key) {
34
58
  case "Enter": {
35
59
  handleTabChange(event);
@@ -37,28 +61,29 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
37
61
  }
38
62
  case "ArrowRight": {
39
63
  const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
40
- focusElement = tabRefs[nextTab] ?? tabRefs[0];
64
+ focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
41
65
  break;
42
66
  }
43
67
  case "ArrowLeft": {
44
68
  const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
45
- focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
69
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
46
70
  break;
47
71
  }
48
72
  default:
49
73
  break;
50
74
  }
75
+
51
76
  focusElement?.focus();
52
77
  };
53
78
 
54
- const tabItemListContainerRef = useRef(null);
55
- const [showTabArrows, setShowTabArrows] = useState(false);
79
+ const tabItemListContainerRef = useRef<HTMLUListElement>(null);
80
+ const [showTabArrows, setShowTabArrows] = useState<boolean>(false);
56
81
 
57
82
  useEffect(() => {
58
83
  const resizeObserver = new ResizeObserver((entries) => {
59
84
  for (let entry of entries) {
60
85
  requestAnimationFrame(() => {
61
- if (entry.target.offsetWidth < entry.target.scrollWidth) {
86
+ if (entry.target.clientWidth < entry.target.scrollWidth) {
62
87
  setShowTabArrows(true);
63
88
  } else {
64
89
  setShowTabArrows(false);
@@ -67,7 +92,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
67
92
  }
68
93
  });
69
94
 
70
- resizeObserver.observe(tabItemListContainerRef.current);
95
+ resizeObserver.observe(tabItemListContainerRef.current!);
71
96
 
72
97
  return () => {
73
98
  resizeObserver.disconnect();
@@ -75,11 +100,11 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
75
100
  }, []);
76
101
 
77
102
  const handleRightClick = () => {
78
- tabItemListContainerRef.current.scrollLeft += 90;
103
+ tabItemListContainerRef.current!.scrollLeft += 90;
79
104
  };
80
105
 
81
106
  const handleLeftClick = () => {
82
- tabItemListContainerRef.current.scrollLeft -= 90;
107
+ tabItemListContainerRef.current!.scrollLeft -= 90;
83
108
  };
84
109
 
85
110
  return (
@@ -118,7 +143,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
118
143
  className={clsx(
119
144
  "tabs__item",
120
145
  "openapi-tabs__discriminator-item",
121
- attributes?.className,
146
+ attributes?.className as string,
122
147
  {
123
148
  active: selectedValue === value,
124
149
  }
@@ -140,12 +165,18 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
140
165
  </div>
141
166
  );
142
167
  }
143
- function TabContent({ lazy, children, selectedValue }) {
144
- // eslint-disable-next-line no-param-reassign
145
- children = Array.isArray(children) ? children : [children];
146
- const flattenedChildren = flatten(children);
168
+
169
+ function TabContent({
170
+ lazy,
171
+ children,
172
+ selectedValue,
173
+ }: TabProps & ReturnType<typeof useTabs>): React.JSX.Element | null {
174
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
175
+ Boolean
176
+ ) as ReactElement<TabItemProps>[];
177
+ const flattenedChildTabs = flatten(childTabs);
147
178
  if (lazy) {
148
- const selectedTabItem = flattenedChildren.find(
179
+ const selectedTabItem = flattenedChildTabs.find(
149
180
  (tabItem) => tabItem.props.value === selectedValue
150
181
  );
151
182
  if (!selectedTabItem) {
@@ -156,7 +187,7 @@ function TabContent({ lazy, children, selectedValue }) {
156
187
  }
157
188
  return (
158
189
  <div className="margin-top--md">
159
- {children.map((tabItem, i) =>
190
+ {childTabs.map((tabItem, i) =>
160
191
  cloneElement(tabItem, {
161
192
  key: i,
162
193
  hidden: tabItem.props.value !== selectedValue,
@@ -165,7 +196,7 @@ function TabContent({ lazy, children, selectedValue }) {
165
196
  </div>
166
197
  );
167
198
  }
168
- function TabsComponent(props) {
199
+ function TabsComponent(props: TabProps): React.JSX.Element {
169
200
  const tabs = useTabs(props);
170
201
  return (
171
202
  <div className="openapi-tabs__container">
@@ -174,7 +205,7 @@ function TabsComponent(props) {
174
205
  </div>
175
206
  );
176
207
  }
177
- export default function DiscriminatorTabs(props) {
208
+ export default function DiscriminatorTabs(props: TabProps): React.JSX.Element {
178
209
  const isBrowser = useIsBrowser();
179
210
  return (
180
211
  <TabsComponent
@@ -182,6 +213,8 @@ export default function DiscriminatorTabs(props) {
182
213
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
183
214
  key={String(isBrowser)}
184
215
  {...props}
185
- />
216
+ >
217
+ {sanitizeTabsChildren(props.children)}
218
+ </TabsComponent>
186
219
  );
187
220
  }
@@ -5,18 +5,32 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { cloneElement, useEffect, useState, useRef } from "react";
8
+ import React, {
9
+ cloneElement,
10
+ useEffect,
11
+ useState,
12
+ useRef,
13
+ ReactElement,
14
+ } from "react";
9
15
 
10
16
  import {
17
+ sanitizeTabsChildren,
18
+ TabProps,
11
19
  useScrollPositionBlocker,
12
20
  useTabs,
13
21
  } from "@docusaurus/theme-common/internal";
22
+ import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
14
23
  import useIsBrowser from "@docusaurus/useIsBrowser";
15
- import { setAccept } from "@theme/ApiExplorer/Accept/slice";
24
+ import setAccept from "@theme/ApiExplorer/Accept/slice";
16
25
  import { setContentType } from "@theme/ApiExplorer/ContentType/slice";
17
26
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
27
+ import { RootState } from "@theme/ApiItem/store";
18
28
  import clsx from "clsx";
19
29
 
30
+ export interface Props {
31
+ schemaType: any;
32
+ }
33
+
20
34
  function TabList({
21
35
  className,
22
36
  block,
@@ -24,8 +38,8 @@ function TabList({
24
38
  selectValue,
25
39
  tabValues,
26
40
  schemaType,
27
- }) {
28
- const tabRefs = [];
41
+ }: Props & TabProps & ReturnType<typeof useTabs>): React.JSX.Element {
42
+ const tabRefs: (HTMLLIElement | null)[] = [];
29
43
  const { blockElementScrollPositionUntilNextRender } =
30
44
  useScrollPositionBlocker();
31
45
 
@@ -34,8 +48,12 @@ function TabList({
34
48
  const isRequestSchema = schemaType?.toLowerCase() === "request";
35
49
 
36
50
  const [selectedValue, setSelectedValue] = useState(selectedValueProp);
37
- const contentTypeVal = useTypedSelector((state) => state.contentType.value);
38
- const acceptTypeVal = useTypedSelector((state) => state.accept.value);
51
+ const contentTypeVal = useTypedSelector(
52
+ (state: RootState) => state.contentType.value
53
+ );
54
+ const acceptTypeVal = useTypedSelector(
55
+ (state: RootState) => state.accept.value
56
+ );
39
57
 
40
58
  useEffect(() => {
41
59
  if (tabRefs.length > 1) {
@@ -48,7 +66,12 @@ function TabList({
48
66
  // eslint-disable-next-line react-hooks/exhaustive-deps
49
67
  }, [contentTypeVal, acceptTypeVal]);
50
68
 
51
- const handleTabChange = (event) => {
69
+ const handleTabChange = (
70
+ event:
71
+ | React.FocusEvent<HTMLLIElement>
72
+ | React.MouseEvent<HTMLLIElement>
73
+ | React.KeyboardEvent<HTMLLIElement>
74
+ ) => {
52
75
  event.preventDefault();
53
76
  const newTab = event.currentTarget;
54
77
  const newTabIndex = tabRefs.indexOf(newTab);
@@ -65,8 +88,9 @@ function TabList({
65
88
  }
66
89
  };
67
90
 
68
- const handleKeydown = (event) => {
69
- let focusElement = null;
91
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
92
+ let focusElement: HTMLLIElement | null = null;
93
+
70
94
  switch (event.key) {
71
95
  case "Enter": {
72
96
  handleTabChange(event);
@@ -74,28 +98,29 @@ function TabList({
74
98
  }
75
99
  case "ArrowRight": {
76
100
  const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
77
- focusElement = tabRefs[nextTab] ?? tabRefs[0];
101
+ focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
78
102
  break;
79
103
  }
80
104
  case "ArrowLeft": {
81
105
  const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
82
- focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
106
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
83
107
  break;
84
108
  }
85
109
  default:
86
110
  break;
87
111
  }
112
+
88
113
  focusElement?.focus();
89
114
  };
90
115
 
91
- const tabItemListContainerRef = useRef(null);
92
- const [showTabArrows, setShowTabArrows] = useState(false);
116
+ const tabItemListContainerRef = useRef<HTMLUListElement>(null);
117
+ const [showTabArrows, setShowTabArrows] = useState<boolean>(false);
93
118
 
94
119
  useEffect(() => {
95
120
  const resizeObserver = new ResizeObserver((entries) => {
96
121
  for (let entry of entries) {
97
122
  requestAnimationFrame(() => {
98
- if (entry.target.offsetWidth < entry.target.scrollWidth) {
123
+ if (entry.target.clientWidth < entry.target.scrollWidth) {
99
124
  setShowTabArrows(true);
100
125
  } else {
101
126
  setShowTabArrows(false);
@@ -104,7 +129,7 @@ function TabList({
104
129
  }
105
130
  });
106
131
 
107
- resizeObserver.observe(tabItemListContainerRef.current);
132
+ resizeObserver.observe(tabItemListContainerRef.current!);
108
133
 
109
134
  return () => {
110
135
  resizeObserver.disconnect();
@@ -112,11 +137,11 @@ function TabList({
112
137
  }, []);
113
138
 
114
139
  const handleRightClick = () => {
115
- tabItemListContainerRef.current.scrollLeft += 90;
140
+ tabItemListContainerRef.current!.scrollLeft += 90;
116
141
  };
117
142
 
118
143
  const handleLeftClick = () => {
119
- tabItemListContainerRef.current.scrollLeft -= 90;
144
+ tabItemListContainerRef.current!.scrollLeft -= 90;
120
145
  };
121
146
 
122
147
  return (
@@ -156,7 +181,7 @@ function TabList({
156
181
  className={clsx(
157
182
  "tabs__item",
158
183
  "openapi-tabs__mime-item",
159
- attributes?.className,
184
+ attributes?.className as string,
160
185
  {
161
186
  active: selectedValue === value,
162
187
  }
@@ -177,11 +202,16 @@ function TabList({
177
202
  </div>
178
203
  );
179
204
  }
180
- function TabContent({ lazy, children, selectedValue }) {
181
- // eslint-disable-next-line no-param-reassign
182
- children = Array.isArray(children) ? children : [children];
205
+ function TabContent({
206
+ lazy,
207
+ children,
208
+ selectedValue,
209
+ }: Props & TabProps & ReturnType<typeof useTabs>) {
210
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
211
+ Boolean
212
+ ) as ReactElement<TabItemProps>[];
183
213
  if (lazy) {
184
- const selectedTabItem = children.find(
214
+ const selectedTabItem = childTabs.find(
185
215
  (tabItem) => tabItem.props.value === selectedValue
186
216
  );
187
217
  if (!selectedTabItem) {
@@ -192,7 +222,7 @@ function TabContent({ lazy, children, selectedValue }) {
192
222
  }
193
223
  return (
194
224
  <div className="margin-top--md">
195
- {children.map((tabItem, i) =>
225
+ {childTabs.map((tabItem, i) =>
196
226
  cloneElement(tabItem, {
197
227
  key: i,
198
228
  hidden: tabItem.props.value !== selectedValue,
@@ -201,7 +231,7 @@ function TabContent({ lazy, children, selectedValue }) {
201
231
  </div>
202
232
  );
203
233
  }
204
- function TabsComponent(props) {
234
+ function TabsComponent(props: Props & TabProps): React.JSX.Element {
205
235
  const tabs = useTabs(props);
206
236
  return (
207
237
  <div className="tabs-container">
@@ -210,7 +240,7 @@ function TabsComponent(props) {
210
240
  </div>
211
241
  );
212
242
  }
213
- export default function MimeTabs(props) {
243
+ export default function MimeTabs(props: Props & TabProps) {
214
244
  const isBrowser = useIsBrowser();
215
245
  return (
216
246
  <TabsComponent
@@ -218,6 +248,8 @@ export default function MimeTabs(props) {
218
248
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
219
249
  key={String(isBrowser)}
220
250
  {...props}
221
- />
251
+ >
252
+ {sanitizeTabsChildren(props.children)}
253
+ </TabsComponent>
222
254
  );
223
255
  }
@@ -8,10 +8,13 @@
8
8
  .openapi-tabs__operation-container {
9
9
  display: flex;
10
10
  align-items: center;
11
- margin-top: 1rem;
12
11
  overflow: hidden;
13
12
  }
14
13
 
14
+ .openapi-tabs__operation-header {
15
+ margin-bottom: 0;
16
+ }
17
+
15
18
  .openapi-tabs__operation-item {
16
19
  display: flex;
17
20
  align-items: center;
@@ -5,34 +5,54 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { cloneElement, useEffect, useState, useRef } from "react";
8
+ import React, {
9
+ cloneElement,
10
+ useEffect,
11
+ useState,
12
+ useRef,
13
+ ReactElement,
14
+ } from "react";
9
15
 
10
16
  import {
17
+ sanitizeTabsChildren,
18
+ TabProps,
11
19
  useScrollPositionBlocker,
12
20
  useTabs,
13
21
  } from "@docusaurus/theme-common/internal";
22
+ import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
14
23
  import useIsBrowser from "@docusaurus/useIsBrowser";
15
24
  import clsx from "clsx";
16
25
 
17
- function TabList({ className, block, selectedValue, selectValue, tabValues }) {
18
- const tabRefs = [];
26
+ function TabList({
27
+ className,
28
+ block,
29
+ selectedValue,
30
+ selectValue,
31
+ tabValues,
32
+ }: TabProps & ReturnType<typeof useTabs>) {
33
+ const tabRefs: (HTMLLIElement | null)[] = [];
19
34
  const { blockElementScrollPositionUntilNextRender } =
20
35
  useScrollPositionBlocker();
21
36
 
22
- const handleTabChange = (event) => {
23
- event.preventDefault();
37
+ const handleTabChange = (
38
+ event:
39
+ | React.FocusEvent<HTMLLIElement>
40
+ | React.MouseEvent<HTMLLIElement>
41
+ | React.KeyboardEvent<HTMLLIElement>
42
+ ) => {
24
43
  const newTab = event.currentTarget;
25
44
  const newTabIndex = tabRefs.indexOf(newTab);
26
45
  const newTabValue = tabValues[newTabIndex].value;
27
- // custom
46
+
28
47
  if (newTabValue !== selectedValue) {
29
48
  blockElementScrollPositionUntilNextRender(newTab);
30
49
  selectValue(newTabValue);
31
50
  }
32
51
  };
33
52
 
34
- const handleKeydown = (event) => {
35
- let focusElement = null;
53
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
54
+ let focusElement: HTMLLIElement | null = null;
55
+
36
56
  switch (event.key) {
37
57
  case "Enter": {
38
58
  handleTabChange(event);
@@ -40,28 +60,29 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
40
60
  }
41
61
  case "ArrowRight": {
42
62
  const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
43
- focusElement = tabRefs[nextTab] ?? tabRefs[0];
63
+ focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
44
64
  break;
45
65
  }
46
66
  case "ArrowLeft": {
47
67
  const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
48
- focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
68
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
49
69
  break;
50
70
  }
51
71
  default:
52
72
  break;
53
73
  }
74
+
54
75
  focusElement?.focus();
55
76
  };
56
77
 
57
- const tabItemListContainerRef = useRef(null);
58
- const [showTabArrows, setShowTabArrows] = useState(false);
78
+ const tabItemListContainerRef = useRef<HTMLUListElement>(null);
79
+ const [showTabArrows, setShowTabArrows] = useState<boolean>(false);
59
80
 
60
81
  useEffect(() => {
61
82
  const resizeObserver = new ResizeObserver((entries) => {
62
83
  for (let entry of entries) {
63
84
  requestAnimationFrame(() => {
64
- if (entry.target.offsetWidth < entry.target.scrollWidth) {
85
+ if (entry.target.clientWidth < entry.target.scrollWidth) {
65
86
  setShowTabArrows(true);
66
87
  } else {
67
88
  setShowTabArrows(false);
@@ -70,7 +91,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
70
91
  }
71
92
  });
72
93
 
73
- resizeObserver.observe(tabItemListContainerRef.current);
94
+ resizeObserver.observe(tabItemListContainerRef.current!);
74
95
 
75
96
  return () => {
76
97
  resizeObserver.disconnect();
@@ -78,11 +99,11 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
78
99
  }, []);
79
100
 
80
101
  const handleRightClick = () => {
81
- tabItemListContainerRef.current.scrollLeft += 90;
102
+ tabItemListContainerRef.current!.scrollLeft += 90;
82
103
  };
83
104
 
84
105
  const handleLeftClick = () => {
85
- tabItemListContainerRef.current.scrollLeft -= 90;
106
+ tabItemListContainerRef.current!.scrollLeft -= 90;
86
107
  };
87
108
 
88
109
  return (
@@ -110,6 +131,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
110
131
  {tabValues.map(({ value, label, attributes }) => {
111
132
  return (
112
133
  <li
134
+ // TODO extract TabListItem
113
135
  role="tab"
114
136
  tabIndex={selectedValue === value ? 0 : -1}
115
137
  aria-selected={selectedValue === value}
@@ -122,7 +144,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
122
144
  className={clsx(
123
145
  "tabs__item",
124
146
  "openapi-tabs__operation-item",
125
- attributes?.className,
147
+ attributes?.className as string,
126
148
  {
127
149
  active: selectedValue === value,
128
150
  }
@@ -143,11 +165,16 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
143
165
  </div>
144
166
  );
145
167
  }
146
- function TabContent({ lazy, children, selectedValue }) {
147
- // eslint-disable-next-line no-param-reassign
148
- children = Array.isArray(children) ? children : [children];
168
+ function TabContent({
169
+ lazy,
170
+ children,
171
+ selectedValue,
172
+ }: TabProps & ReturnType<typeof useTabs>): React.JSX.Element | null {
173
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
174
+ Boolean
175
+ ) as ReactElement<TabItemProps>[];
149
176
  if (lazy) {
150
- const selectedTabItem = children.find(
177
+ const selectedTabItem = childTabs.find(
151
178
  (tabItem) => tabItem.props.value === selectedValue
152
179
  );
153
180
  if (!selectedTabItem) {
@@ -158,7 +185,7 @@ function TabContent({ lazy, children, selectedValue }) {
158
185
  }
159
186
  return (
160
187
  <div className="margin-top--md">
161
- {children.map((tabItem, i) =>
188
+ {childTabs.map((tabItem, i) =>
162
189
  cloneElement(tabItem, {
163
190
  key: i,
164
191
  hidden: tabItem.props.value !== selectedValue,
@@ -167,7 +194,7 @@ function TabContent({ lazy, children, selectedValue }) {
167
194
  </div>
168
195
  );
169
196
  }
170
- function TabsComponent(props) {
197
+ function TabsComponent(props: TabProps): React.JSX.Element {
171
198
  const tabs = useTabs(props);
172
199
  return (
173
200
  <div className="tabs-container">
@@ -176,7 +203,7 @@ function TabsComponent(props) {
176
203
  </div>
177
204
  );
178
205
  }
179
- export default function OperationTabs(props) {
206
+ export default function OperationTabs(props: TabProps): React.JSX.Element {
180
207
  const isBrowser = useIsBrowser();
181
208
  return (
182
209
  <TabsComponent
@@ -184,6 +211,8 @@ export default function OperationTabs(props) {
184
211
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
185
212
  key={String(isBrowser)}
186
213
  {...props}
187
- />
214
+ >
215
+ {sanitizeTabsChildren(props.children)}
216
+ </TabsComponent>
188
217
  );
189
218
  }
@@ -12,23 +12,39 @@ import SchemaTabs from "@theme/SchemaTabs";
12
12
  import TabItem from "@theme/TabItem";
13
13
  /* eslint-disable import/no-extraneous-dependencies*/
14
14
  import clsx from "clsx";
15
- import { createDescription } from "docusaurus-theme-openapi-docs/lib/markdown/createDescription";
16
- /* eslint-disable import/no-extraneous-dependencies*/
17
- import {
18
- getQualifierMessage,
19
- getSchemaName,
20
- } from "docusaurus-theme-openapi-docs/lib/markdown/schema";
21
- /* eslint-disable import/no-extraneous-dependencies*/
22
- import {
23
- guard,
24
- toString,
25
- } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
26
15
  import ReactMarkdown from "react-markdown";
27
16
  import rehypeRaw from "rehype-raw";
28
17
 
18
+ import { createDescription } from "../../markdown/createDescription";
19
+ import { getQualifierMessage, getSchemaName } from "../../markdown/schema";
20
+ import { guard, toString } from "../../markdown/utils";
21
+
22
+ interface Map<T> {
23
+ [key: string]: T;
24
+ }
25
+
26
+ export interface ExampleObject {
27
+ summary?: string;
28
+ description?: string;
29
+ value?: any;
30
+ externalValue?: string;
31
+ }
32
+
33
+ export interface Props {
34
+ param: {
35
+ description: string;
36
+ example: any;
37
+ examples: Map<ExampleObject>;
38
+ name: string;
39
+ required: boolean;
40
+ deprecated: boolean;
41
+ schema: any;
42
+ };
43
+ }
44
+
29
45
  function ParamsItem({
30
46
  param: { description, example, examples, name, required, schema, deprecated },
31
- }) {
47
+ }: Props) {
32
48
  if (!schema || !schema?.type) {
33
49
  schema = { type: "any" };
34
50
  }
@@ -79,8 +95,8 @@ function ParamsItem({
79
95
  schema && schema.items
80
96
  ? schema.items.default
81
97
  : schema
82
- ? schema.default
83
- : undefined,
98
+ ? schema.default
99
+ : undefined,
84
100
  (value) => (
85
101
  <div>
86
102
  <ReactMarkdown children={`**Default value:** \`${value}\``} />
@@ -102,6 +118,7 @@ function ParamsItem({
102
118
  <strong>Examples:</strong>
103
119
  <SchemaTabs>
104
120
  {exampleEntries.map(([exampleName, exampleProperties]) => (
121
+ // @ts-ignore
105
122
  <TabItem value={exampleName} label={exampleName}>
106
123
  {exampleProperties.summary && <p>{exampleProperties.summary}</p>}
107
124
  {exampleProperties.description && (
@@ -8,8 +8,17 @@
8
8
  import React from "react";
9
9
 
10
10
  import CodeBlock from "@theme/CodeBlock";
11
+ import { Language } from "prism-react-renderer";
11
12
 
12
- function ResponseSamples({ responseExample, language }) {
13
+ export interface Props {
14
+ readonly responseExample: string;
15
+ readonly language: Language;
16
+ }
17
+
18
+ function ResponseSamples({
19
+ responseExample,
20
+ language,
21
+ }: Props): React.JSX.Element {
13
22
  return (
14
23
  <div className="openapi-code__response-samples-container">
15
24
  <CodeBlock language={language ? language : "json"}>