docusaurus-theme-openapi-docs 3.0.0-beta.3 → 3.0.0-beta.4

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 (89) 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/Accept/index.d.ts +2 -2
  5. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.d.ts +4 -0
  6. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.js +25 -19
  7. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/Element.d.ts +4 -0
  8. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/Element.js +27 -16
  9. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.d.ts +4 -0
  10. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.js +115 -96
  11. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.d.ts +3 -0
  12. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.js +115 -54
  13. package/lib/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.d.ts +6 -0
  14. package/lib/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.js +41 -30
  15. package/lib/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.d.ts +14 -0
  16. package/lib/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.js +200 -120
  17. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.d.ts +3 -0
  18. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.js +36 -24
  19. package/lib/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.d.ts +7 -0
  20. package/lib/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.js +35 -28
  21. package/lib/theme/ApiExplorer/ApiCodeBlock/index.d.ts +3 -0
  22. package/lib/theme/ApiExplorer/ApiCodeBlock/index.js +72 -14
  23. package/lib/theme/ApiExplorer/Authorization/index.d.ts +2 -2
  24. package/lib/theme/ApiExplorer/Body/index.d.ts +2 -2
  25. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -2
  26. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +11 -0
  27. package/lib/theme/ApiExplorer/CodeTabs/index.js +125 -78
  28. package/lib/theme/ApiExplorer/ContentType/index.d.ts +2 -2
  29. package/lib/theme/ApiExplorer/Export/index.d.ts +2 -2
  30. package/lib/theme/ApiExplorer/FloatingButton/index.d.ts +1 -1
  31. package/lib/theme/ApiExplorer/FormFileUpload/index.d.ts +2 -2
  32. package/lib/theme/ApiExplorer/FormItem/index.d.ts +1 -1
  33. package/lib/theme/ApiExplorer/FormMultiSelect/index.d.ts +1 -1
  34. package/lib/theme/ApiExplorer/FormSelect/index.d.ts +1 -1
  35. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +1 -1
  36. package/lib/theme/ApiExplorer/MethodEndpoint/index.d.ts +2 -2
  37. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +2 -2
  38. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +2 -2
  39. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +2 -2
  40. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +2 -2
  41. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +2 -2
  42. package/lib/theme/ApiExplorer/ParamOptions/index.d.ts +2 -2
  43. package/lib/theme/ApiExplorer/Request/index.d.ts +2 -2
  44. package/lib/theme/ApiExplorer/Response/index.d.ts +2 -2
  45. package/lib/theme/ApiExplorer/SecuritySchemes/index.d.ts +2 -2
  46. package/lib/theme/ApiExplorer/Server/index.d.ts +2 -2
  47. package/lib/theme/ApiExplorer/index.d.ts +2 -2
  48. package/lib/theme/ApiItem/index.d.ts +2 -2
  49. package/lib/theme/ApiItem/index.js +4 -3
  50. package/lib/theme/ApiItem/store.d.ts +4 -4
  51. package/lib/theme/ApiLogo/index.d.ts +2 -2
  52. package/lib/theme/ApiTabs/index.d.ts +3 -0
  53. package/lib/theme/ApiTabs/index.js +146 -96
  54. package/lib/theme/DiscriminatorTabs/index.d.ts +3 -0
  55. package/lib/theme/DiscriminatorTabs/index.js +146 -94
  56. package/lib/theme/MimeTabs/index.d.ts +6 -0
  57. package/lib/theme/MimeTabs/index.js +163 -114
  58. package/lib/theme/ParamsItem/index.d.ts +22 -0
  59. package/lib/theme/ParamsItem/index.js +154 -109
  60. package/lib/theme/ResponseSamples/index.d.ts +8 -0
  61. package/lib/theme/ResponseSamples/index.js +18 -13
  62. package/lib/theme/SchemaItem/index.d.ts +12 -0
  63. package/lib/theme/SchemaItem/index.js +123 -89
  64. package/lib/theme/SchemaTabs/index.d.ts +3 -0
  65. package/lib/theme/SchemaTabs/index.js +142 -91
  66. package/package.json +4 -4
  67. package/src/markdown/utils.ts +4 -2
  68. package/src/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/{index.js → index.tsx} +21 -8
  69. package/src/theme/ApiExplorer/ApiCodeBlock/Container/{index.js → index.tsx} +6 -3
  70. package/src/theme/ApiExplorer/ApiCodeBlock/Content/{Element.js → Element.tsx} +5 -1
  71. package/src/theme/ApiExplorer/ApiCodeBlock/Content/{String.js → String.tsx} +4 -4
  72. package/src/theme/ApiExplorer/ApiCodeBlock/CopyButton/{index.js → index.tsx} +8 -3
  73. package/src/theme/ApiExplorer/ApiCodeBlock/ExitButton/{index.js → index.tsx} +9 -1
  74. package/src/theme/ApiExplorer/ApiCodeBlock/ExpandButton/{index.js → index.tsx} +12 -2
  75. package/src/theme/ApiExplorer/ApiCodeBlock/Line/{index.js → index.tsx} +2 -1
  76. package/src/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/{index.js → index.tsx} +11 -1
  77. package/src/theme/ApiExplorer/ApiCodeBlock/{index.js → index.tsx} +10 -5
  78. package/src/theme/ApiExplorer/CodeTabs/{index.js → index.tsx} +48 -25
  79. package/src/theme/ApiItem/index.tsx +3 -4
  80. package/src/theme/ApiLogo/index.tsx +1 -1
  81. package/src/theme/ApiTabs/{index.js → index.tsx} +54 -23
  82. package/src/theme/DiscriminatorTabs/{index.js → index.tsx} +57 -24
  83. package/src/theme/MimeTabs/{index.js → index.tsx} +58 -26
  84. package/src/theme/ParamsItem/{index.js → index.tsx} +28 -13
  85. package/src/theme/ResponseSamples/{index.js → index.tsx} +10 -1
  86. package/src/theme/SchemaItem/{index.js → index.tsx} +18 -9
  87. package/src/theme/SchemaTabs/{index.js → index.tsx} +56 -25
  88. package/src/theme-classic.d.ts +69 -2
  89. package/tsconfig.json +4 -1
@@ -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,27 +98,28 @@ 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
- if (entry.target.offsetWidth < entry.target.scrollWidth) {
122
+ if (entry.target.clientWidth < entry.target.scrollWidth) {
98
123
  setShowTabArrows(true);
99
124
  } else {
100
125
  setShowTabArrows(false);
@@ -102,7 +127,7 @@ function TabList({
102
127
  }
103
128
  });
104
129
 
105
- resizeObserver.observe(tabItemListContainerRef.current);
130
+ resizeObserver.observe(tabItemListContainerRef.current!);
106
131
 
107
132
  return () => {
108
133
  resizeObserver.disconnect();
@@ -110,11 +135,11 @@ function TabList({
110
135
  }, []);
111
136
 
112
137
  const handleRightClick = () => {
113
- tabItemListContainerRef.current.scrollLeft += 90;
138
+ tabItemListContainerRef.current!.scrollLeft += 90;
114
139
  };
115
140
 
116
141
  const handleLeftClick = () => {
117
- tabItemListContainerRef.current.scrollLeft -= 90;
142
+ tabItemListContainerRef.current!.scrollLeft -= 90;
118
143
  };
119
144
 
120
145
  return (
@@ -154,7 +179,7 @@ function TabList({
154
179
  className={clsx(
155
180
  "tabs__item",
156
181
  "openapi-tabs__mime-item",
157
- attributes?.className,
182
+ attributes?.className as string,
158
183
  {
159
184
  active: selectedValue === value,
160
185
  }
@@ -175,11 +200,16 @@ function TabList({
175
200
  </div>
176
201
  );
177
202
  }
178
- function TabContent({ lazy, children, selectedValue }) {
179
- // eslint-disable-next-line no-param-reassign
180
- children = Array.isArray(children) ? children : [children];
203
+ function TabContent({
204
+ lazy,
205
+ children,
206
+ selectedValue,
207
+ }: Props & TabProps & ReturnType<typeof useTabs>) {
208
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
209
+ Boolean
210
+ ) as ReactElement<TabItemProps>[];
181
211
  if (lazy) {
182
- const selectedTabItem = children.find(
212
+ const selectedTabItem = childTabs.find(
183
213
  (tabItem) => tabItem.props.value === selectedValue
184
214
  );
185
215
  if (!selectedTabItem) {
@@ -190,7 +220,7 @@ function TabContent({ lazy, children, selectedValue }) {
190
220
  }
191
221
  return (
192
222
  <div className="margin-top--md">
193
- {children.map((tabItem, i) =>
223
+ {childTabs.map((tabItem, i) =>
194
224
  cloneElement(tabItem, {
195
225
  key: i,
196
226
  hidden: tabItem.props.value !== selectedValue,
@@ -199,7 +229,7 @@ function TabContent({ lazy, children, selectedValue }) {
199
229
  </div>
200
230
  );
201
231
  }
202
- function TabsComponent(props) {
232
+ function TabsComponent(props: Props & TabProps): React.JSX.Element {
203
233
  const tabs = useTabs(props);
204
234
  return (
205
235
  <div className="tabs-container">
@@ -208,7 +238,7 @@ function TabsComponent(props) {
208
238
  </div>
209
239
  );
210
240
  }
211
- export default function MimeTabs(props) {
241
+ export default function MimeTabs(props: Props & TabProps) {
212
242
  const isBrowser = useIsBrowser();
213
243
  return (
214
244
  <TabsComponent
@@ -216,6 +246,8 @@ export default function MimeTabs(props) {
216
246
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
217
247
  key={String(isBrowser)}
218
248
  {...props}
219
- />
249
+ >
250
+ {sanitizeTabsChildren(props.children)}
251
+ </TabsComponent>
220
252
  );
221
253
  }
@@ -10,24 +10,38 @@ import React from "react";
10
10
  import CodeBlock from "@theme/CodeBlock";
11
11
  import SchemaTabs from "@theme/SchemaTabs";
12
12
  import TabItem from "@theme/TabItem";
13
- /* eslint-disable import/no-extraneous-dependencies*/
14
- import { createDescription } from "docusaurus-theme-openapi-docs/lib/markdown/createDescription";
15
- /* eslint-disable import/no-extraneous-dependencies*/
16
- import {
17
- getQualifierMessage,
18
- getSchemaName,
19
- } from "docusaurus-theme-openapi-docs/lib/markdown/schema";
20
- /* eslint-disable import/no-extraneous-dependencies*/
21
- import {
22
- guard,
23
- toString,
24
- } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
25
13
  import ReactMarkdown from "react-markdown";
26
14
  import rehypeRaw from "rehype-raw";
27
15
 
16
+ import { createDescription } from "../../markdown/createDescription";
17
+ import { getQualifierMessage, getSchemaName } from "../../markdown/schema";
18
+ import { guard, toString } from "../../markdown/utils";
19
+
20
+ interface Map<T> {
21
+ [key: string]: T;
22
+ }
23
+
24
+ export interface ExampleObject {
25
+ summary?: string;
26
+ description?: string;
27
+ value?: any;
28
+ externalValue?: string;
29
+ }
30
+
31
+ export interface Props {
32
+ param: {
33
+ description: string;
34
+ example: any;
35
+ examples: Map<ExampleObject>;
36
+ name: string;
37
+ required: boolean;
38
+ schema: any;
39
+ };
40
+ }
41
+
28
42
  function ParamsItem({
29
43
  param: { description, example, examples, name, required, schema },
30
- }) {
44
+ }: Props) {
31
45
  if (!schema || !schema?.type) {
32
46
  schema = { type: "any" };
33
47
  }
@@ -97,6 +111,7 @@ function ParamsItem({
97
111
  <strong>Examples:</strong>
98
112
  <SchemaTabs>
99
113
  {exampleEntries.map(([exampleName, exampleProperties]) => (
114
+ // @ts-ignore
100
115
  <TabItem value={exampleName} label={exampleName}>
101
116
  {exampleProperties.summary && <p>{exampleProperties.summary}</p>}
102
117
  {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"}>
@@ -5,18 +5,29 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React from "react";
8
+ import React, { ReactNode } from "react";
9
9
 
10
10
  import CodeBlock from "@theme/CodeBlock";
11
- /* eslint-disable import/no-extraneous-dependencies*/
12
11
  import clsx from "clsx";
13
- import { createDescription } from "docusaurus-theme-openapi-docs/lib/markdown/createDescription";
14
- /* eslint-disable import/no-extraneous-dependencies*/
15
- import { guard } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
16
12
  import ReactMarkdown from "react-markdown";
17
13
  import rehypeRaw from "rehype-raw";
18
14
 
19
- function SchemaItem({
15
+ import { createDescription } from "../../markdown/createDescription";
16
+ import { guard } from "../../markdown/utils";
17
+
18
+ export interface Props {
19
+ children: ReactNode;
20
+ collapsible: boolean;
21
+ name: string;
22
+ qualifierMessage: string | undefined;
23
+ required: boolean;
24
+ schemaName: string;
25
+ // TODO should probably be typed
26
+ schema: any;
27
+ discriminator: boolean;
28
+ }
29
+
30
+ export default function SchemaItem({
20
31
  children: collapsibleSchemaContent,
21
32
  collapsible,
22
33
  name,
@@ -24,7 +35,7 @@ function SchemaItem({
24
35
  required,
25
36
  schemaName,
26
37
  schema,
27
- }) {
38
+ }: Props) {
28
39
  let deprecated;
29
40
  let schemaDescription;
30
41
  let defaultValue;
@@ -119,5 +130,3 @@ function SchemaItem({
119
130
  </div>
120
131
  );
121
132
  }
122
-
123
- export default SchemaItem;
@@ -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
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) => {
32
- let focusElement = null;
53
+
54
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
55
+ let focusElement: HTMLLIElement | null = null;
56
+
33
57
  switch (event.key) {
34
58
  case "Enter": {
35
59
  handleTabChange(event);
@@ -37,27 +61,28 @@ 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
- if (entry.target.offsetWidth < entry.target.scrollWidth) {
85
+ if (entry.target.clientWidth < entry.target.scrollWidth) {
61
86
  setShowTabArrows(true);
62
87
  } else {
63
88
  setShowTabArrows(false);
@@ -65,7 +90,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
65
90
  }
66
91
  });
67
92
 
68
- resizeObserver.observe(tabItemListContainerRef.current);
93
+ resizeObserver.observe(tabItemListContainerRef.current!);
69
94
 
70
95
  return () => {
71
96
  resizeObserver.disconnect();
@@ -73,11 +98,11 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
73
98
  }, []);
74
99
 
75
100
  const handleRightClick = () => {
76
- tabItemListContainerRef.current.scrollLeft += 90;
101
+ tabItemListContainerRef.current!.scrollLeft += 90;
77
102
  };
78
103
 
79
104
  const handleLeftClick = () => {
80
- tabItemListContainerRef.current.scrollLeft -= 90;
105
+ tabItemListContainerRef.current!.scrollLeft -= 90;
81
106
  };
82
107
 
83
108
  return (
@@ -115,7 +140,7 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
115
140
  className={clsx(
116
141
  "tabs__item",
117
142
  "openapi-tabs__schema-item",
118
- attributes?.className,
143
+ attributes?.className as string,
119
144
  {
120
145
  active: selectedValue === value,
121
146
  }
@@ -134,13 +159,17 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
134
159
  </div>
135
160
  );
136
161
  }
137
- function TabContent({ lazy, children, selectedValue }) {
138
- // eslint-disable-next-line no-param-reassign
139
- children = Array.isArray(children) ? children : [children];
140
- const flattenedChildren = flatten(children);
141
-
162
+ function TabContent({
163
+ lazy,
164
+ children,
165
+ selectedValue,
166
+ }: TabProps & ReturnType<typeof useTabs>) {
167
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
168
+ Boolean
169
+ ) as ReactElement<TabItemProps>[];
170
+ const flattenedChildTabs = flatten(childTabs);
142
171
  if (lazy) {
143
- const selectedTabItem = flattenedChildren.find(
172
+ const selectedTabItem = flattenedChildTabs.find(
144
173
  (tabItem) => tabItem.props.value === selectedValue
145
174
  );
146
175
  if (!selectedTabItem) {
@@ -151,7 +180,7 @@ function TabContent({ lazy, children, selectedValue }) {
151
180
  }
152
181
  return (
153
182
  <div className="margin-top--md">
154
- {children.map((tabItem, i) =>
183
+ {childTabs.map((tabItem, i) =>
155
184
  cloneElement(tabItem, {
156
185
  key: i,
157
186
  hidden: tabItem.props.value !== selectedValue,
@@ -160,7 +189,7 @@ function TabContent({ lazy, children, selectedValue }) {
160
189
  </div>
161
190
  );
162
191
  }
163
- function TabsComponent(props) {
192
+ function TabsComponent(props: TabProps): React.JSX.Element {
164
193
  const tabs = useTabs(props);
165
194
  return (
166
195
  <div className="openapi-tabs__schema-container">
@@ -169,7 +198,7 @@ function TabsComponent(props) {
169
198
  </div>
170
199
  );
171
200
  }
172
- export default function SchemaTabs(props) {
201
+ export default function SchemaTabs(props: TabProps): React.JSX.Element {
173
202
  const isBrowser = useIsBrowser();
174
203
  return (
175
204
  <TabsComponent
@@ -177,6 +206,8 @@ export default function SchemaTabs(props) {
177
206
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
178
207
  key={String(isBrowser)}
179
208
  {...props}
180
- />
209
+ >
210
+ {sanitizeTabsChildren(props.children)}
211
+ </TabsComponent>
181
212
  );
182
213
  }
@@ -8,6 +8,73 @@
8
8
  /// <reference types="@docusaurus/theme-classic" />
9
9
 
10
10
  declare module "@docusaurus/theme-common/internal" {
11
- function useDoc(): any;
12
- export const { useDoc };
11
+ import { CSSProperties, ReactNode, RefObject } from "react";
12
+
13
+ import type { PropDocContent } from "@docusaurus/plugin-content-docs";
14
+ import { MagicCommentConfig } from "@docusaurus/theme-common/lib/utils/codeBlockUtils";
15
+ import {
16
+ TabsProps as ITabsProps,
17
+ TabValue,
18
+ } from "@docusaurus/theme-common/lib/utils/tabsUtils";
19
+ import { Props as ICodeBlockProps } from "@theme/CodeBlock";
20
+ import { Props as ICopyButtonProps } from "@theme/CodeBlock/CopyButton";
21
+ import { Props as ILineProps } from "@theme/CodeBlock/Line";
22
+ import { PrismTheme } from "prism-react-renderer";
23
+
24
+ export interface TabProps extends ITabsProps {}
25
+
26
+ export interface CopyButtonProps extends ICopyButtonProps {}
27
+ export interface LineProps extends ILineProps {}
28
+ export interface CodeBlockProps extends ICodeBlockProps {}
29
+
30
+ export function useDoc();
31
+
32
+ export function usePrismTheme(): PrismTheme;
33
+
34
+ export function sanitizeTabsChildren(children: TabProps["children"]);
35
+
36
+ export function getPrismCssVariables(prismTheme: PrismTheme): CSSProperties;
37
+
38
+ export function parseCodeBlockTitle(metastring?: string): string;
39
+
40
+ export function parseLanguage(className: string): string | undefined;
41
+
42
+ export function containsLineNumbers(metastring?: string): boolean;
43
+
44
+ export function useScrollPositionBlocker(): {
45
+ blockElementScrollPositionUntilNextRender: (el: HTMLElement) => void;
46
+ };
47
+
48
+ export function DocProvider({
49
+ children,
50
+ content,
51
+ }: {
52
+ children: ReactNode;
53
+ content: PropDocContent;
54
+ });
55
+
56
+ export function useTabs(props: TabProps): {
57
+ selectedValue: string;
58
+ selectValue: (value: string) => void;
59
+ tabValues: readonly TabValue[];
60
+ };
61
+
62
+ export function parseLines(
63
+ content: string,
64
+ options: {
65
+ metastring: string | undefined;
66
+ language: string | undefined;
67
+ magicComments: MagicCommentConfig[];
68
+ }
69
+ ): {
70
+ lineClassNames: { [lineIndex: number]: string[] };
71
+ code: string;
72
+ };
73
+
74
+ export function useCodeWordWrap(): {
75
+ readonly codeBlockRef: RefObject<HTMLPreElement>;
76
+ readonly isEnabled: boolean;
77
+ readonly isCodeScrollable: boolean;
78
+ readonly toggle: () => void;
79
+ };
13
80
  }
package/tsconfig.json CHANGED
@@ -7,7 +7,10 @@
7
7
  "target": "ESNext",
8
8
  "noEmit": false,
9
9
  "outDir": "lib",
10
- "jsx": "react"
10
+ "jsx": "react",
11
+ "paths": {
12
+ "@theme/*": ["./src/theme/*"]
13
+ }
11
14
  },
12
15
  "include": ["src"]
13
16
  }