docusaurus-theme-openapi-docs 4.7.1 → 5.0.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.
- package/lib/index.js +2 -0
- package/lib/markdown/schema.js +63 -9
- package/lib/theme/ApiExplorer/Accept/index.js +2 -1
- package/lib/theme/ApiExplorer/Authorization/index.js +12 -18
- package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.js +0 -4
- package/lib/theme/ApiExplorer/Body/FormBodyItem/index.d.ts +5 -1
- package/lib/theme/ApiExplorer/Body/FormBodyItem/index.js +190 -37
- package/lib/theme/ApiExplorer/Body/index.js +84 -13
- package/lib/theme/ApiExplorer/Body/slice.d.ts +136 -544
- package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
- package/lib/theme/ApiExplorer/CodeSnippets/index.js +4 -0
- package/lib/theme/ApiExplorer/CodeTabs/index.js +15 -16
- package/lib/theme/ApiExplorer/ContentType/index.js +7 -2
- package/lib/theme/ApiExplorer/EncodingSelection/slice.d.ts +17 -0
- package/lib/theme/ApiExplorer/EncodingSelection/slice.js +29 -0
- package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.d.ts +12 -0
- package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.js +39 -0
- package/lib/theme/ApiExplorer/FormItem/_FormItem.scss +0 -5
- package/lib/theme/ApiExplorer/FormItem/index.d.ts +1 -4
- package/lib/theme/ApiExplorer/FormItem/index.js +2 -26
- package/lib/theme/ApiExplorer/FormLabel/_FormLabel.scss +4 -0
- package/lib/theme/ApiExplorer/FormLabel/index.d.ts +9 -0
- package/lib/theme/ApiExplorer/FormLabel/index.js +50 -0
- package/lib/theme/ApiExplorer/FormMultiSelect/index.d.ts +4 -1
- package/lib/theme/ApiExplorer/FormMultiSelect/index.js +97 -19
- package/lib/theme/ApiExplorer/FormSelect/index.d.ts +6 -1
- package/lib/theme/ApiExplorer/FormSelect/index.js +96 -15
- package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +4 -1
- package/lib/theme/ApiExplorer/FormTextInput/index.js +71 -1
- package/lib/theme/ApiExplorer/MethodEndpoint/index.js +28 -0
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +4 -1
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +11 -3
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +4 -1
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +4 -1
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +4 -1
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +6 -2
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +4 -1
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +6 -2
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +4 -1
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +8 -3
- package/lib/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +0 -9
- package/lib/theme/ApiExplorer/ParamOptions/index.d.ts +10 -0
- package/lib/theme/ApiExplorer/ParamOptions/index.js +55 -5
- package/lib/theme/ApiExplorer/Request/_Request.scss +11 -0
- package/lib/theme/ApiExplorer/Request/index.js +19 -5
- package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +3 -1
- package/lib/theme/ApiExplorer/Request/makeRequest.js +19 -3
- package/lib/theme/ApiExplorer/Response/_Response.scss +11 -0
- package/lib/theme/ApiExplorer/Response/index.js +98 -12
- package/lib/theme/ApiExplorer/Server/index.d.ts +4 -1
- package/lib/theme/ApiExplorer/Server/index.js +6 -3
- package/lib/theme/ApiExplorer/buildPostmanRequest.d.ts +4 -1
- package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -5
- package/lib/theme/ApiExplorer/index.js +1 -0
- package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +2 -0
- package/lib/theme/ApiItem/hooks.d.ts +1 -0
- package/lib/theme/ApiItem/index.js +2 -1
- package/lib/theme/ApiItem/store.d.ts +6 -0
- package/lib/theme/ApiItem/store.js +11 -7
- package/lib/theme/ApiTabs/index.js +10 -11
- package/lib/theme/DiscriminatorTabs/index.js +10 -11
- package/lib/theme/MimeTabs/index.js +10 -11
- package/lib/theme/OperationTabs/index.js +10 -11
- package/lib/theme/ParamsItem/index.js +27 -0
- package/lib/theme/RequestSchema/index.js +172 -109
- package/lib/theme/ResponseHeaders/index.js +0 -1
- package/lib/theme/Schema/index.d.ts +1 -1
- package/lib/theme/Schema/index.js +91 -23
- package/lib/theme/SchemaItem/index.js +6 -1
- package/lib/theme/SchemaTabs/index.d.ts +1 -1
- package/lib/theme/SchemaTabs/index.js +31 -12
- package/lib/theme/styles.scss +1 -0
- package/lib/theme/translationIds.d.ts +3 -0
- package/lib/theme/translationIds.js +3 -0
- package/package.json +9 -8
- package/src/index.ts +2 -0
- package/src/markdown/schema.ts +69 -13
- package/src/theme/ApiExplorer/Accept/index.tsx +2 -1
- package/src/theme/ApiExplorer/Authorization/index.tsx +27 -33
- package/src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx +0 -5
- package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +115 -37
- package/src/theme/ApiExplorer/Body/index.tsx +85 -17
- package/src/theme/ApiExplorer/CodeSnippets/index.tsx +9 -1
- package/src/theme/ApiExplorer/CodeTabs/index.tsx +19 -19
- package/src/theme/ApiExplorer/ContentType/index.tsx +7 -4
- package/src/theme/ApiExplorer/EncodingSelection/slice.ts +31 -0
- package/src/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.ts +43 -0
- package/src/theme/ApiExplorer/FormItem/_FormItem.scss +0 -5
- package/src/theme/ApiExplorer/FormItem/index.tsx +2 -16
- package/src/theme/ApiExplorer/FormLabel/_FormLabel.scss +4 -0
- package/src/theme/ApiExplorer/FormLabel/index.tsx +43 -0
- package/src/theme/ApiExplorer/FormMultiSelect/index.tsx +40 -20
- package/src/theme/ApiExplorer/FormSelect/index.tsx +41 -15
- package/src/theme/ApiExplorer/FormTextInput/index.tsx +15 -1
- package/src/theme/ApiExplorer/MethodEndpoint/index.tsx +21 -0
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +13 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +12 -1
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +14 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +14 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +16 -3
- package/src/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +0 -9
- package/src/theme/ApiExplorer/ParamOptions/index.tsx +97 -11
- package/src/theme/ApiExplorer/Request/_Request.scss +11 -0
- package/src/theme/ApiExplorer/Request/index.tsx +20 -8
- package/src/theme/ApiExplorer/Request/makeRequest.ts +19 -3
- package/src/theme/ApiExplorer/Response/_Response.scss +11 -0
- package/src/theme/ApiExplorer/Response/index.tsx +35 -14
- package/src/theme/ApiExplorer/Server/index.tsx +10 -3
- package/src/theme/ApiExplorer/buildPostmanRequest.ts +52 -5
- package/src/theme/ApiExplorer/index.tsx +1 -0
- package/src/theme/ApiItem/index.tsx +2 -1
- package/src/theme/ApiItem/store.ts +2 -0
- package/src/theme/ApiTabs/index.tsx +14 -19
- package/src/theme/DiscriminatorTabs/index.tsx +14 -19
- package/src/theme/MimeTabs/index.tsx +15 -19
- package/src/theme/OperationTabs/index.tsx +14 -19
- package/src/theme/ParamsItem/index.tsx +25 -0
- package/src/theme/RequestSchema/index.tsx +141 -83
- package/src/theme/ResponseHeaders/index.tsx +1 -2
- package/src/theme/Schema/index.tsx +112 -27
- package/src/theme/SchemaItem/index.tsx +6 -1
- package/src/theme/SchemaTabs/index.tsx +42 -21
- package/src/theme/styles.scss +1 -0
- package/src/theme/translationIds.ts +3 -0
- package/src/theme-classic.d.ts +25 -1
- package/src/types.d.ts +7 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -93,6 +93,8 @@ function Body({
|
|
|
93
93
|
const rawSchema = requestBodyMetadata?.content?.[contentType]?.schema;
|
|
94
94
|
const example = requestBodyMetadata?.content?.[contentType]?.example;
|
|
95
95
|
const examples = requestBodyMetadata?.content?.[contentType]?.examples;
|
|
96
|
+
const encoding: Record<string, { contentType?: string }> | undefined =
|
|
97
|
+
requestBodyMetadata?.content?.[contentType]?.encoding;
|
|
96
98
|
|
|
97
99
|
// Resolve the schema based on user's anyOf/oneOf tab selections
|
|
98
100
|
const schema = useMemo(() => {
|
|
@@ -316,23 +318,89 @@ function Body({
|
|
|
316
318
|
) {
|
|
317
319
|
return (
|
|
318
320
|
<FormItem className="openapi-explorer__form-item-body-container">
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
321
|
+
<SchemaTabs className="openapi-tabs__schema" lazy>
|
|
322
|
+
{/* @ts-ignore */}
|
|
323
|
+
<TabItem
|
|
324
|
+
label={translate({
|
|
325
|
+
id: OPENAPI_BODY.EXAMPLE_FROM_SCHEMA,
|
|
326
|
+
message: "Example (from schema)",
|
|
327
|
+
})}
|
|
328
|
+
value="Example (from schema)"
|
|
329
|
+
default
|
|
330
|
+
>
|
|
331
|
+
{Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
|
|
332
|
+
return (
|
|
333
|
+
<FormItem key={key}>
|
|
334
|
+
<FormBodyItem
|
|
335
|
+
schemaObject={val}
|
|
336
|
+
id={key}
|
|
337
|
+
schema={schema}
|
|
338
|
+
exampleValue={val.example}
|
|
339
|
+
label={key}
|
|
340
|
+
required={
|
|
341
|
+
Array.isArray(schema.required) &&
|
|
342
|
+
schema.required.includes(key)
|
|
343
|
+
}
|
|
344
|
+
fieldEncoding={encoding?.[key]?.contentType}
|
|
345
|
+
></FormBodyItem>
|
|
346
|
+
</FormItem>
|
|
347
|
+
);
|
|
348
|
+
})}
|
|
349
|
+
</TabItem>
|
|
350
|
+
{example && (
|
|
351
|
+
// @ts-ignore
|
|
352
|
+
<TabItem label="Example" value="example">
|
|
353
|
+
{Object.entries(schema.properties ?? {}).map(
|
|
354
|
+
([schemaKey, schemaVal]: any) => {
|
|
355
|
+
return (
|
|
356
|
+
<FormItem key={schemaKey}>
|
|
357
|
+
<FormBodyItem
|
|
358
|
+
schemaObject={schemaVal}
|
|
359
|
+
id={schemaKey}
|
|
360
|
+
schema={schema}
|
|
361
|
+
exampleValue={example[schemaKey]}
|
|
362
|
+
label={schemaKey}
|
|
363
|
+
required={
|
|
364
|
+
Array.isArray(schema.required) &&
|
|
365
|
+
schema.required.includes(schemaKey)
|
|
366
|
+
}
|
|
367
|
+
fieldEncoding={encoding?.[schemaKey]?.contentType}
|
|
368
|
+
></FormBodyItem>
|
|
369
|
+
</FormItem>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
)}
|
|
373
|
+
</TabItem>
|
|
374
|
+
)}
|
|
375
|
+
{examples &&
|
|
376
|
+
Object.entries(examples).map(([key, value]) => {
|
|
377
|
+
return (
|
|
378
|
+
// @ts-ignore
|
|
379
|
+
<TabItem label={key} value={key} key={key}>
|
|
380
|
+
{Object.entries(schema.properties ?? {}).map(
|
|
381
|
+
([schemaKey, schemaVal]: any) => {
|
|
382
|
+
return (
|
|
383
|
+
<FormItem key={schemaKey}>
|
|
384
|
+
<FormBodyItem
|
|
385
|
+
schemaObject={schemaVal}
|
|
386
|
+
id={schemaKey}
|
|
387
|
+
schema={schema}
|
|
388
|
+
exampleValue={value.value?.[schemaKey]}
|
|
389
|
+
label={schemaKey}
|
|
390
|
+
required={
|
|
391
|
+
Array.isArray(schema.required) &&
|
|
392
|
+
schema.required.includes(schemaKey)
|
|
393
|
+
}
|
|
394
|
+
fieldEncoding={encoding?.[schemaKey]?.contentType}
|
|
395
|
+
></FormBodyItem>
|
|
396
|
+
</FormItem>
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
)}
|
|
400
|
+
</TabItem>
|
|
401
|
+
);
|
|
402
|
+
})}
|
|
403
|
+
</SchemaTabs>
|
|
336
404
|
</FormItem>
|
|
337
405
|
);
|
|
338
406
|
}
|
|
@@ -11,6 +11,7 @@ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
|
11
11
|
import ApiCodeBlock from "@theme/ApiExplorer/ApiCodeBlock";
|
|
12
12
|
import buildPostmanRequest from "@theme/ApiExplorer/buildPostmanRequest";
|
|
13
13
|
import CodeTabs from "@theme/ApiExplorer/CodeTabs";
|
|
14
|
+
import { useResolvedEncoding } from "@theme/ApiExplorer/EncodingSelection/useResolvedEncoding";
|
|
14
15
|
import { useTypedSelector } from "@theme/ApiItem/hooks";
|
|
15
16
|
import cloneDeep from "lodash/cloneDeep";
|
|
16
17
|
import codegen from "postman-code-generators";
|
|
@@ -30,6 +31,7 @@ export interface Props {
|
|
|
30
31
|
postman: sdk.Request;
|
|
31
32
|
codeSamples: CodeSample[];
|
|
32
33
|
maskCredentials?: boolean;
|
|
34
|
+
requestBody?: import("docusaurus-plugin-openapi-docs/src/openapi/types").RequestBodyObject;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
function CodeTab({ children, hidden, className }: any): React.JSX.Element {
|
|
@@ -44,6 +46,7 @@ function CodeSnippets({
|
|
|
44
46
|
postman,
|
|
45
47
|
codeSamples,
|
|
46
48
|
maskCredentials: propMaskCredentials,
|
|
49
|
+
requestBody,
|
|
47
50
|
}: Props) {
|
|
48
51
|
const { siteConfig } = useDocusaurusContext();
|
|
49
52
|
|
|
@@ -76,7 +79,9 @@ function CodeSnippets({
|
|
|
76
79
|
const authOptions =
|
|
77
80
|
clonedAuth?.options?.[key] ??
|
|
78
81
|
clonedAuth?.options?.[comboAuthId];
|
|
79
|
-
placeholder = authOptions?.find(
|
|
82
|
+
placeholder = authOptions?.find(
|
|
83
|
+
(opt: any) => opt.key === key
|
|
84
|
+
)?.name;
|
|
80
85
|
obj[key] = cleanCredentials(obj[key]);
|
|
81
86
|
} else {
|
|
82
87
|
obj[key] = `<${placeholder ?? key}>`;
|
|
@@ -93,6 +98,8 @@ function CodeSnippets({
|
|
|
93
98
|
})()
|
|
94
99
|
: auth;
|
|
95
100
|
|
|
101
|
+
const encoding = useResolvedEncoding(requestBody);
|
|
102
|
+
|
|
96
103
|
// Create a Postman request object using cleanedAuth or original auth
|
|
97
104
|
const cleanedPostmanRequest = buildPostmanRequest(postman, {
|
|
98
105
|
queryParams,
|
|
@@ -104,6 +111,7 @@ function CodeSnippets({
|
|
|
104
111
|
body,
|
|
105
112
|
server,
|
|
106
113
|
auth: cleanedAuth,
|
|
114
|
+
encoding,
|
|
107
115
|
});
|
|
108
116
|
|
|
109
117
|
// User-defined languages array
|
|
@@ -9,11 +9,12 @@ import React, { cloneElement, ReactElement, useEffect, useRef } from "react";
|
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
sanitizeTabsChildren,
|
|
12
|
+
type TabItemProps,
|
|
12
13
|
type TabProps,
|
|
14
|
+
TabsProvider,
|
|
13
15
|
useScrollPositionBlocker,
|
|
14
|
-
|
|
16
|
+
useTabsContextValue,
|
|
15
17
|
} from "@docusaurus/theme-common/internal";
|
|
16
|
-
import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
|
|
17
18
|
import useIsBrowser from "@docusaurus/useIsBrowser";
|
|
18
19
|
import clsx from "clsx";
|
|
19
20
|
|
|
@@ -43,7 +44,7 @@ function TabList({
|
|
|
43
44
|
selectedValue,
|
|
44
45
|
selectValue,
|
|
45
46
|
tabValues,
|
|
46
|
-
}: CodeTabsProps & ReturnType<typeof
|
|
47
|
+
}: CodeTabsProps & ReturnType<typeof useTabsContextValue>) {
|
|
47
48
|
const tabRefs = useRef<(HTMLLIElement | null)[]>([]);
|
|
48
49
|
const tabsScrollContainerRef = useRef<any>(null);
|
|
49
50
|
const { blockElementScrollPositionUntilNextRender } =
|
|
@@ -192,7 +193,8 @@ function TabContent({
|
|
|
192
193
|
lazy,
|
|
193
194
|
children,
|
|
194
195
|
selectedValue,
|
|
195
|
-
}: CodeTabsProps &
|
|
196
|
+
}: CodeTabsProps &
|
|
197
|
+
ReturnType<typeof useTabsContextValue>): React.JSX.Element | null {
|
|
196
198
|
const childTabs = (Array.isArray(children) ? children : [children]).filter(
|
|
197
199
|
Boolean
|
|
198
200
|
) as ReactElement<TabItemProps>[];
|
|
@@ -207,28 +209,26 @@ function TabContent({
|
|
|
207
209
|
return cloneElement(selectedTabItem, { className: "margin-top--md" });
|
|
208
210
|
}
|
|
209
211
|
return (
|
|
210
|
-
<div className="margin-top--md openapi-tabs__code-content">
|
|
211
|
-
{childTabs.map((tabItem, i) =>
|
|
212
|
-
cloneElement(tabItem, {
|
|
213
|
-
key: i,
|
|
214
|
-
hidden: tabItem.props.value !== selectedValue,
|
|
215
|
-
})
|
|
216
|
-
)}
|
|
217
|
-
</div>
|
|
212
|
+
<div className="margin-top--md openapi-tabs__code-content">{childTabs}</div>
|
|
218
213
|
);
|
|
219
214
|
}
|
|
220
215
|
|
|
221
216
|
function TabsComponent(props: CodeTabsProps & Props): React.JSX.Element {
|
|
222
|
-
const tabs =
|
|
217
|
+
const tabs = useTabsContextValue(props);
|
|
223
218
|
const { className } = props;
|
|
224
219
|
|
|
225
220
|
return (
|
|
226
|
-
<
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
221
|
+
<TabsProvider value={tabs}>
|
|
222
|
+
<div
|
|
223
|
+
className={clsx(
|
|
224
|
+
"tabs-container openapi-tabs__code-container",
|
|
225
|
+
className
|
|
226
|
+
)}
|
|
227
|
+
>
|
|
228
|
+
<TabList {...props} {...tabs} />
|
|
229
|
+
<TabContent {...props} {...tabs} />
|
|
230
|
+
</div>
|
|
231
|
+
</TabsProvider>
|
|
232
232
|
);
|
|
233
233
|
}
|
|
234
234
|
|
|
@@ -12,6 +12,7 @@ import FormSelect from "@theme/ApiExplorer/FormSelect";
|
|
|
12
12
|
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
|
|
13
13
|
|
|
14
14
|
import { setContentType } from "./slice";
|
|
15
|
+
import { clearEncodingSelection } from "@theme/ApiExplorer/EncodingSelection/slice";
|
|
15
16
|
|
|
16
17
|
function ContentType() {
|
|
17
18
|
const value = useTypedSelector((state: any) => state.contentType.value);
|
|
@@ -23,13 +24,15 @@ function ContentType() {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
return (
|
|
26
|
-
<FormItem
|
|
27
|
+
<FormItem>
|
|
27
28
|
<FormSelect
|
|
29
|
+
label="Content-Type"
|
|
28
30
|
value={value}
|
|
29
31
|
options={options}
|
|
30
|
-
onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
|
|
31
|
-
dispatch(setContentType(e.target.value))
|
|
32
|
-
|
|
32
|
+
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
33
|
+
dispatch(setContentType(e.target.value));
|
|
34
|
+
dispatch(clearEncodingSelection());
|
|
35
|
+
}}
|
|
33
36
|
/>
|
|
34
37
|
</FormItem>
|
|
35
38
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|
9
|
+
|
|
10
|
+
// Maps form field name → user-selected content type
|
|
11
|
+
export type State = Record<string, string>;
|
|
12
|
+
|
|
13
|
+
const initialState: State = {};
|
|
14
|
+
|
|
15
|
+
export const slice = createSlice({
|
|
16
|
+
name: "encodingSelection",
|
|
17
|
+
initialState,
|
|
18
|
+
reducers: {
|
|
19
|
+
setFieldEncoding: (
|
|
20
|
+
state,
|
|
21
|
+
action: PayloadAction<{ field: string; contentType: string }>
|
|
22
|
+
) => {
|
|
23
|
+
state[action.payload.field] = action.payload.contentType;
|
|
24
|
+
},
|
|
25
|
+
clearEncodingSelection: () => initialState,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const { setFieldEncoding, clearEncodingSelection } = slice.actions;
|
|
30
|
+
|
|
31
|
+
export default slice.reducer;
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
import { useTypedSelector } from "@theme/ApiItem/hooks";
|
|
9
|
+
import type { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Merges the spec-declared `encoding` for the active content type with any
|
|
13
|
+
* per-field content-type selections the user has made in the UI. User picks
|
|
14
|
+
* take precedence over the spec default.
|
|
15
|
+
*
|
|
16
|
+
* Returns `undefined` when no encoding is declared for the current content
|
|
17
|
+
* type so callers can skip the encoding path entirely.
|
|
18
|
+
*/
|
|
19
|
+
export function useResolvedEncoding(
|
|
20
|
+
requestBody: RequestBodyObject | undefined
|
|
21
|
+
): Record<string, { contentType?: string }> | undefined {
|
|
22
|
+
const contentType = useTypedSelector((state: any) => state.contentType.value);
|
|
23
|
+
const encodingSelection = useTypedSelector(
|
|
24
|
+
(state: any) => state.encodingSelection
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const specEncoding: Record<string, { contentType?: string }> =
|
|
28
|
+
requestBody?.content?.[contentType]?.encoding ?? {};
|
|
29
|
+
|
|
30
|
+
if (!Object.keys(specEncoding).length) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return Object.fromEntries(
|
|
35
|
+
Object.entries(specEncoding).map(([field, enc]) => [
|
|
36
|
+
field,
|
|
37
|
+
{
|
|
38
|
+
...enc,
|
|
39
|
+
contentType: encodingSelection[field] ?? enc.contentType,
|
|
40
|
+
},
|
|
41
|
+
])
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -7,31 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
|
|
10
|
-
import { translate } from "@docusaurus/Translate";
|
|
11
|
-
import { OPENAPI_SCHEMA_ITEM } from "@theme/translationIds";
|
|
12
10
|
import clsx from "clsx";
|
|
13
11
|
|
|
14
12
|
export interface Props {
|
|
15
|
-
label?: string;
|
|
16
|
-
type?: string;
|
|
17
|
-
required?: boolean | undefined;
|
|
18
13
|
children?: React.ReactNode;
|
|
19
14
|
className?: string;
|
|
20
15
|
}
|
|
21
16
|
|
|
22
|
-
function FormItem({
|
|
17
|
+
function FormItem({ children, className }: Props) {
|
|
23
18
|
return (
|
|
24
19
|
<div className={clsx("openapi-explorer__form-item", className)}>
|
|
25
|
-
{
|
|
26
|
-
<label className="openapi-explorer__form-item-label">{label}</label>
|
|
27
|
-
)}
|
|
28
|
-
{type && <span style={{ opacity: 0.6 }}> — {type}</span>}
|
|
29
|
-
{required && (
|
|
30
|
-
<span className="openapi-schema__required">
|
|
31
|
-
{translate({ id: OPENAPI_SCHEMA_ITEM.REQUIRED, message: "required" })}
|
|
32
|
-
</span>
|
|
33
|
-
)}
|
|
34
|
-
<div>{children}</div>
|
|
20
|
+
{children}
|
|
35
21
|
</div>
|
|
36
22
|
);
|
|
37
23
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
import React from "react";
|
|
9
|
+
|
|
10
|
+
import { translate } from "@docusaurus/Translate";
|
|
11
|
+
import { OPENAPI_SCHEMA_ITEM } from "@theme/translationIds";
|
|
12
|
+
|
|
13
|
+
export interface Props {
|
|
14
|
+
htmlFor?: string;
|
|
15
|
+
label: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function FormLabel({ htmlFor, label, type, required }: Props) {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
{htmlFor ? (
|
|
24
|
+
<label className="openapi-explorer__form-item-label" htmlFor={htmlFor}>
|
|
25
|
+
{label}
|
|
26
|
+
</label>
|
|
27
|
+
) : (
|
|
28
|
+
<span className="openapi-explorer__form-item-label">{label}</span>
|
|
29
|
+
)}
|
|
30
|
+
{type && <span style={{ opacity: 0.6 }}> — {type}</span>}
|
|
31
|
+
{required && (
|
|
32
|
+
<span className="openapi-schema__required">
|
|
33
|
+
{translate({
|
|
34
|
+
id: OPENAPI_SCHEMA_ITEM.REQUIRED,
|
|
35
|
+
message: "required",
|
|
36
|
+
})}
|
|
37
|
+
</span>
|
|
38
|
+
)}
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default FormLabel;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
|
-
import React from "react";
|
|
8
|
+
import React, { useId } from "react";
|
|
9
9
|
|
|
10
|
+
import FormLabel from "@theme/ApiExplorer/FormLabel";
|
|
10
11
|
import clsx from "clsx";
|
|
11
12
|
|
|
12
13
|
export interface Props {
|
|
@@ -14,9 +15,22 @@ export interface Props {
|
|
|
14
15
|
options: string[];
|
|
15
16
|
onChange?: React.ChangeEventHandler<HTMLSelectElement>;
|
|
16
17
|
showErrors?: boolean;
|
|
18
|
+
label?: string;
|
|
19
|
+
type?: string;
|
|
20
|
+
required?: boolean;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
function FormMultiSelect({
|
|
23
|
+
function FormMultiSelect({
|
|
24
|
+
value,
|
|
25
|
+
options,
|
|
26
|
+
onChange,
|
|
27
|
+
showErrors,
|
|
28
|
+
label,
|
|
29
|
+
type,
|
|
30
|
+
required,
|
|
31
|
+
}: Props) {
|
|
32
|
+
const id = useId();
|
|
33
|
+
|
|
20
34
|
if (options.length === 0) {
|
|
21
35
|
return null;
|
|
22
36
|
}
|
|
@@ -33,24 +47,30 @@ function FormMultiSelect({ value, options, onChange, showErrors }: Props) {
|
|
|
33
47
|
}
|
|
34
48
|
|
|
35
49
|
return (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
<>
|
|
51
|
+
{label && (
|
|
52
|
+
<FormLabel htmlFor={id} label={label} type={type} required={required} />
|
|
53
|
+
)}
|
|
54
|
+
<select
|
|
55
|
+
id={label ? id : undefined}
|
|
56
|
+
style={{ height: height }}
|
|
57
|
+
className={clsx("openapi-explorer__multi-select-input", {
|
|
58
|
+
error: showErrors,
|
|
59
|
+
})}
|
|
60
|
+
value={value}
|
|
61
|
+
onChange={onChange}
|
|
62
|
+
size={Math.min(6, options.length + 1)}
|
|
63
|
+
multiple
|
|
64
|
+
>
|
|
65
|
+
{options.map((option) => {
|
|
66
|
+
return (
|
|
67
|
+
<option key={option} value={option}>
|
|
68
|
+
{option}
|
|
69
|
+
</option>
|
|
70
|
+
);
|
|
71
|
+
})}
|
|
72
|
+
</select>
|
|
73
|
+
</>
|
|
54
74
|
);
|
|
55
75
|
}
|
|
56
76
|
|
|
@@ -5,33 +5,59 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
|
-
import React from "react";
|
|
8
|
+
import React, { useId } from "react";
|
|
9
|
+
|
|
10
|
+
import FormLabel from "@theme/ApiExplorer/FormLabel";
|
|
9
11
|
|
|
10
12
|
export interface Props {
|
|
11
13
|
value?: string;
|
|
12
14
|
options?: string[];
|
|
13
15
|
onChange?: React.ChangeEventHandler<HTMLSelectElement>;
|
|
16
|
+
label?: string;
|
|
17
|
+
type?: string;
|
|
18
|
+
required?: boolean;
|
|
19
|
+
ariaLabelledBy?: string;
|
|
20
|
+
ariaLabel?: string;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
function FormSelect({
|
|
23
|
+
function FormSelect({
|
|
24
|
+
value,
|
|
25
|
+
options,
|
|
26
|
+
onChange,
|
|
27
|
+
label,
|
|
28
|
+
type,
|
|
29
|
+
required,
|
|
30
|
+
ariaLabelledBy,
|
|
31
|
+
ariaLabel,
|
|
32
|
+
}: Props) {
|
|
33
|
+
const id = useId();
|
|
34
|
+
|
|
17
35
|
if (!Array.isArray(options) || options.length === 0) {
|
|
18
36
|
return null;
|
|
19
37
|
}
|
|
20
38
|
|
|
21
39
|
return (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
<>
|
|
41
|
+
{label && (
|
|
42
|
+
<FormLabel htmlFor={id} label={label} type={type} required={required} />
|
|
43
|
+
)}
|
|
44
|
+
<select
|
|
45
|
+
id={label ? id : undefined}
|
|
46
|
+
className="openapi-explorer__select-input"
|
|
47
|
+
value={value}
|
|
48
|
+
onChange={onChange}
|
|
49
|
+
aria-labelledby={!label ? ariaLabelledBy : undefined}
|
|
50
|
+
aria-label={!label && !ariaLabelledBy ? ariaLabel : undefined}
|
|
51
|
+
>
|
|
52
|
+
{options.map((option) => {
|
|
53
|
+
return (
|
|
54
|
+
<option key={option} value={option}>
|
|
55
|
+
{option}
|
|
56
|
+
</option>
|
|
57
|
+
);
|
|
58
|
+
})}
|
|
59
|
+
</select>
|
|
60
|
+
</>
|
|
35
61
|
);
|
|
36
62
|
}
|
|
37
63
|
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
8
|
// @ts-nocheck
|
|
9
|
-
import React from "react";
|
|
9
|
+
import React, { useId } from "react";
|
|
10
10
|
|
|
11
11
|
import { translate } from "@docusaurus/Translate";
|
|
12
12
|
import { ErrorMessage } from "@hookform/error-message";
|
|
13
|
+
import FormLabel from "@theme/ApiExplorer/FormLabel";
|
|
13
14
|
import { OPENAPI_FORM } from "@theme/translationIds";
|
|
14
15
|
import clsx from "clsx";
|
|
15
16
|
import { useFormContext } from "react-hook-form";
|
|
@@ -21,6 +22,9 @@ export interface Props {
|
|
|
21
22
|
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
22
23
|
paramName?: string;
|
|
23
24
|
isRequired?: boolean;
|
|
25
|
+
label?: string;
|
|
26
|
+
type?: string;
|
|
27
|
+
required?: boolean;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
function FormTextInput({
|
|
@@ -30,7 +34,12 @@ function FormTextInput({
|
|
|
30
34
|
password,
|
|
31
35
|
onChange,
|
|
32
36
|
paramName,
|
|
37
|
+
label,
|
|
38
|
+
type,
|
|
39
|
+
required,
|
|
33
40
|
}: Props) {
|
|
41
|
+
const id = useId();
|
|
42
|
+
|
|
34
43
|
placeholder = placeholder?.split("\n")[0];
|
|
35
44
|
|
|
36
45
|
const {
|
|
@@ -42,6 +51,9 @@ function FormTextInput({
|
|
|
42
51
|
|
|
43
52
|
return (
|
|
44
53
|
<>
|
|
54
|
+
{label && (
|
|
55
|
+
<FormLabel htmlFor={id} label={label} type={type} required={required} />
|
|
56
|
+
)}
|
|
45
57
|
{paramName ? (
|
|
46
58
|
<input
|
|
47
59
|
{...register(paramName, {
|
|
@@ -52,6 +64,7 @@ function FormTextInput({
|
|
|
52
64
|
})
|
|
53
65
|
: false,
|
|
54
66
|
})}
|
|
67
|
+
id={label ? id : undefined}
|
|
55
68
|
className={clsx("openapi-explorer__form-item-input", {
|
|
56
69
|
error: showErrorMessage,
|
|
57
70
|
})}
|
|
@@ -64,6 +77,7 @@ function FormTextInput({
|
|
|
64
77
|
/>
|
|
65
78
|
) : (
|
|
66
79
|
<input
|
|
80
|
+
id={label ? id : undefined}
|
|
67
81
|
className="openapi-explorer__form-item-input"
|
|
68
82
|
type={password ? "password" : "text"}
|
|
69
83
|
placeholder={placeholder}
|