docusaurus-theme-openapi-docs 1.2.2 → 1.3.0

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 (64) hide show
  1. package/lib/theme/ApiDemoPanel/Accept/index.js +1 -1
  2. package/lib/theme/ApiDemoPanel/Authorization/index.js +2 -2
  3. package/lib/theme/ApiDemoPanel/Body/index.js +104 -9
  4. package/lib/theme/ApiDemoPanel/ContentType/index.js +1 -1
  5. package/lib/theme/ApiDemoPanel/Curl/index.js +2 -2
  6. package/lib/theme/ApiDemoPanel/Execute/index.js +1 -1
  7. package/lib/theme/ApiDemoPanel/ParamOptions/index.js +1 -1
  8. package/lib/theme/ApiDemoPanel/Request/index.js +2 -2
  9. package/lib/theme/ApiDemoPanel/Response/index.js +1 -1
  10. package/lib/theme/ApiDemoPanel/SecuritySchemes/index.js +1 -1
  11. package/lib/theme/ApiDemoPanel/Server/index.js +27 -10
  12. package/lib/theme/ApiDemoPanel/Server/slice.js +3 -2
  13. package/lib/theme/ApiDemoPanel/index.js +8 -72
  14. package/lib/theme/ApiDemoPanel/persistanceMiddleware.js +22 -0
  15. package/lib/theme/ApiItem/Layout/styles.module.css +11 -3
  16. package/lib/theme/{ApiDemoPanel → ApiItem}/hooks.js +0 -0
  17. package/lib/theme/ApiItem/index.js +101 -22
  18. package/lib/theme/{ApiDemoPanel → ApiItem}/store.js +7 -7
  19. package/lib/theme/MimeTabs/index.js +29 -1
  20. package/lib/theme/MimeTabs/styles.module.css +1 -0
  21. package/lib/theme/SchemaTabs/index.js +4 -1
  22. package/lib-next/theme/ApiDemoPanel/Accept/index.js +1 -1
  23. package/lib-next/theme/ApiDemoPanel/Authorization/index.js +1 -1
  24. package/lib-next/theme/ApiDemoPanel/Body/index.js +114 -7
  25. package/lib-next/theme/ApiDemoPanel/ContentType/index.js +1 -1
  26. package/lib-next/theme/ApiDemoPanel/Curl/index.js +1 -1
  27. package/lib-next/theme/ApiDemoPanel/Execute/index.js +1 -1
  28. package/lib-next/theme/ApiDemoPanel/ParamOptions/index.js +1 -1
  29. package/lib-next/theme/ApiDemoPanel/Request/index.js +1 -1
  30. package/lib-next/theme/ApiDemoPanel/Response/index.js +1 -1
  31. package/lib-next/theme/ApiDemoPanel/SecuritySchemes/index.js +1 -1
  32. package/lib-next/theme/ApiDemoPanel/Server/index.js +38 -10
  33. package/lib-next/theme/ApiDemoPanel/Server/slice.js +5 -3
  34. package/lib-next/theme/ApiDemoPanel/index.js +7 -69
  35. package/lib-next/theme/ApiDemoPanel/persistanceMiddleware.js +20 -0
  36. package/lib-next/theme/ApiItem/Layout/styles.module.css +11 -3
  37. package/lib-next/theme/{ApiDemoPanel → ApiItem}/hooks.js +0 -0
  38. package/lib-next/theme/ApiItem/index.js +104 -26
  39. package/lib-next/theme/{ApiDemoPanel → ApiItem}/store.js +7 -7
  40. package/lib-next/theme/MimeTabs/index.js +29 -1
  41. package/lib-next/theme/MimeTabs/styles.module.css +1 -0
  42. package/lib-next/theme/SchemaTabs/index.js +4 -1
  43. package/package.json +3 -3
  44. package/src/theme/ApiDemoPanel/Accept/index.tsx +1 -1
  45. package/src/theme/ApiDemoPanel/Authorization/index.tsx +1 -1
  46. package/src/theme/ApiDemoPanel/Body/index.tsx +107 -7
  47. package/src/theme/ApiDemoPanel/ContentType/index.tsx +1 -1
  48. package/src/theme/ApiDemoPanel/Curl/index.tsx +1 -1
  49. package/src/theme/ApiDemoPanel/Execute/index.tsx +1 -1
  50. package/src/theme/ApiDemoPanel/ParamOptions/index.tsx +1 -1
  51. package/src/theme/ApiDemoPanel/Request/index.tsx +1 -1
  52. package/src/theme/ApiDemoPanel/Response/index.tsx +1 -1
  53. package/src/theme/ApiDemoPanel/SecuritySchemes/index.tsx +1 -1
  54. package/src/theme/ApiDemoPanel/Server/index.tsx +34 -6
  55. package/src/theme/ApiDemoPanel/Server/slice.ts +6 -7
  56. package/src/theme/ApiDemoPanel/index.tsx +10 -73
  57. package/src/theme/ApiDemoPanel/persistanceMiddleware.ts +21 -1
  58. package/src/theme/ApiItem/Layout/styles.module.css +11 -3
  59. package/src/theme/{ApiDemoPanel → ApiItem}/hooks.ts +0 -0
  60. package/src/theme/ApiItem/index.tsx +103 -27
  61. package/src/theme/{ApiDemoPanel → ApiItem}/store.ts +7 -7
  62. package/src/theme/MimeTabs/index.js +29 -1
  63. package/src/theme/MimeTabs/styles.module.css +1 -0
  64. package/src/theme/SchemaTabs/index.js +4 -1
@@ -13,11 +13,11 @@ import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/type
13
13
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
14
14
 
15
15
  import { ThemeConfig } from "../../../types";
16
+ import { useTypedSelector } from "../../ApiItem/hooks";
16
17
  import Accept from "../Accept";
17
18
  import Authorization from "../Authorization";
18
19
  import Body from "../Body";
19
20
  import Execute from "../Execute";
20
- import { useTypedSelector } from "../hooks";
21
21
  import ParamOptions from "../ParamOptions";
22
22
  import Server from "../Server";
23
23
  import styles from "./styles.module.css";
@@ -9,7 +9,7 @@ import React from "react";
9
9
 
10
10
  import CodeBlock from "@theme/CodeBlock";
11
11
 
12
- import { useTypedDispatch, useTypedSelector } from "../hooks";
12
+ import { useTypedDispatch, useTypedSelector } from "../../ApiItem/hooks";
13
13
  import { clearResponse } from "./slice";
14
14
 
15
15
  // TODO: We probably shouldn't attempt to format XML...
@@ -9,7 +9,7 @@ import React from "react";
9
9
 
10
10
  import Link from "@docusaurus/Link";
11
11
 
12
- import { useTypedSelector } from "../hooks";
12
+ import { useTypedSelector } from "../../ApiItem/hooks";
13
13
 
14
14
  function SecuritySchemes(props: any) {
15
15
  const options = useTypedSelector((state) => state.auth.options);
@@ -7,8 +7,8 @@
7
7
 
8
8
  import React, { useState } from "react";
9
9
 
10
+ import { useTypedDispatch, useTypedSelector } from "../../ApiItem/hooks";
10
11
  import FloatingButton from "../FloatingButton";
11
- import { useTypedDispatch, useTypedSelector } from "../hooks";
12
12
  import FormItem from "./../FormItem";
13
13
  import FormSelect from "./../FormSelect";
14
14
  import FormTextInput from "./../FormTextInput";
@@ -19,7 +19,6 @@ function Server() {
19
19
  const [isEditing, setIsEditing] = useState(false);
20
20
  const value = useTypedSelector((state) => state.server.value);
21
21
  const options = useTypedSelector((state) => state.server.options);
22
-
23
22
  const dispatch = useTypedDispatch();
24
23
 
25
24
  if (options.length <= 0) {
@@ -30,6 +29,20 @@ function Server() {
30
29
  return null;
31
30
  }
32
31
 
32
+ if (!value) {
33
+ const defaultOption = options[0];
34
+ dispatch(setServer(JSON.stringify(defaultOption)));
35
+ }
36
+
37
+ // Default to first option when existing server state is mismatched
38
+ if (value) {
39
+ const urlExists = options.find((s) => s.url === value.url);
40
+ if (!urlExists) {
41
+ const defaultOption = options[0];
42
+ dispatch(setServer(JSON.stringify(defaultOption)));
43
+ }
44
+ }
45
+
33
46
  if (!isEditing) {
34
47
  let url = "";
35
48
  if (value) {
@@ -58,14 +71,21 @@ function Server() {
58
71
  </FloatingButton>
59
72
  );
60
73
  }
61
-
62
74
  return (
63
75
  <div className={styles.optionsPanel}>
64
76
  <FloatingButton onClick={() => setIsEditing(false)} label="Hide">
65
77
  <FormItem label="Base URL">
66
78
  <FormSelect
67
79
  options={options.map((s) => s.url)}
68
- onChange={(e) => dispatch(setServer(e.target.value))}
80
+ onChange={(e) => {
81
+ dispatch(
82
+ setServer(
83
+ JSON.stringify(
84
+ options.filter((s) => s.url === e.target.value)[0]
85
+ )
86
+ )
87
+ );
88
+ }}
69
89
  value={value?.url}
70
90
  />
71
91
  <small>{value?.description}</small>
@@ -79,9 +99,12 @@ function Server() {
79
99
  options={value.variables[key].enum}
80
100
  onChange={(e) => {
81
101
  dispatch(
82
- setServerVariable({ key, value: e.target.value })
102
+ setServerVariable(
103
+ JSON.stringify({ key, value: e.target.value })
104
+ )
83
105
  );
84
106
  }}
107
+ value={value?.variables[key].default}
85
108
  />
86
109
  </FormItem>
87
110
  );
@@ -91,8 +114,13 @@ function Server() {
91
114
  <FormTextInput
92
115
  placeholder={value.variables?.[key].default}
93
116
  onChange={(e) => {
94
- dispatch(setServerVariable({ key, value: e.target.value }));
117
+ dispatch(
118
+ setServerVariable(
119
+ JSON.stringify({ key, value: e.target.value })
120
+ )
121
+ );
95
122
  }}
123
+ value={value?.variables?.[key].default}
96
124
  />
97
125
  </FormItem>
98
126
  );
@@ -21,15 +21,14 @@ export const slice = createSlice({
21
21
  initialState,
22
22
  reducers: {
23
23
  setServer: (state, action: PayloadAction<string>) => {
24
- state.value = state.options.find((s) => s.url === action.payload);
24
+ state.value = state.options.find(
25
+ (s) => s.url === JSON.parse(action.payload).url
26
+ );
25
27
  },
26
- setServerVariable: (
27
- state,
28
- action: PayloadAction<{ key: string; value: string }>
29
- ) => {
28
+ setServerVariable: (state, action: PayloadAction<string>) => {
30
29
  if (state.value?.variables) {
31
- state.value.variables[action.payload.key].default =
32
- action.payload.value;
30
+ const parsedPayload = JSON.parse(action.payload);
31
+ state.value.variables[parsedPayload.key].default = parsedPayload.value;
33
32
  }
34
33
  },
35
34
  },
@@ -7,21 +7,14 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
- import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
11
10
  import sdk from "@paloaltonetworks/postman-collection";
12
- import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
13
11
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
14
- import { Provider } from "react-redux";
15
12
 
16
- import { ThemeConfig } from "../../types";
17
- import { createAuth } from "./Authorization/slice";
18
13
  import Curl from "./Curl";
19
14
  import MethodEndpoint from "./MethodEndpoint";
20
- import { createPersistanceMiddleware } from "./persistanceMiddleware";
21
15
  import Request from "./Request";
22
16
  import Response from "./Response";
23
17
  import SecuritySchemes from "./SecuritySchemes";
24
- import { createStoreWithState } from "./store";
25
18
  import styles from "./styles.module.css";
26
19
 
27
20
  function ApiDemoPanel({
@@ -31,76 +24,20 @@ function ApiDemoPanel({
31
24
  item: NonNullable<ApiItem>;
32
25
  infoPath: string;
33
26
  }) {
34
- const { siteConfig } = useDocusaurusContext();
35
- const themeConfig = siteConfig.themeConfig as ThemeConfig;
36
- const options = themeConfig.api;
37
27
  const postman = new sdk.Request(item.postman);
38
-
39
- const acceptArray = Array.from(
40
- new Set(
41
- Object.values(item.responses ?? {})
42
- .map((response: any) => Object.keys(response.content ?? {}))
43
- .flat()
44
- )
45
- );
46
-
47
- const content = item.requestBody?.content ?? {};
48
-
49
- const contentTypeArray = Object.keys(content);
50
-
51
- const servers = item.servers ?? [];
52
-
53
- const params = {
54
- path: [] as ParameterObject[],
55
- query: [] as ParameterObject[],
56
- header: [] as ParameterObject[],
57
- cookie: [] as ParameterObject[],
58
- };
59
-
60
- item.parameters?.forEach(
61
- (param: { in: "path" | "query" | "header" | "cookie" }) => {
62
- const paramType = param.in;
63
- const paramsArray: ParameterObject[] = params[paramType];
64
- paramsArray.push(param as ParameterObject);
65
- }
66
- );
67
-
68
- const auth = createAuth({
69
- security: item.security,
70
- securitySchemes: item.securitySchemes,
71
- options,
72
- });
73
-
74
- const persistanceMiddleware = createPersistanceMiddleware(options);
75
-
76
- const store2 = createStoreWithState(
77
- {
78
- accept: { value: acceptArray[0], options: acceptArray },
79
- contentType: { value: contentTypeArray[0], options: contentTypeArray },
80
- server: { value: servers[0], options: servers },
81
- response: { value: undefined },
82
- body: { type: "empty" },
83
- params,
84
- auth,
85
- },
86
- [persistanceMiddleware]
87
- );
88
-
89
28
  const { path, method } = item;
90
29
 
91
30
  return (
92
- <Provider store={store2}>
93
- <div className={styles.apiDemoPanelContainer}>
94
- <MethodEndpoint method={method} path={path} />
95
- <SecuritySchemes infoPath={infoPath} />
96
- <Request item={item} />
97
- <Response />
98
- <Curl
99
- postman={postman}
100
- codeSamples={(item as any)["x-code-samples"] ?? []}
101
- />
102
- </div>
103
- </Provider>
31
+ <div className={styles.apiDemoPanelContainer}>
32
+ <MethodEndpoint method={method} path={path} />
33
+ <SecuritySchemes infoPath={infoPath} />
34
+ <Request item={item} />
35
+ <Response />
36
+ <Curl
37
+ postman={postman}
38
+ codeSamples={(item as any)["x-code-samples"] ?? []}
39
+ />
40
+ </div>
104
41
  );
105
42
  }
106
43
 
@@ -8,9 +8,9 @@
8
8
  import { Middleware } from "@reduxjs/toolkit";
9
9
 
10
10
  import { ThemeConfig } from "../../types";
11
+ import { AppDispatch, RootState } from "../ApiItem/store";
11
12
  import { setAuthData, setSelectedAuth } from "./Authorization/slice";
12
13
  import { createStorage, hashArray } from "./storage-utils";
13
- import { AppDispatch, RootState } from "./store";
14
14
 
15
15
  export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
16
16
  const persistanceMiddleware: Middleware<{}, RootState, AppDispatch> =
@@ -40,6 +40,26 @@ export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
40
40
  }
41
41
  }
42
42
 
43
+ if (action.type === "contentType/setContentType") {
44
+ storage.setItem("contentType", action.payload);
45
+ }
46
+
47
+ if (action.type === "accept/setAccept") {
48
+ storage.setItem("accept", action.payload);
49
+ }
50
+
51
+ if (action.type === "server/setServer") {
52
+ storage.setItem("server", action.payload);
53
+ }
54
+
55
+ if (action.type === "server/setServerVariable") {
56
+ const server = storage.getItem("server") ?? "{}";
57
+ const variables = JSON.parse(action.payload);
58
+ let serverObject = JSON.parse(server);
59
+ serverObject.variables[variables.key].default = variables.value;
60
+ storage.setItem("server", JSON.stringify(serverObject));
61
+ }
62
+
43
63
  return result;
44
64
  };
45
65
  return persistanceMiddleware;
@@ -154,12 +154,15 @@
154
154
  margin-bottom: 0;
155
155
  }
156
156
 
157
- :global(.theme-api-markdown li::before) {
157
+ :global([class^="paramsItem"]::before),
158
+ :global([class^="schemaItem"]::before) {
158
159
  position: absolute;
159
160
  top: 10px;
160
161
  left: 0;
161
- width: 0.7rem; /* width of horizontal line */
162
- height: 0.5rem; /* vertical position of line */
162
+ width: 0.7rem;
163
+ /* width of horizontal line */
164
+ height: 0.5rem;
165
+ /* vertical position of line */
163
166
  vertical-align: top;
164
167
  border-bottom: thin solid var(--ifm-color-gray-500);
165
168
  content: "";
@@ -410,3 +413,8 @@
410
413
  max-height: 500px;
411
414
  overflow: auto;
412
415
  }
416
+
417
+ /* Prism code styles */
418
+ :global(.prism-code.language-json) {
419
+ white-space: pre !important;
420
+ }
File without changes
@@ -9,58 +9,134 @@ import React from "react";
9
9
 
10
10
  import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
11
11
  import { HtmlClassNameProvider } from "@docusaurus/theme-common";
12
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
12
13
  import type { Props } from "@theme/DocItem";
13
14
  import clsx from "clsx";
15
+ import { ServerObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types";
14
16
  import type { ApiItem as ApiItemType } from "docusaurus-plugin-openapi-docs/lib/types";
17
+ import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
18
+ import { Provider } from "react-redux";
15
19
 
16
20
  import { DocFrontMatter } from "../../types";
21
+ import { ThemeConfig } from "../../types";
22
+ import { createAuth } from "../ApiDemoPanel/Authorization/slice";
23
+ import { createPersistanceMiddleware } from "../ApiDemoPanel/persistanceMiddleware";
17
24
  import DocItemLayout from "./Layout";
18
25
  import DocItemMetadata from "./Metadata";
26
+ import { createStoreWithState } from "./store";
19
27
 
20
28
  const { DocProvider } = require("@docusaurus/theme-common/internal");
21
29
 
22
30
  let ApiDemoPanel = (_: { item: any; infoPath: any }) => (
23
31
  <div style={{ marginTop: "3.5em" }} />
24
32
  );
25
- if (ExecutionEnvironment.canUseDOM) {
26
- ApiDemoPanel = require("@theme/ApiDemoPanel").default;
27
- }
33
+
34
+ let DocItem = (props: Props) => {
35
+ return <div style={{ marginTop: "3.5em" }} />;
36
+ };
28
37
 
29
38
  interface ApiFrontMatter extends DocFrontMatter {
30
39
  readonly api?: ApiItemType;
31
40
  }
32
41
 
33
- export default function DocItem(props: Props): JSX.Element {
34
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
42
+ if (ExecutionEnvironment.canUseDOM) {
43
+ ApiDemoPanel = require("@theme/ApiDemoPanel").default;
35
44
 
36
- const DocContent = () => {
45
+ DocItem = function DocItem(props: Props): JSX.Element {
46
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
37
47
  const MDXComponent = props.content;
38
48
  const { frontMatter } = MDXComponent;
39
49
  const { info_path: infoPath } = frontMatter as DocFrontMatter;
40
50
  const { api } = frontMatter as ApiFrontMatter;
51
+ const { siteConfig } = useDocusaurusContext();
52
+ const themeConfig = siteConfig.themeConfig as ThemeConfig;
53
+ const options = themeConfig.api;
41
54
 
42
- return (
43
- <div className="row">
44
- <div className={clsx("col", api ? "col--7" : "col--12")}>
45
- <MDXComponent />
46
- </div>
47
- {api && (
48
- <div className="col col--5">
49
- <ApiDemoPanel item={api} infoPath={infoPath} />
55
+ const acceptArray = Array.from(
56
+ new Set(
57
+ Object.values(api?.responses ?? {})
58
+ .map((response: any) => Object.keys(response.content ?? {}))
59
+ .flat()
60
+ )
61
+ );
62
+
63
+ const content = api?.requestBody?.content ?? {};
64
+ const contentTypeArray = Object.keys(content);
65
+ const servers = api?.servers ?? [];
66
+
67
+ const params = {
68
+ path: [] as ParameterObject[],
69
+ query: [] as ParameterObject[],
70
+ header: [] as ParameterObject[],
71
+ cookie: [] as ParameterObject[],
72
+ };
73
+
74
+ api?.parameters?.forEach(
75
+ (param: { in: "path" | "query" | "header" | "cookie" }) => {
76
+ const paramType = param.in;
77
+ const paramsArray: ParameterObject[] = params[paramType];
78
+ paramsArray.push(param as ParameterObject);
79
+ }
80
+ );
81
+
82
+ const auth = createAuth({
83
+ security: api?.security,
84
+ securitySchemes: api?.securitySchemes,
85
+ options,
86
+ });
87
+
88
+ const persistanceMiddleware = createPersistanceMiddleware(options);
89
+ const acceptValue = window?.sessionStorage.getItem("accept");
90
+ const contentTypeValue = window?.sessionStorage.getItem("contentType");
91
+ const server = window?.sessionStorage.getItem("server");
92
+ const serverObject = (JSON.parse(server!) as ServerObject) ?? {};
93
+ const store2 = createStoreWithState(
94
+ {
95
+ accept: { value: acceptValue || acceptArray[0], options: acceptArray },
96
+ contentType: {
97
+ value: contentTypeValue || contentTypeArray[0],
98
+ options: contentTypeArray,
99
+ },
100
+ server: {
101
+ value: serverObject.url ? serverObject : undefined,
102
+ options: servers,
103
+ },
104
+ response: { value: undefined },
105
+ body: { type: "empty" },
106
+ params,
107
+ auth,
108
+ },
109
+ [persistanceMiddleware]
110
+ );
111
+
112
+ const DocContent = () => {
113
+ return (
114
+ <div className="row">
115
+ <div className={clsx("col", api ? "col--7" : "col--12")}>
116
+ <MDXComponent />
50
117
  </div>
51
- )}
52
- </div>
118
+ {api && (
119
+ <div className="col col--5">
120
+ <ApiDemoPanel item={api} infoPath={infoPath} />
121
+ </div>
122
+ )}
123
+ </div>
124
+ );
125
+ };
126
+
127
+ return (
128
+ <Provider store={store2}>
129
+ <DocProvider content={props.content}>
130
+ <HtmlClassNameProvider className={docHtmlClassName}>
131
+ <DocItemMetadata />
132
+ <DocItemLayout>
133
+ <DocContent />
134
+ </DocItemLayout>
135
+ </HtmlClassNameProvider>
136
+ </DocProvider>
137
+ </Provider>
53
138
  );
54
139
  };
55
-
56
- return (
57
- <DocProvider content={props.content}>
58
- <HtmlClassNameProvider className={docHtmlClassName}>
59
- <DocItemMetadata />
60
- <DocItemLayout>
61
- <DocContent />
62
- </DocItemLayout>
63
- </HtmlClassNameProvider>
64
- </DocProvider>
65
- );
66
140
  }
141
+
142
+ export default DocItem;
@@ -7,13 +7,13 @@
7
7
 
8
8
  import { configureStore, combineReducers } from "@reduxjs/toolkit";
9
9
 
10
- import accept from "./Accept/slice";
11
- import auth from "./Authorization/slice";
12
- import body from "./Body/slice";
13
- import contentType from "./ContentType/slice";
14
- import params from "./ParamOptions/slice";
15
- import response from "./Response/slice";
16
- import server from "./Server/slice";
10
+ import accept from "../ApiDemoPanel/Accept/slice";
11
+ import auth from "../ApiDemoPanel/Authorization/slice";
12
+ import body from "../ApiDemoPanel/Body/slice";
13
+ import contentType from "../ApiDemoPanel/ContentType/slice";
14
+ import params from "../ApiDemoPanel/ParamOptions/slice";
15
+ import response from "../ApiDemoPanel/Response/slice";
16
+ import server from "../ApiDemoPanel/Server/slice";
17
17
 
18
18
  const rootReducer = combineReducers({
19
19
  accept,
@@ -18,6 +18,9 @@ import { duplicates } from "@docusaurus/theme-common";
18
18
  import useIsBrowser from "@docusaurus/useIsBrowser";
19
19
  import clsx from "clsx";
20
20
 
21
+ import { setAccept } from "../ApiDemoPanel/Accept/slice";
22
+ import { setContentType } from "../ApiDemoPanel/ContentType/slice";
23
+ import { useTypedDispatch, useTypedSelector } from "../ApiItem/hooks";
21
24
  import styles from "./styles.module.css"; // A very rough duck type, but good enough to guard against mistakes while
22
25
 
23
26
  const {
@@ -39,6 +42,7 @@ function MimeTabsComponent(props) {
39
42
  values: valuesProp,
40
43
  groupId,
41
44
  className,
45
+ schemaType,
42
46
  } = props;
43
47
  const children = Children.map(props.children, (child) => {
44
48
  if (isValidElement(child) && isTabItem(child)) {
@@ -105,12 +109,22 @@ function MimeTabsComponent(props) {
105
109
  }
106
110
  }
107
111
 
112
+ const dispatch = useTypedDispatch();
113
+ const isRequestSchema = schemaType?.toLowerCase() === "request";
114
+
108
115
  const handleTabChange = (event) => {
116
+ event.preventDefault();
109
117
  const newTab = event.currentTarget;
110
118
  const newTabIndex = tabRefs.indexOf(newTab);
111
119
  const newTabValue = values[newTabIndex].value;
112
120
 
113
121
  if (newTabValue !== selectedValue) {
122
+ if (isRequestSchema) {
123
+ dispatch(setContentType(newTabValue));
124
+ } else {
125
+ dispatch(setAccept(newTabValue));
126
+ }
127
+
114
128
  blockElementScrollPositionUntilNextRender(newTab);
115
129
  setSelectedValue(newTabValue);
116
130
 
@@ -120,6 +134,20 @@ function MimeTabsComponent(props) {
120
134
  }
121
135
  };
122
136
 
137
+ const contentTypeVal = useTypedSelector((state) => state.contentType.value);
138
+ const acceptTypeVal = useTypedSelector((state) => state.accept.value);
139
+
140
+ useEffect(() => {
141
+ if (tabRefs.length > 1) {
142
+ if (isRequestSchema) {
143
+ setSelectedValue(contentTypeVal);
144
+ } else {
145
+ setSelectedValue(acceptTypeVal);
146
+ }
147
+ }
148
+ // eslint-disable-next-line react-hooks/exhaustive-deps
149
+ }, [contentTypeVal, acceptTypeVal]);
150
+
123
151
  const handleKeydown = (event) => {
124
152
  let focusElement = null;
125
153
 
@@ -197,7 +225,7 @@ function MimeTabsComponent(props) {
197
225
  ref={(tabControl) => tabRefs.push(tabControl)}
198
226
  onKeyDown={handleKeydown}
199
227
  onFocus={handleTabChange}
200
- onClick={handleTabChange}
228
+ onClick={(e) => handleTabChange(e)}
201
229
  {...attributes}
202
230
  className={clsx(
203
231
  "tabs__item",
@@ -17,6 +17,7 @@
17
17
  font-weight: var(--ifm-font-weight-normal);
18
18
  /* color: var(--openapi-code-dim-dark); */
19
19
  font-size: 12px;
20
+ white-space: nowrap;
20
21
  }
21
22
 
22
23
  .tabItem:active {
@@ -227,7 +227,10 @@ function SchemaTabsComponent(props) {
227
227
  cloneElement(
228
228
  children.filter(
229
229
  (tabItem) => tabItem.props.value === selectedValue
230
- )[0],
230
+ )[0] ?? // TODO: see if there's a better way to handle this
231
+ children.filter(
232
+ (tabItem) => tabItem.props.value === defaultValue
233
+ )[0],
231
234
  {
232
235
  className: "margin-vert--md",
233
236
  }