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
@@ -18,12 +18,14 @@
18
18
  background-color: var(--ifm-pre-background);
19
19
  border-radius: var(--ifm-global-radius);
20
20
  border: 1px solid var(--openapi-explorer-border-color);
21
- box-shadow: 0 2px 3px hsla(222, 8%, 43%, 0.1),
21
+ box-shadow:
22
+ 0 2px 3px hsla(222, 8%, 43%, 0.1),
22
23
  0 8px 16px -10px hsla(222, 8%, 43%, 0.2);
23
24
  transition: 300ms;
24
25
 
25
26
  &:hover {
26
- box-shadow: 0 0 0 2px rgba(38, 53, 61, 0.15),
27
+ box-shadow:
28
+ 0 0 0 2px rgba(38, 53, 61, 0.15),
27
29
  0 2px 3px hsla(222, 8%, 43%, 0.15),
28
30
  0 16px 16px -10px hsla(222, 8%, 43%, 0.2);
29
31
  }
@@ -5,15 +5,32 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { cloneElement } from "react";
8
+ import React, { cloneElement, ReactElement } from "react";
9
9
 
10
10
  import {
11
+ sanitizeTabsChildren,
12
+ type TabProps,
11
13
  useScrollPositionBlocker,
12
14
  useTabs,
13
15
  } from "@docusaurus/theme-common/internal";
16
+ import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
14
17
  import useIsBrowser from "@docusaurus/useIsBrowser";
18
+ import { Language } from "@theme/ApiExplorer/CodeSnippets";
15
19
  import clsx from "clsx";
16
20
 
21
+ export interface Props {
22
+ action: {
23
+ [key: string]: React.Dispatch<any>;
24
+ };
25
+ currentLanguage: Language;
26
+ languageSet: Language[];
27
+ includeVariant: boolean;
28
+ }
29
+
30
+ export interface CodeTabsProps extends Props, TabProps {
31
+ includeSample?: boolean;
32
+ }
33
+
17
34
  function TabList({
18
35
  action,
19
36
  currentLanguage,
@@ -25,15 +42,20 @@ function TabList({
25
42
  selectedValue,
26
43
  selectValue,
27
44
  tabValues,
28
- }) {
29
- const tabRefs = [];
45
+ }: CodeTabsProps & ReturnType<typeof useTabs>) {
46
+ const tabRefs: (HTMLLIElement | null)[] = [];
30
47
  const { blockElementScrollPositionUntilNextRender } =
31
48
  useScrollPositionBlocker();
32
49
 
33
- const handleTabChange = (event) => {
50
+ const handleTabChange = (
51
+ event:
52
+ | React.FocusEvent<HTMLLIElement>
53
+ | React.MouseEvent<HTMLLIElement>
54
+ | React.KeyboardEvent<HTMLLIElement>
55
+ ) => {
34
56
  const newTab = event.currentTarget;
35
57
  const newTabIndex = tabRefs.indexOf(newTab);
36
- const newTabValue = tabValues[newTabIndex].value;
58
+ const newTabValue = tabValues[newTabIndex]!.value;
37
59
 
38
60
  if (newTabValue !== selectedValue) {
39
61
  blockElementScrollPositionUntilNextRender(newTab);
@@ -41,33 +63,33 @@ function TabList({
41
63
  }
42
64
 
43
65
  if (action) {
44
- let newLanguage;
66
+ let newLanguage: Language;
45
67
  if (currentLanguage && includeVariant) {
46
68
  newLanguage = languageSet.filter(
47
- (lang) => lang.language === currentLanguage
69
+ (lang: Language) => lang.language === currentLanguage
48
70
  )[0];
49
71
  newLanguage.variant = newTabValue;
50
72
  action.setSelectedVariant(newTabValue.toLowerCase());
51
73
  } else if (currentLanguage && includeSample) {
52
74
  newLanguage = languageSet.filter(
53
- (lang) => lang.language === currentLanguage
75
+ (lang: Language) => lang.language === currentLanguage
54
76
  )[0];
55
77
  newLanguage.sample = newTabValue;
56
78
  action.setSelectedSample(newTabValue);
57
79
  } else {
58
80
  newLanguage = languageSet.filter(
59
- (lang) => lang.language === newTabValue
81
+ (lang: Language) => lang.language === newTabValue
60
82
  )[0];
61
83
  action.setSelectedVariant(newLanguage.variant.toLowerCase());
62
84
  action.setSelectedSample(newLanguage.sample);
63
85
  }
64
-
65
86
  action.setLanguage(newLanguage);
66
87
  }
67
88
  };
68
89
 
69
- const handleKeydown = (event) => {
70
- let focusElement = null;
90
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
91
+ let focusElement: HTMLLIElement | null = null;
92
+
71
93
  switch (event.key) {
72
94
  case "Enter": {
73
95
  handleTabChange(event);
@@ -75,17 +97,18 @@ function TabList({
75
97
  }
76
98
  case "ArrowRight": {
77
99
  const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
78
- focusElement = tabRefs[nextTab] ?? tabRefs[0];
100
+ focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
79
101
  break;
80
102
  }
81
103
  case "ArrowLeft": {
82
104
  const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
83
- focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
105
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
84
106
  break;
85
107
  }
86
108
  default:
87
109
  break;
88
110
  }
111
+
89
112
  focusElement?.focus();
90
113
  };
91
114
 
@@ -116,7 +139,7 @@ function TabList({
116
139
  className={clsx(
117
140
  "tabs__item",
118
141
  "openapi-tabs__code-item",
119
- attributes?.className,
142
+ attributes?.className as string,
120
143
  {
121
144
  active: selectedValue === value,
122
145
  }
@@ -129,11 +152,16 @@ function TabList({
129
152
  );
130
153
  }
131
154
 
132
- function TabContent({ lazy, children, selectedValue }) {
133
- // eslint-disable-next-line no-param-reassign
134
- children = Array.isArray(children) ? children : [children];
155
+ function TabContent({
156
+ lazy,
157
+ children,
158
+ selectedValue,
159
+ }: CodeTabsProps & ReturnType<typeof useTabs>): React.JSX.Element | null {
160
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
161
+ Boolean
162
+ ) as ReactElement<TabItemProps>[];
135
163
  if (lazy) {
136
- const selectedTabItem = children.find(
164
+ const selectedTabItem = childTabs.find(
137
165
  (tabItem) => tabItem.props.value === selectedValue
138
166
  );
139
167
  if (!selectedTabItem) {
@@ -144,7 +172,7 @@ function TabContent({ lazy, children, selectedValue }) {
144
172
  }
145
173
  return (
146
174
  <div className="margin-top--md openapi-tabs__code-content">
147
- {children.map((tabItem, i) =>
175
+ {childTabs.map((tabItem, i) =>
148
176
  cloneElement(tabItem, {
149
177
  key: i,
150
178
  hidden: tabItem.props.value !== selectedValue,
@@ -154,15 +182,13 @@ function TabContent({ lazy, children, selectedValue }) {
154
182
  );
155
183
  }
156
184
 
157
- function TabsComponent(props) {
185
+ function TabsComponent(props: CodeTabsProps & Props): React.JSX.Element {
158
186
  const tabs = useTabs(props);
159
187
  const { className } = props;
160
188
 
161
189
  return (
162
190
  <div
163
- className={clsx("tabs-container openapi-tabs__code-container", {
164
- [className]: className,
165
- })}
191
+ className={clsx("tabs-container openapi-tabs__code-container", className)}
166
192
  >
167
193
  <TabList {...props} {...tabs} />
168
194
  <TabContent {...props} {...tabs} />
@@ -170,7 +196,9 @@ function TabsComponent(props) {
170
196
  );
171
197
  }
172
198
 
173
- export default function CodeTabs(props) {
199
+ export default function CodeTabs(
200
+ props: CodeTabsProps & Props
201
+ ): React.JSX.Element {
174
202
  const isBrowser = useIsBrowser();
175
203
  return (
176
204
  <TabsComponent
@@ -178,6 +206,8 @@ export default function CodeTabs(props) {
178
206
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
179
207
  key={String(isBrowser)}
180
208
  {...props}
181
- />
209
+ >
210
+ {sanitizeTabsChildren(props.children)}
211
+ </TabsComponent>
182
212
  );
183
213
  }
@@ -11,7 +11,9 @@
11
11
  padding: 0.4rem 0.5rem;
12
12
  opacity: 0;
13
13
  visibility: hidden;
14
- transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out,
14
+ transition:
15
+ opacity 0.2s ease-in-out,
16
+ visibility 0.2s ease-in-out,
15
17
  bottom 0.2s ease-in-out;
16
18
  position: absolute;
17
19
  right: calc(var(--ifm-pre-padding) / 2);
@@ -37,10 +37,10 @@ export default function ParamMultiSelectFormItem({ param }: ParamProps) {
37
37
  const paramTypeToWatch = pathParams.length
38
38
  ? pathParams
39
39
  : queryParams.length
40
- ? queryParams
41
- : cookieParams.length
42
- ? cookieParams
43
- : headerParams;
40
+ ? queryParams
41
+ : cookieParams.length
42
+ ? cookieParams
43
+ : headerParams;
44
44
 
45
45
  const handleChange = (e: any, onChange: any) => {
46
46
  const values = Array.prototype.filter
@@ -107,7 +107,8 @@
107
107
  }
108
108
 
109
109
  &:active {
110
- box-shadow: inset 0 0 0 1px var(--openapi-input-border),
110
+ box-shadow:
111
+ inset 0 0 0 1px var(--openapi-input-border),
111
112
  inset 0 0 0 2px var(--openapi-inverse-color);
112
113
  }
113
114
  }
@@ -2,7 +2,8 @@
2
2
  background-color: var(--ifm-pre-background);
3
3
  border-radius: var(--openapi-card-border-radius);
4
4
  border: 1px solid var(--openapi-explorer-border-color);
5
- box-shadow: 0 2px 3px hsla(222, 8%, 43%, 0.1),
5
+ box-shadow:
6
+ 0 2px 3px hsla(222, 8%, 43%, 0.1),
6
7
  0 8px 16px -10px hsla(222, 8%, 43%, 0.2);
7
8
  color: var(--ifm-pre-color);
8
9
  line-height: var(--ifm-pre-line-height);
@@ -19,7 +20,8 @@
19
20
  }
20
21
 
21
22
  &:hover {
22
- box-shadow: 0 0 0 2px rgba(38, 53, 61, 0.15),
23
+ box-shadow:
24
+ 0 0 0 2px rgba(38, 53, 61, 0.15),
23
25
  0 2px 3px hsla(222, 8%, 43%, 0.15),
24
26
  0 16px 16px -10px hsla(222, 8%, 43%, 0.2);
25
27
  }
@@ -112,10 +114,6 @@
112
114
  }
113
115
  }
114
116
 
115
- .openapi-security__summary-container {
116
- background: var(--ifm-pre-background);
117
- }
118
-
119
117
  // Prevent auto zoom on mobile iOS devices when focusing on input elmenents
120
118
  @media screen and (-webkit-min-device-pixel-ratio: 0) and (max-device-width: 1024px) {
121
119
  .prism-code,
@@ -2,7 +2,8 @@
2
2
  background-color: var(--ifm-pre-background);
3
3
  border-radius: var(--openapi-card-border-radius);
4
4
  border: 1px solid var(--openapi-explorer-border-color);
5
- box-shadow: 0 2px 3px hsla(222, 8%, 43%, 0.1),
5
+ box-shadow:
6
+ 0 2px 3px hsla(222, 8%, 43%, 0.1),
6
7
  0 8px 16px -10px hsla(222, 8%, 43%, 0.2);
7
8
  color: var(--ifm-pre-color);
8
9
  line-height: var(--ifm-pre-line-height);
@@ -12,7 +13,8 @@
12
13
  transition: 300ms;
13
14
 
14
15
  &:hover {
15
- box-shadow: 0 0 0 2px rgba(38, 53, 61, 0.15),
16
+ box-shadow:
17
+ 0 0 0 2px rgba(38, 53, 61, 0.15),
16
18
  0 2px 3px hsla(222, 8%, 43%, 0.15),
17
19
  0 16px 16px -10px hsla(222, 8%, 43%, 0.2);
18
20
  }
@@ -52,8 +52,8 @@ function Response({ item }: { item: NonNullable<ApiItem> }) {
52
52
  (parseInt(code) >= 400
53
53
  ? "openapi-response__dot--danger"
54
54
  : parseInt(code) >= 200 && parseInt(code) < 300
55
- ? "openapi-response__dot--success"
56
- : "openapi-response__dot--info");
55
+ ? "openapi-response__dot--success"
56
+ : "openapi-response__dot--info");
57
57
 
58
58
  if (!item.servers || hideSendButton) {
59
59
  return null;
@@ -13,8 +13,6 @@ import Request from "@theme/ApiExplorer/Request";
13
13
  import Response from "@theme/ApiExplorer/Response";
14
14
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
15
15
 
16
- import SecuritySchemes from "./SecuritySchemes";
17
-
18
16
  function ApiExplorer({
19
17
  item,
20
18
  infoPath,
@@ -26,7 +24,6 @@ function ApiExplorer({
26
24
 
27
25
  return (
28
26
  <>
29
- <SecuritySchemes infoPath={infoPath} />
30
27
  {item.method !== "event" && (
31
28
  <CodeSnippets
32
29
  postman={postman}
@@ -18,6 +18,7 @@ import DocItemTOCDesktop from "@theme/DocItem/TOC/Desktop";
18
18
  import DocItemTOCMobile from "@theme/DocItem/TOC/Mobile";
19
19
  import DocVersionBadge from "@theme/DocVersionBadge";
20
20
  import DocVersionBanner from "@theme/DocVersionBanner";
21
+ import Unlisted from "@theme/Unlisted";
21
22
  import clsx from "clsx";
22
23
 
23
24
  import styles from "./styles.module.css";
@@ -49,12 +50,14 @@ function useDocTOC() {
49
50
  export default function DocItemLayout({ children }: Props): JSX.Element {
50
51
  const docTOC = useDocTOC();
51
52
  const {
53
+ metadata: { unlisted },
52
54
  frontMatter: { api },
53
55
  } = useDoc();
54
56
 
55
57
  return (
56
58
  <div className="row">
57
59
  <div className={clsx("col", !docTOC.hidden && styles.docItemCol)}>
60
+ {unlisted && <Unlisted />}
58
61
  <DocVersionBanner />
59
62
  <div className={styles.docItemContainer}>
60
63
  <article>
@@ -12,6 +12,7 @@ import React from "react";
12
12
  import BrowserOnly from "@docusaurus/BrowserOnly";
13
13
  import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
14
14
  import { HtmlClassNameProvider } from "@docusaurus/theme-common";
15
+ import { DocProvider } from "@docusaurus/theme-common/internal";
15
16
  import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
16
17
  import useIsBrowser from "@docusaurus/useIsBrowser";
17
18
  import { createAuth } from "@theme/ApiExplorer/Authorization/slice";
@@ -23,7 +24,6 @@ import clsx from "clsx";
23
24
  import { ServerObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
24
25
  import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
25
26
  import type { ApiItem as ApiItemType } from "docusaurus-plugin-openapi-docs/src/types";
26
- /* eslint-disable import/no-extraneous-dependencies*/
27
27
  import type {
28
28
  DocFrontMatter,
29
29
  ThemeConfig,
@@ -32,8 +32,6 @@ import { Provider } from "react-redux";
32
32
 
33
33
  import { createStoreWithoutState, createStoreWithState } from "./store";
34
34
 
35
- const { DocProvider } = require("@docusaurus/theme-common/internal");
36
-
37
35
  let ApiExplorer = (_: { item: any; infoPath: any }) => <div />;
38
36
 
39
37
  if (ExecutionEnvironment.canUseDOM) {
@@ -48,8 +46,9 @@ interface SchemaFrontMatter extends DocFrontMatter {
48
46
  readonly schema?: boolean;
49
47
  }
50
48
 
49
+ // @ts-ignore
51
50
  export default function ApiItem(props: Props): JSX.Element {
52
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
51
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`;
53
52
  const MDXComponent = props.content;
54
53
  const { frontMatter } = MDXComponent;
55
54
  const { info_path: infoPath } = frontMatter as DocFrontMatter;
@@ -11,7 +11,7 @@ import { useColorMode } from "@docusaurus/theme-common";
11
11
  import useBaseUrl from "@docusaurus/useBaseUrl";
12
12
  import ThemedImage from "@theme/ThemedImage";
13
13
 
14
- export default function ApiLogo(props: any): JSX.Element | undefined {
14
+ export default function ApiLogo(props: any): React.JSX.Element | undefined {
15
15
  const { colorMode } = useColorMode();
16
16
  const { logo, darkLogo } = props;
17
17
  const altText = () => {
@@ -10,7 +10,9 @@
10
10
  }
11
11
 
12
12
  .openapi-tabs__response-header {
13
- margin-bottom: 0;
13
+ &.openapi-tabs__heading {
14
+ margin-bottom: 0;
15
+ }
14
16
  }
15
17
 
16
18
  .openapi-tabs__response-code-item {
@@ -5,16 +5,30 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { cloneElement, useRef, useState, useEffect } from "react";
8
+ import React, {
9
+ cloneElement,
10
+ useRef,
11
+ useState,
12
+ useEffect,
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 Heading from "@theme/Heading";
16
25
  import clsx from "clsx";
17
26
 
27
+ export interface TabListProps extends TabProps {
28
+ label: string;
29
+ id: string;
30
+ }
31
+
18
32
  function TabList({
19
33
  className,
20
34
  block,
@@ -23,23 +37,30 @@ function TabList({
23
37
  tabValues,
24
38
  label = "Responses",
25
39
  id = "responses",
26
- }) {
27
- const tabRefs = [];
40
+ }: TabListProps & ReturnType<typeof useTabs>) {
41
+ const tabRefs: (HTMLLIElement | null)[] = [];
28
42
  const { blockElementScrollPositionUntilNextRender } =
29
43
  useScrollPositionBlocker();
30
44
 
31
- const handleTabChange = (event) => {
45
+ const handleTabChange = (
46
+ event:
47
+ | React.FocusEvent<HTMLLIElement>
48
+ | React.MouseEvent<HTMLLIElement>
49
+ | React.KeyboardEvent<HTMLLIElement>
50
+ ) => {
32
51
  const newTab = event.currentTarget;
33
52
  const newTabIndex = tabRefs.indexOf(newTab);
34
53
  const newTabValue = tabValues[newTabIndex].value;
54
+
35
55
  if (newTabValue !== selectedValue) {
36
56
  blockElementScrollPositionUntilNextRender(newTab);
37
57
  selectValue(newTabValue);
38
58
  }
39
59
  };
40
60
 
41
- const handleKeydown = (event) => {
42
- let focusElement = null;
61
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
62
+ let focusElement: HTMLLIElement | null = null;
63
+
43
64
  switch (event.key) {
44
65
  case "Enter": {
45
66
  handleTabChange(event);
@@ -47,28 +68,29 @@ function TabList({
47
68
  }
48
69
  case "ArrowRight": {
49
70
  const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
50
- focusElement = tabRefs[nextTab] ?? tabRefs[0];
71
+ focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
51
72
  break;
52
73
  }
53
74
  case "ArrowLeft": {
54
75
  const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
55
- focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
76
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
56
77
  break;
57
78
  }
58
79
  default:
59
80
  break;
60
81
  }
82
+
61
83
  focusElement?.focus();
62
84
  };
63
85
 
64
- const tabItemListContainerRef = useRef(null);
65
- const [showTabArrows, setShowTabArrows] = useState(false);
86
+ const tabItemListContainerRef = useRef<HTMLUListElement>(null);
87
+ const [showTabArrows, setShowTabArrows] = useState<boolean>(false);
66
88
 
67
89
  useEffect(() => {
68
90
  const resizeObserver = new ResizeObserver((entries) => {
69
91
  for (let entry of entries) {
70
92
  requestAnimationFrame(() => {
71
- if (entry.target.offsetWidth < entry.target.scrollWidth) {
93
+ if (entry.target.clientWidth < entry.target.scrollWidth) {
72
94
  setShowTabArrows(true);
73
95
  } else {
74
96
  setShowTabArrows(false);
@@ -77,7 +99,7 @@ function TabList({
77
99
  }
78
100
  });
79
101
 
80
- resizeObserver.observe(tabItemListContainerRef.current);
102
+ resizeObserver.observe(tabItemListContainerRef.current!);
81
103
 
82
104
  return () => {
83
105
  resizeObserver.disconnect();
@@ -85,16 +107,20 @@ function TabList({
85
107
  }, []);
86
108
 
87
109
  const handleRightClick = () => {
88
- tabItemListContainerRef.current.scrollLeft += 90;
110
+ tabItemListContainerRef.current!.scrollLeft += 90;
89
111
  };
90
112
 
91
113
  const handleLeftClick = () => {
92
- tabItemListContainerRef.current.scrollLeft -= 90;
114
+ tabItemListContainerRef.current!.scrollLeft -= 90;
93
115
  };
94
116
 
95
117
  return (
96
118
  <div className="openapi-tabs__response-header-section">
97
- <Heading as="h2" id={id} className="openapi-tabs__response-header">
119
+ <Heading
120
+ as="h2"
121
+ id={id}
122
+ className="openapi-tabs__heading openapi-tabs__response-header"
123
+ >
98
124
  {label}
99
125
  </Heading>
100
126
  <div className="openapi-tabs__response-container">
@@ -131,12 +157,12 @@ function TabList({
131
157
  className={clsx(
132
158
  "tabs__item",
133
159
  "openapi-tabs__response-code-item",
134
- attributes?.className,
160
+ attributes?.className as string,
135
161
  parseInt(value) >= 400
136
162
  ? "danger"
137
163
  : parseInt(value) >= 200 && parseInt(value) < 300
138
- ? "success"
139
- : "info",
164
+ ? "success"
165
+ : "info",
140
166
  {
141
167
  active: selectedValue === value,
142
168
  }
@@ -156,11 +182,17 @@ function TabList({
156
182
  </div>
157
183
  );
158
184
  }
159
- function TabContent({ lazy, children, selectedValue }) {
160
- // eslint-disable-next-line no-param-reassign
161
- children = Array.isArray(children) ? children : [children];
185
+
186
+ function TabContent({
187
+ lazy,
188
+ children,
189
+ selectedValue,
190
+ }: TabProps & ReturnType<typeof useTabs>): React.JSX.Element | null {
191
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
192
+ Boolean
193
+ ) as ReactElement<TabItemProps>[];
162
194
  if (lazy) {
163
- const selectedTabItem = children.find(
195
+ const selectedTabItem = childTabs.find(
164
196
  (tabItem) => tabItem.props.value === selectedValue
165
197
  );
166
198
  if (!selectedTabItem) {
@@ -171,7 +203,7 @@ function TabContent({ lazy, children, selectedValue }) {
171
203
  }
172
204
  return (
173
205
  <div className="margin-top--md">
174
- {children.map((tabItem, i) =>
206
+ {childTabs.map((tabItem, i) =>
175
207
  cloneElement(tabItem, {
176
208
  key: i,
177
209
  hidden: tabItem.props.value !== selectedValue,
@@ -180,7 +212,7 @@ function TabContent({ lazy, children, selectedValue }) {
180
212
  </div>
181
213
  );
182
214
  }
183
- function TabsComponent(props) {
215
+ function TabsComponent(props: TabListProps): React.JSX.Element {
184
216
  const tabs = useTabs(props);
185
217
  return (
186
218
  <div className="openapi-tabs__container">
@@ -189,7 +221,7 @@ function TabsComponent(props) {
189
221
  </div>
190
222
  );
191
223
  }
192
- export default function ApiTabs(props) {
224
+ export default function ApiTabs(props: TabListProps): React.JSX.Element {
193
225
  const isBrowser = useIsBrowser();
194
226
  return (
195
227
  <TabsComponent
@@ -197,6 +229,8 @@ export default function ApiTabs(props) {
197
229
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
198
230
  key={String(isBrowser)}
199
231
  {...props}
200
- />
232
+ >
233
+ {sanitizeTabsChildren(props.children)}
234
+ </TabsComponent>
201
235
  );
202
236
  }