docusaurus-theme-openapi-docs 0.0.0-1240 → 0.0.0-1247

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 (30) hide show
  1. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +74 -2
  2. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +66 -2
  3. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +65 -1
  4. package/lib/theme/ApiItem/index.js +47 -33
  5. package/lib/theme/RequestSchema/index.js +58 -56
  6. package/lib/theme/ResponseSchema/index.js +25 -22
  7. package/lib/theme/Schema/index.js +15 -5
  8. package/lib/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
  9. package/lib/theme/SchemaExpansion/context.d.ts +24 -0
  10. package/lib/theme/SchemaExpansion/context.js +187 -0
  11. package/lib/theme/SchemaExpansion/index.d.ts +4 -0
  12. package/lib/theme/SchemaExpansion/index.js +315 -0
  13. package/lib/theme/styles.scss +1 -0
  14. package/lib/theme/translationIds.d.ts +6 -0
  15. package/lib/theme/translationIds.js +7 -0
  16. package/package.json +3 -3
  17. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +19 -2
  18. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +14 -2
  19. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +11 -1
  20. package/src/theme/ApiItem/index.tsx +31 -21
  21. package/src/theme/RequestSchema/index.tsx +38 -39
  22. package/src/theme/ResponseSchema/index.tsx +15 -15
  23. package/src/theme/Schema/index.tsx +17 -5
  24. package/src/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
  25. package/src/theme/SchemaExpansion/context.tsx +154 -0
  26. package/src/theme/SchemaExpansion/index.tsx +237 -0
  27. package/src/theme/styles.scss +1 -0
  28. package/src/theme/translationIds.ts +7 -0
  29. package/src/types.d.ts +18 -0
  30. package/tsconfig.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-theme-openapi-docs",
3
3
  "description": "OpenAPI theme for Docusaurus.",
4
- "version": "0.0.0-1240",
4
+ "version": "0.0.0-1247",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -38,7 +38,7 @@
38
38
  "@types/postman-collection": "^3.5.11",
39
39
  "@types/react-modal": "^3.16.3",
40
40
  "concurrently": "^9.2.0",
41
- "docusaurus-plugin-openapi-docs": "0.0.0-1240",
41
+ "docusaurus-plugin-openapi-docs": "0.0.0-1247",
42
42
  "docusaurus-plugin-sass": "^0.2.6",
43
43
  "eslint-plugin-prettier": "^5.5.1"
44
44
  },
@@ -82,5 +82,5 @@
82
82
  "engines": {
83
83
  "node": ">=14"
84
84
  },
85
- "gitHead": "ba15cc438d6103aa536970431145d112310d5678"
85
+ "gitHead": "2e6e04573a1c30d9b0ef899da2e75518ce7c046f"
86
86
  }
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React from "react";
8
+ import React, { useEffect } from "react";
9
9
 
10
10
  import { translate } from "@docusaurus/Translate";
11
11
  import { ErrorMessage } from "@hookform/error-message";
@@ -33,10 +33,26 @@ export default function ParamBooleanFormItem({
33
33
  const {
34
34
  control,
35
35
  formState: { errors },
36
+ setValue,
36
37
  } = useFormContext();
37
38
 
38
39
  const showErrorMessage = errors?.paramBoolean;
39
40
 
41
+ useEffect(() => {
42
+ if (param.value === undefined) return;
43
+ const initial =
44
+ typeof param.value === "boolean" ? String(param.value) : param.value;
45
+ if (initial === "true" || initial === "false") {
46
+ setValue("paramBoolean", initial);
47
+ // Boolean defaults arrive in redux as actual booleans; normalize to the
48
+ // string form the rest of the form uses.
49
+ if (typeof param.value === "boolean") {
50
+ dispatch(setParam({ ...param, value: initial }));
51
+ }
52
+ }
53
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
+ }, []);
55
+
40
56
  return (
41
57
  <>
42
58
  <Controller
@@ -50,11 +66,12 @@ export default function ParamBooleanFormItem({
50
66
  : false,
51
67
  }}
52
68
  name="paramBoolean"
53
- render={({ field: { onChange } }) => (
69
+ render={({ field: { onChange, value } }) => (
54
70
  <FormSelect
55
71
  label={label}
56
72
  type={type}
57
73
  required={required}
74
+ value={value ?? "---"}
58
75
  options={["---", "true", "false"]}
59
76
  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
60
77
  const val = e.target.value;
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React from "react";
8
+ import React, { useEffect } from "react";
9
9
 
10
10
  import { translate } from "@docusaurus/Translate";
11
11
  import { ErrorMessage } from "@hookform/error-message";
@@ -32,6 +32,7 @@ export default function ParamSelectFormItem({
32
32
  const {
33
33
  control,
34
34
  formState: { errors },
35
+ setValue,
35
36
  } = useFormContext();
36
37
 
37
38
  const showErrorMessage = errors?.paramSelect;
@@ -40,6 +41,16 @@ export default function ParamSelectFormItem({
40
41
 
41
42
  const options = getSchemaEnum(param.schema) ?? [];
42
43
 
44
+ useEffect(() => {
45
+ if (
46
+ typeof param.value === "string" &&
47
+ (options as string[]).includes(param.value)
48
+ ) {
49
+ setValue("paramSelect", param.value);
50
+ }
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, []);
53
+
43
54
  return (
44
55
  <>
45
56
  <Controller
@@ -53,11 +64,12 @@ export default function ParamSelectFormItem({
53
64
  : false,
54
65
  }}
55
66
  name="paramSelect"
56
- render={({ field: { onChange } }) => (
67
+ render={({ field: { onChange, value } }) => (
57
68
  <FormSelect
58
69
  label={label}
59
70
  type={type}
60
71
  required={required}
72
+ value={value ?? "---"}
61
73
  options={["---", ...(options as string[])]}
62
74
  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
63
75
  const val = e.target.value;
@@ -5,11 +5,12 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React from "react";
8
+ import React, { useEffect } from "react";
9
9
 
10
10
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
11
11
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
12
12
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
13
+ import { useFormContext } from "react-hook-form";
13
14
 
14
15
  export interface ParamProps {
15
16
  param: Param;
@@ -25,6 +26,15 @@ export default function ParamTextFormItem({
25
26
  required,
26
27
  }: ParamProps) {
27
28
  const dispatch = useTypedDispatch();
29
+ const { setValue } = useFormContext();
30
+
31
+ useEffect(() => {
32
+ if (param.value !== undefined && !Array.isArray(param.value)) {
33
+ setValue(param.name, param.value);
34
+ }
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ }, []);
37
+
28
38
  return (
29
39
  <FormTextInput
30
40
  label={label}
@@ -20,6 +20,7 @@ import DocItemLayout from "@theme/ApiItem/Layout";
20
20
  import CodeBlock from "@theme/CodeBlock";
21
21
  import type { Props } from "@theme/DocItem";
22
22
  import DocItemMetadata from "@theme/DocItem/Metadata";
23
+ import { SchemaExpansionProvider } from "@theme/SchemaExpansion";
23
24
  import SkeletonLoader from "@theme/SkeletonLoader";
24
25
  import clsx from "clsx";
25
26
  import type {
@@ -122,7 +123,12 @@ export default function ApiItem(props: Props): JSX.Element {
122
123
  (param: { in: "path" | "query" | "header" | "cookie" }) => {
123
124
  const paramType = param.in;
124
125
  const paramsArray: ParameterObject[] = params[paramType];
125
- paramsArray?.push(param as ParameterObject);
126
+ const defaultValue = (param as any).schema?.default;
127
+ const initialized =
128
+ defaultValue !== undefined
129
+ ? ({ ...param, value: defaultValue } as unknown as ParameterObject)
130
+ : (param as ParameterObject);
131
+ paramsArray?.push(initialized);
126
132
  }
127
133
  );
128
134
  const auth = createAuth({
@@ -172,18 +178,20 @@ export default function ApiItem(props: Props): JSX.Element {
172
178
  <DocItemMetadata />
173
179
  <DocItemLayout>
174
180
  <Provider store={store2}>
175
- <div className={clsx("row", "theme-api-markdown")}>
176
- <div className="col col--7 openapi-left-panel__container">
177
- <MDXComponent />
178
- </div>
179
- <div className="col col--5 openapi-right-panel__container">
180
- <BrowserOnly fallback={<SkeletonLoader size="lg" />}>
181
- {() => {
182
- return <ApiExplorer item={api} infoPath={infoPath} />;
183
- }}
184
- </BrowserOnly>
181
+ <SchemaExpansionProvider>
182
+ <div className={clsx("row", "theme-api-markdown")}>
183
+ <div className="col col--7 openapi-left-panel__container">
184
+ <MDXComponent />
185
+ </div>
186
+ <div className="col col--5 openapi-right-panel__container">
187
+ <BrowserOnly fallback={<SkeletonLoader size="lg" />}>
188
+ {() => {
189
+ return <ApiExplorer item={api} infoPath={infoPath} />;
190
+ }}
191
+ </BrowserOnly>
192
+ </div>
185
193
  </div>
186
- </div>
194
+ </SchemaExpansionProvider>
187
195
  </Provider>
188
196
  </DocItemLayout>
189
197
  </HtmlClassNameProvider>
@@ -195,16 +203,18 @@ export default function ApiItem(props: Props): JSX.Element {
195
203
  <HtmlClassNameProvider className={docHtmlClassName}>
196
204
  <DocItemMetadata />
197
205
  <DocItemLayout>
198
- <div className={clsx("row", "theme-api-markdown")}>
199
- <div className="col col--7 openapi-left-panel__container schema">
200
- <MDXComponent />
201
- </div>
202
- <div className="col col--5 openapi-right-panel__container">
203
- <CodeBlock language="json" title={`${frontMatter.title}`}>
204
- {JSON.stringify(sample, null, 2)}
205
- </CodeBlock>
206
+ <SchemaExpansionProvider>
207
+ <div className={clsx("row", "theme-api-markdown")}>
208
+ <div className="col col--7 openapi-left-panel__container schema">
209
+ <MDXComponent />
210
+ </div>
211
+ <div className="col col--5 openapi-right-panel__container">
212
+ <CodeBlock language="json" title={`${frontMatter.title}`}>
213
+ {JSON.stringify(sample, null, 2)}
214
+ </CodeBlock>
215
+ </div>
206
216
  </div>
207
- </div>
217
+ </SchemaExpansionProvider>
208
218
  </DocItemLayout>
209
219
  </HtmlClassNameProvider>
210
220
  </DocProvider>
@@ -18,6 +18,7 @@ import {
18
18
  ResponseExamples,
19
19
  } from "@theme/ResponseExamples";
20
20
  import SchemaNode from "@theme/Schema";
21
+ import SchemaExpansionControl from "@theme/SchemaExpansion";
21
22
  import SchemaTabs from "@theme/SchemaTabs";
22
23
  import SkeletonLoader from "@theme/SkeletonLoader";
23
24
  import TabItem from "@theme/TabItem";
@@ -77,24 +78,23 @@ const RequestSchemaComponent: React.FC<Props> = ({ title, body, style }) => {
77
78
  open={true}
78
79
  style={style}
79
80
  summary={
80
- <>
81
- <summary>
82
- <h3 className="openapi-markdown__details-summary-header-body">
83
- {translate({
84
- id: OPENAPI_REQUEST.BODY_TITLE,
85
- message: title,
86
- })}
87
- {body.required === true && (
88
- <span className="openapi-schema__required">
89
- {translate({
90
- id: OPENAPI_SCHEMA_ITEM.REQUIRED,
91
- message: "required",
92
- })}
93
- </span>
94
- )}
95
- </h3>
96
- </summary>
97
- </>
81
+ <summary className="openapi-markdown__details-summary--with-control">
82
+ <h3 className="openapi-markdown__details-summary-header-body">
83
+ {translate({
84
+ id: OPENAPI_REQUEST.BODY_TITLE,
85
+ message: title,
86
+ })}
87
+ {body.required === true && (
88
+ <span className="openapi-schema__required">
89
+ {translate({
90
+ id: OPENAPI_SCHEMA_ITEM.REQUIRED,
91
+ message: "required",
92
+ })}
93
+ </span>
94
+ )}
95
+ </h3>
96
+ <SchemaExpansionControl />
97
+ </summary>
98
98
  }
99
99
  >
100
100
  <div style={{ textAlign: "left", marginLeft: "1rem" }}>
@@ -164,27 +164,26 @@ const RequestSchemaComponent: React.FC<Props> = ({ title, body, style }) => {
164
164
  open={true}
165
165
  style={style}
166
166
  summary={
167
- <>
168
- <summary>
169
- <h3 className="openapi-markdown__details-summary-header-body">
170
- {translate({
171
- id: OPENAPI_REQUEST.BODY_TITLE,
172
- message: title,
173
- })}
174
- {firstBody.type === "array" && (
175
- <span style={{ opacity: "0.6" }}> array</span>
176
- )}
177
- {body.required && (
178
- <strong className="openapi-schema__required">
179
- {translate({
180
- id: OPENAPI_SCHEMA_ITEM.REQUIRED,
181
- message: "required",
182
- })}
183
- </strong>
184
- )}
185
- </h3>
186
- </summary>
187
- </>
167
+ <summary className="openapi-markdown__details-summary--with-control">
168
+ <h3 className="openapi-markdown__details-summary-header-body">
169
+ {translate({
170
+ id: OPENAPI_REQUEST.BODY_TITLE,
171
+ message: title,
172
+ })}
173
+ {firstBody.type === "array" && (
174
+ <span style={{ opacity: "0.6" }}> array</span>
175
+ )}
176
+ {body.required && (
177
+ <strong className="openapi-schema__required">
178
+ {translate({
179
+ id: OPENAPI_SCHEMA_ITEM.REQUIRED,
180
+ message: "required",
181
+ })}
182
+ </strong>
183
+ )}
184
+ </h3>
185
+ <SchemaExpansionControl />
186
+ </summary>
188
187
  }
189
188
  >
190
189
  <div style={{ textAlign: "left", marginLeft: "1rem" }}>
@@ -18,6 +18,7 @@ import {
18
18
  ResponseExamples,
19
19
  } from "@theme/ResponseExamples";
20
20
  import SchemaNode from "@theme/Schema";
21
+ import SchemaExpansionControl from "@theme/SchemaExpansion";
21
22
  import SchemaTabs from "@theme/SchemaTabs";
22
23
  import SkeletonLoader from "@theme/SkeletonLoader";
23
24
  import TabItem from "@theme/TabItem";
@@ -91,21 +92,20 @@ const ResponseSchemaComponent: React.FC<Props> = ({
91
92
  open={true}
92
93
  style={style}
93
94
  summary={
94
- <>
95
- <summary>
96
- <strong className="openapi-markdown__details-summary-response">
97
- {title}
98
- {body.required === true && (
99
- <span className="openapi-schema__required">
100
- {translate({
101
- id: OPENAPI_SCHEMA_ITEM.REQUIRED,
102
- message: "required",
103
- })}
104
- </span>
105
- )}
106
- </strong>
107
- </summary>
108
- </>
95
+ <summary className="openapi-markdown__details-summary--with-control">
96
+ <strong className="openapi-markdown__details-summary-response">
97
+ {title}
98
+ {body.required === true && (
99
+ <span className="openapi-schema__required">
100
+ {translate({
101
+ id: OPENAPI_SCHEMA_ITEM.REQUIRED,
102
+ message: "required",
103
+ })}
104
+ </span>
105
+ )}
106
+ </strong>
107
+ <SchemaExpansionControl />
108
+ </summary>
109
109
  }
110
110
  >
111
111
  <div style={{ textAlign: "left", marginLeft: "1rem" }}>
@@ -14,6 +14,11 @@ import { ClosingArrayBracket, OpeningArrayBracket } from "@theme/ArrayBrackets";
14
14
  import Details from "@theme/Details";
15
15
  import DiscriminatorTabs from "@theme/DiscriminatorTabs";
16
16
  import Markdown from "@theme/Markdown";
17
+ import {
18
+ SchemaDepthProvider,
19
+ useSchemaDepth,
20
+ useSchemaExpansion,
21
+ } from "@theme/SchemaExpansion";
17
22
  import SchemaItem from "@theme/SchemaItem";
18
23
  import SchemaTabs from "@theme/SchemaTabs";
19
24
  import TabItem from "@theme/TabItem";
@@ -676,10 +681,15 @@ const SchemaNodeDetails: React.FC<SchemaEdgeProps> = ({
676
681
  schemaType,
677
682
  schemaPath,
678
683
  }) => {
684
+ const depth = useSchemaDepth();
685
+ const { level } = useSchemaExpansion();
686
+ const defaultOpen = depth < level;
679
687
  return (
680
688
  <SchemaItem collapsible={true}>
681
689
  <Details
690
+ key={`level-${level}`}
682
691
  className="openapi-markdown__details"
692
+ open={defaultOpen}
683
693
  summary={
684
694
  <Summary
685
695
  name={name}
@@ -694,11 +704,13 @@ const SchemaNodeDetails: React.FC<SchemaEdgeProps> = ({
694
704
  {getQualifierMessage(schema) && (
695
705
  <MarkdownWrapper text={getQualifierMessage(schema)} />
696
706
  )}
697
- <SchemaNode
698
- schema={schema}
699
- schemaType={schemaType}
700
- schemaPath={schemaPath}
701
- />
707
+ <SchemaDepthProvider depth={depth + 1}>
708
+ <SchemaNode
709
+ schema={schema}
710
+ schemaType={schemaType}
711
+ schemaPath={schemaPath}
712
+ />
713
+ </SchemaDepthProvider>
702
714
  </div>
703
715
  </Details>
704
716
  </SchemaItem>
@@ -0,0 +1,113 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ .openapi-schema-expansion {
9
+ position: relative;
10
+ display: inline-flex;
11
+ align-items: center;
12
+ margin-left: auto;
13
+ }
14
+
15
+ .openapi-schema-expansion__trigger {
16
+ appearance: none;
17
+ background: transparent;
18
+ border: none;
19
+ border-radius: var(--ifm-global-radius);
20
+ padding: 0;
21
+ width: 22px;
22
+ height: 22px;
23
+ flex: 0 0 22px;
24
+ display: inline-flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ color: var(--ifm-color-emphasis-600);
28
+ line-height: 0;
29
+ opacity: 0.7;
30
+ transition:
31
+ opacity 0.12s ease,
32
+ background-color 0.12s ease,
33
+ color 0.12s ease;
34
+
35
+ &:hover {
36
+ opacity: 1;
37
+ background-color: var(--ifm-color-emphasis-200);
38
+ color: var(--ifm-color-emphasis-900);
39
+ }
40
+
41
+ &:focus-visible {
42
+ outline: 2px solid var(--ifm-color-primary);
43
+ outline-offset: 2px;
44
+ opacity: 1;
45
+ }
46
+
47
+ &[aria-expanded="true"] {
48
+ opacity: 1;
49
+ background-color: var(--ifm-color-emphasis-200);
50
+ color: var(--ifm-color-emphasis-900);
51
+ }
52
+ }
53
+
54
+ .openapi-schema-expansion__popover {
55
+ position: fixed;
56
+ z-index: 1000;
57
+ display: inline-flex;
58
+ align-items: center;
59
+ gap: 2px;
60
+ padding: 3px;
61
+ background-color: var(--ifm-background-surface-color);
62
+ border: 1px solid var(--ifm-color-emphasis-300);
63
+ border-radius: var(--ifm-global-radius);
64
+ box-shadow: var(--ifm-global-shadow-md);
65
+ white-space: nowrap;
66
+ }
67
+
68
+ .openapi-schema-expansion__option {
69
+ appearance: none;
70
+ background: transparent;
71
+ border: none;
72
+ border-radius: calc(var(--ifm-global-radius) - 2px);
73
+ padding: 2px 8px;
74
+ font-size: 0.8rem;
75
+ line-height: 1.4;
76
+ color: var(--ifm-color-emphasis-800);
77
+ transition:
78
+ background-color 0.12s ease,
79
+ color 0.12s ease;
80
+
81
+ &:hover {
82
+ background-color: var(--ifm-color-emphasis-200);
83
+ }
84
+
85
+ &:focus-visible {
86
+ outline: 2px solid var(--ifm-color-primary);
87
+ outline-offset: 1px;
88
+ }
89
+ }
90
+
91
+ .openapi-schema-expansion__option--active {
92
+ background-color: var(--ifm-color-primary);
93
+ color: var(--ifm-color-white);
94
+
95
+ &:hover {
96
+ background-color: var(--ifm-color-primary-dark);
97
+ }
98
+ }
99
+
100
+ .openapi-markdown__details-summary--with-control {
101
+ display: flex !important;
102
+ align-items: center;
103
+ gap: 0.5rem;
104
+
105
+ > h3,
106
+ > strong {
107
+ margin-bottom: 0;
108
+ display: inline-flex;
109
+ align-items: center;
110
+ flex-wrap: wrap;
111
+ gap: 0.4rem;
112
+ }
113
+ }