docusaurus-theme-openapi-docs 4.7.1 → 5.0.1

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 (129) hide show
  1. package/lib/index.js +2 -0
  2. package/lib/markdown/schema.js +63 -9
  3. package/lib/theme/ApiExplorer/Accept/index.js +2 -1
  4. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.js +16 -5
  5. package/lib/theme/ApiExplorer/Authorization/index.js +12 -18
  6. package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.js +0 -4
  7. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.d.ts +5 -1
  8. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.js +190 -37
  9. package/lib/theme/ApiExplorer/Body/index.js +84 -13
  10. package/lib/theme/ApiExplorer/Body/slice.d.ts +136 -544
  11. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
  12. package/lib/theme/ApiExplorer/CodeSnippets/index.js +4 -0
  13. package/lib/theme/ApiExplorer/CodeTabs/index.js +15 -16
  14. package/lib/theme/ApiExplorer/ContentType/index.js +7 -2
  15. package/lib/theme/ApiExplorer/EncodingSelection/slice.d.ts +17 -0
  16. package/lib/theme/ApiExplorer/EncodingSelection/slice.js +29 -0
  17. package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.d.ts +12 -0
  18. package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.js +39 -0
  19. package/lib/theme/ApiExplorer/FormItem/_FormItem.scss +0 -5
  20. package/lib/theme/ApiExplorer/FormItem/index.d.ts +1 -4
  21. package/lib/theme/ApiExplorer/FormItem/index.js +2 -26
  22. package/lib/theme/ApiExplorer/FormLabel/_FormLabel.scss +4 -0
  23. package/lib/theme/ApiExplorer/FormLabel/index.d.ts +9 -0
  24. package/lib/theme/ApiExplorer/FormLabel/index.js +50 -0
  25. package/lib/theme/ApiExplorer/FormMultiSelect/index.d.ts +4 -1
  26. package/lib/theme/ApiExplorer/FormMultiSelect/index.js +97 -19
  27. package/lib/theme/ApiExplorer/FormSelect/index.d.ts +6 -1
  28. package/lib/theme/ApiExplorer/FormSelect/index.js +96 -15
  29. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +4 -1
  30. package/lib/theme/ApiExplorer/FormTextInput/index.js +71 -1
  31. package/lib/theme/ApiExplorer/MethodEndpoint/index.js +28 -0
  32. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +4 -1
  33. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +11 -3
  34. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +4 -1
  35. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +4 -1
  36. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +4 -1
  37. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +6 -2
  38. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +4 -1
  39. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +6 -2
  40. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +4 -1
  41. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +8 -3
  42. package/lib/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +0 -9
  43. package/lib/theme/ApiExplorer/ParamOptions/index.d.ts +10 -0
  44. package/lib/theme/ApiExplorer/ParamOptions/index.js +55 -5
  45. package/lib/theme/ApiExplorer/Request/_Request.scss +11 -0
  46. package/lib/theme/ApiExplorer/Request/index.js +19 -5
  47. package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +3 -1
  48. package/lib/theme/ApiExplorer/Request/makeRequest.js +19 -3
  49. package/lib/theme/ApiExplorer/Response/_Response.scss +11 -0
  50. package/lib/theme/ApiExplorer/Response/index.js +98 -12
  51. package/lib/theme/ApiExplorer/Server/index.d.ts +4 -1
  52. package/lib/theme/ApiExplorer/Server/index.js +6 -3
  53. package/lib/theme/ApiExplorer/buildPostmanRequest.d.ts +4 -1
  54. package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -5
  55. package/lib/theme/ApiExplorer/index.js +1 -0
  56. package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +2 -0
  57. package/lib/theme/ApiItem/hooks.d.ts +1 -0
  58. package/lib/theme/ApiItem/index.js +2 -1
  59. package/lib/theme/ApiItem/store.d.ts +6 -0
  60. package/lib/theme/ApiItem/store.js +11 -7
  61. package/lib/theme/ApiTabs/index.js +10 -11
  62. package/lib/theme/DiscriminatorTabs/index.js +10 -11
  63. package/lib/theme/MimeTabs/index.js +10 -11
  64. package/lib/theme/OperationTabs/index.js +10 -11
  65. package/lib/theme/ParamsItem/index.js +27 -0
  66. package/lib/theme/RequestSchema/index.js +172 -109
  67. package/lib/theme/ResponseHeaders/index.js +0 -1
  68. package/lib/theme/Schema/index.d.ts +1 -1
  69. package/lib/theme/Schema/index.js +91 -23
  70. package/lib/theme/SchemaItem/index.js +6 -1
  71. package/lib/theme/SchemaTabs/index.d.ts +1 -1
  72. package/lib/theme/SchemaTabs/index.js +31 -12
  73. package/lib/theme/styles.scss +1 -0
  74. package/lib/theme/translationIds.d.ts +3 -0
  75. package/lib/theme/translationIds.js +3 -0
  76. package/package.json +9 -8
  77. package/src/index.ts +2 -0
  78. package/src/markdown/schema.ts +69 -13
  79. package/src/theme/ApiExplorer/Accept/index.tsx +2 -1
  80. package/src/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.tsx +15 -3
  81. package/src/theme/ApiExplorer/Authorization/index.tsx +27 -33
  82. package/src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx +0 -5
  83. package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +115 -37
  84. package/src/theme/ApiExplorer/Body/index.tsx +85 -17
  85. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +9 -1
  86. package/src/theme/ApiExplorer/CodeTabs/index.tsx +19 -19
  87. package/src/theme/ApiExplorer/ContentType/index.tsx +7 -4
  88. package/src/theme/ApiExplorer/EncodingSelection/slice.ts +31 -0
  89. package/src/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.ts +43 -0
  90. package/src/theme/ApiExplorer/FormItem/_FormItem.scss +0 -5
  91. package/src/theme/ApiExplorer/FormItem/index.tsx +2 -16
  92. package/src/theme/ApiExplorer/FormLabel/_FormLabel.scss +4 -0
  93. package/src/theme/ApiExplorer/FormLabel/index.tsx +43 -0
  94. package/src/theme/ApiExplorer/FormMultiSelect/index.tsx +40 -20
  95. package/src/theme/ApiExplorer/FormSelect/index.tsx +41 -15
  96. package/src/theme/ApiExplorer/FormTextInput/index.tsx +15 -1
  97. package/src/theme/ApiExplorer/MethodEndpoint/index.tsx +21 -0
  98. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +13 -2
  99. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +12 -1
  100. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +14 -2
  101. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +14 -2
  102. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +16 -3
  103. package/src/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +0 -9
  104. package/src/theme/ApiExplorer/ParamOptions/index.tsx +97 -11
  105. package/src/theme/ApiExplorer/Request/_Request.scss +11 -0
  106. package/src/theme/ApiExplorer/Request/index.tsx +20 -8
  107. package/src/theme/ApiExplorer/Request/makeRequest.ts +19 -3
  108. package/src/theme/ApiExplorer/Response/_Response.scss +11 -0
  109. package/src/theme/ApiExplorer/Response/index.tsx +35 -14
  110. package/src/theme/ApiExplorer/Server/index.tsx +10 -3
  111. package/src/theme/ApiExplorer/buildPostmanRequest.ts +52 -5
  112. package/src/theme/ApiExplorer/index.tsx +1 -0
  113. package/src/theme/ApiItem/index.tsx +2 -1
  114. package/src/theme/ApiItem/store.ts +2 -0
  115. package/src/theme/ApiTabs/index.tsx +14 -19
  116. package/src/theme/DiscriminatorTabs/index.tsx +14 -19
  117. package/src/theme/MimeTabs/index.tsx +15 -19
  118. package/src/theme/OperationTabs/index.tsx +14 -19
  119. package/src/theme/ParamsItem/index.tsx +25 -0
  120. package/src/theme/RequestSchema/index.tsx +141 -83
  121. package/src/theme/ResponseHeaders/index.tsx +1 -2
  122. package/src/theme/Schema/index.tsx +112 -27
  123. package/src/theme/SchemaItem/index.tsx +6 -1
  124. package/src/theme/SchemaTabs/index.tsx +42 -21
  125. package/src/theme/styles.scss +1 -0
  126. package/src/theme/translationIds.ts +3 -0
  127. package/src/theme-classic.d.ts +25 -1
  128. package/src/types.d.ts +7 -0
  129. package/tsconfig.tsbuildinfo +1 -1
@@ -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({ value, options, onChange, showErrors }: Props) {
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
- <select
37
- style={{ height: height }}
38
- className={clsx("openapi-explorer__multi-select-input", {
39
- error: showErrors,
40
- })}
41
- value={value}
42
- onChange={onChange}
43
- size={Math.min(6, options.length + 1)}
44
- multiple
45
- >
46
- {options.map((option) => {
47
- return (
48
- <option key={option} value={option}>
49
- {option}
50
- </option>
51
- );
52
- })}
53
- </select>
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({ value, options, onChange }: Props) {
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
- <select
23
- className="openapi-explorer__select-input"
24
- value={value}
25
- onChange={onChange}
26
- >
27
- {options.map((option) => {
28
- return (
29
- <option key={option} value={option}>
30
- {option}
31
- </option>
32
- );
33
- })}
34
- </select>
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}
@@ -8,6 +8,7 @@
8
8
  import React from "react";
9
9
 
10
10
  import BrowserOnly from "@docusaurus/BrowserOnly";
11
+ import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
11
12
  import { useTypedSelector } from "@theme/ApiItem/hooks";
12
13
 
13
14
  function colorForMethod(method: string) {
@@ -38,6 +39,26 @@ export interface Props {
38
39
  }
39
40
 
40
41
  function MethodEndpoint({ method, path, context }: Props) {
42
+ // During SSR, render without Redux store access to avoid "Cannot read properties
43
+ // of null (reading 'store')" errors caused by useSelector running outside a Provider.
44
+ if (!ExecutionEnvironment.canUseDOM) {
45
+ return (
46
+ <>
47
+ <pre className="openapi__method-endpoint">
48
+ <span className={"badge badge--" + colorForMethod(method)}>
49
+ {method === "event" ? "Webhook" : method.toUpperCase()}
50
+ </span>{" "}
51
+ {method !== "event" && (
52
+ <h2 className="openapi__method-endpoint-path">
53
+ {`${path.replace(/{([a-z0-9-_]+)}/gi, ":$1")}`}
54
+ </h2>
55
+ )}
56
+ </pre>
57
+ <div className="openapi__divider" />
58
+ </>
59
+ );
60
+ }
61
+
41
62
  let serverValue = useTypedSelector((state: any) => state.server.value);
42
63
  let serverUrlWithVariables = "";
43
64
 
@@ -10,6 +10,7 @@ import React, { useEffect, useState } from "react";
10
10
  import { translate } from "@docusaurus/Translate";
11
11
  import { ErrorMessage } from "@hookform/error-message";
12
12
  import { nanoid } from "@reduxjs/toolkit";
13
+ import FormLabel from "@theme/ApiExplorer/FormLabel";
13
14
  import FormSelect from "@theme/ApiExplorer/FormSelect";
14
15
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
15
16
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
@@ -19,6 +20,9 @@ import { Controller, useFormContext } from "react-hook-form";
19
20
 
20
21
  export interface ParamProps {
21
22
  param: Param;
23
+ label?: string;
24
+ type?: string;
25
+ required?: boolean;
22
26
  }
23
27
 
24
28
  function ArrayItem({
@@ -31,6 +35,7 @@ function ArrayItem({
31
35
  if (param.schema?.items?.type === "boolean") {
32
36
  return (
33
37
  <FormSelect
38
+ ariaLabel={param.description || param.name}
34
39
  options={["---", "true", "false"]}
35
40
  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
36
41
  const val = e.target.value;
@@ -52,7 +57,12 @@ function ArrayItem({
52
57
  );
53
58
  }
54
59
 
55
- export default function ParamArrayFormItem({ param }: ParamProps) {
60
+ export default function ParamArrayFormItem({
61
+ param,
62
+ label,
63
+ type,
64
+ required,
65
+ }: ParamProps) {
56
66
  const [items, setItems] = useState<{ id: string; value?: string }[]>([]);
57
67
  const dispatch = useTypedDispatch();
58
68
 
@@ -122,6 +132,7 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
122
132
 
123
133
  return (
124
134
  <>
135
+ {label && <FormLabel label={label} type={type} required={required} />}
125
136
  <Controller
126
137
  control={control}
127
138
  rules={{
@@ -145,6 +156,7 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
145
156
  <button
146
157
  className="openapi-explorer__delete-btn"
147
158
  onClick={handleDeleteItem(item)}
159
+ aria-label="Delete"
148
160
  >
149
161
  <svg
150
162
  focusable="false"
@@ -157,7 +169,6 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
157
169
  aria-hidden="true"
158
170
  >
159
171
  <path d="M24 9.4L22.6 8 16 14.6 9.4 8 8 9.4 14.6 16 8 22.6 9.4 24 16 17.4 22.6 24 24 22.6 17.4 16 24 9.4z"></path>
160
- <title>Delete</title>
161
172
  </svg>
162
173
  </button>
163
174
  </div>
@@ -17,9 +17,17 @@ import { Controller, useFormContext } from "react-hook-form";
17
17
 
18
18
  export interface ParamProps {
19
19
  param: Param;
20
+ label?: string;
21
+ type?: string;
22
+ required?: boolean;
20
23
  }
21
24
 
22
- export default function ParamBooleanFormItem({ param }: ParamProps) {
25
+ export default function ParamBooleanFormItem({
26
+ param,
27
+ label,
28
+ type,
29
+ required,
30
+ }: ParamProps) {
23
31
  const dispatch = useTypedDispatch();
24
32
 
25
33
  const {
@@ -44,6 +52,9 @@ export default function ParamBooleanFormItem({ param }: ParamProps) {
44
52
  name="paramBoolean"
45
53
  render={({ field: { onChange } }) => (
46
54
  <FormSelect
55
+ label={label}
56
+ type={type}
57
+ required={required}
47
58
  options={["---", "true", "false"]}
48
59
  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
49
60
  const val = e.target.value;
@@ -10,6 +10,7 @@ import React from "react";
10
10
  import { translate } from "@docusaurus/Translate";
11
11
  import { ErrorMessage } from "@hookform/error-message";
12
12
  import FormMultiSelect from "@theme/ApiExplorer/FormMultiSelect";
13
+ import { getSchemaEnum } from "@theme/ApiExplorer/ParamOptions";
13
14
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
14
15
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
15
16
  import { OPENAPI_FORM } from "@theme/translationIds";
@@ -17,9 +18,17 @@ import { Controller, useFormContext } from "react-hook-form";
17
18
 
18
19
  export interface ParamProps {
19
20
  param: Param;
21
+ label?: string;
22
+ type?: string;
23
+ required?: boolean;
20
24
  }
21
25
 
22
- export default function ParamMultiSelectFormItem({ param }: ParamProps) {
26
+ export default function ParamMultiSelectFormItem({
27
+ param,
28
+ label,
29
+ type,
30
+ required,
31
+ }: ParamProps) {
23
32
  const {
24
33
  control,
25
34
  formState: { errors },
@@ -29,7 +38,7 @@ export default function ParamMultiSelectFormItem({ param }: ParamProps) {
29
38
 
30
39
  const dispatch = useTypedDispatch();
31
40
 
32
- const options = param.schema?.items?.enum ?? [];
41
+ const options = getSchemaEnum(param.schema?.items) ?? [];
33
42
 
34
43
  const pathParams = useTypedSelector((state: any) => state.params.path);
35
44
  const queryParams = useTypedSelector((state: any) => state.params.query);
@@ -74,6 +83,9 @@ export default function ParamMultiSelectFormItem({ param }: ParamProps) {
74
83
  name="paramMultiSelect"
75
84
  render={({ field: { onChange } }) => (
76
85
  <FormMultiSelect
86
+ label={label}
87
+ type={type}
88
+ required={required}
77
89
  options={options as string[]}
78
90
  onChange={(e: any) => handleChange(e, onChange)}
79
91
  showErrors={!!showErrorMessage}
@@ -10,6 +10,7 @@ import React from "react";
10
10
  import { translate } from "@docusaurus/Translate";
11
11
  import { ErrorMessage } from "@hookform/error-message";
12
12
  import FormSelect from "@theme/ApiExplorer/FormSelect";
13
+ import { getSchemaEnum } from "@theme/ApiExplorer/ParamOptions";
13
14
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
14
15
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
15
16
  import { OPENAPI_FORM } from "@theme/translationIds";
@@ -17,9 +18,17 @@ import { Controller, useFormContext } from "react-hook-form";
17
18
 
18
19
  export interface ParamProps {
19
20
  param: Param;
21
+ label?: string;
22
+ type?: string;
23
+ required?: boolean;
20
24
  }
21
25
 
22
- export default function ParamSelectFormItem({ param }: ParamProps) {
26
+ export default function ParamSelectFormItem({
27
+ param,
28
+ label,
29
+ type,
30
+ required,
31
+ }: ParamProps) {
23
32
  const {
24
33
  control,
25
34
  formState: { errors },
@@ -29,7 +38,7 @@ export default function ParamSelectFormItem({ param }: ParamProps) {
29
38
 
30
39
  const dispatch = useTypedDispatch();
31
40
 
32
- const options = param.schema?.enum ?? [];
41
+ const options = getSchemaEnum(param.schema) ?? [];
33
42
 
34
43
  return (
35
44
  <>
@@ -46,6 +55,9 @@ export default function ParamSelectFormItem({ param }: ParamProps) {
46
55
  name="paramSelect"
47
56
  render={({ field: { onChange } }) => (
48
57
  <FormSelect
58
+ label={label}
59
+ type={type}
60
+ required={required}
49
61
  options={["---", ...(options as string[])]}
50
62
  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
51
63
  const val = e.target.value;
@@ -13,12 +13,23 @@ import { useTypedDispatch } from "@theme/ApiItem/hooks";
13
13
 
14
14
  export interface ParamProps {
15
15
  param: Param;
16
+ label?: string;
17
+ type?: string;
18
+ required?: boolean;
16
19
  }
17
20
 
18
- export default function ParamTextFormItem({ param }: ParamProps) {
21
+ export default function ParamTextFormItem({
22
+ param,
23
+ label,
24
+ type,
25
+ required,
26
+ }: ParamProps) {
19
27
  const dispatch = useTypedDispatch();
20
28
  return (
21
29
  <FormTextInput
30
+ label={label}
31
+ type={type}
32
+ required={required}
22
33
  isRequired={param.required}
23
34
  paramName={param.name}
24
35
  placeholder={param.description || param.name}
@@ -27,9 +38,11 @@ export default function ParamTextFormItem({ param }: ParamProps) {
27
38
  setParam({
28
39
  ...param,
29
40
  value:
30
- param.in === "path" || param.in === "query"
41
+ param.in === "path"
31
42
  ? e.target.value.replace(/\s/g, "%20")
32
- : e.target.value,
43
+ : param.in === "query"
44
+ ? encodeURIComponent(e.target.value)
45
+ : e.target.value,
33
46
  })
34
47
  )
35
48
  }
@@ -63,15 +63,10 @@
63
63
  margin-top: calc(var(--ifm-pre-padding) / 2);
64
64
  background-color: var(--openapi-input-background);
65
65
  border: none;
66
- outline: none;
67
66
  color: var(--ifm-pre-color);
68
67
  border-radius: 4px;
69
68
  margin-left: 4px;
70
69
 
71
- &:focus {
72
- outline: 0;
73
- }
74
-
75
70
  &:active {
76
71
  box-shadow: inset 0px 0px 0px 2px var(--openapi-input-border);
77
72
  }
@@ -102,10 +97,6 @@
102
97
  background-color: var(--openapi-input-border);
103
98
  }
104
99
 
105
- &:focus {
106
- outline: 0;
107
- }
108
-
109
100
  &:active {
110
101
  box-shadow:
111
102
  inset 0 0 0 1px var(--openapi-input-border),
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { useState } from "react";
8
+ import React, { useState, useId } from "react";
9
9
 
10
10
  import { translate } from "@docusaurus/Translate";
11
11
  import FormItem from "@theme/ApiExplorer/FormItem";
@@ -19,36 +19,117 @@ import { OPENAPI_PARAM_OPTIONS } from "@theme/translationIds";
19
19
 
20
20
  import { Param } from "./slice";
21
21
 
22
+ export interface LabelProps {
23
+ label?: string;
24
+ type?: string;
25
+ required?: boolean;
26
+ }
27
+
22
28
  export interface ParamProps {
23
29
  param: Param;
24
30
  }
25
31
 
26
- function ParamOption({ param }: ParamProps) {
27
- if (param.schema?.type === "array" && param.schema.items?.enum) {
28
- return <ParamMultiSelectFormItem param={param} />;
32
+ /**
33
+ * Extracts enum values from a schema, including when wrapped in allOf.
34
+ * This handles cases where an enum is referenced via allOf for composition.
35
+ */
36
+ export function getSchemaEnum(schema: any): any[] | undefined {
37
+ // Direct enum on schema
38
+ if (schema?.enum) {
39
+ return schema.enum;
40
+ }
41
+
42
+ // Enum inside allOf - check each item
43
+ if (schema?.allOf && Array.isArray(schema.allOf)) {
44
+ for (const item of schema.allOf) {
45
+ if (item.enum) {
46
+ return item.enum;
47
+ }
48
+ }
49
+ }
50
+
51
+ // const is semantically a single-value enum
52
+ if (schema?.const !== undefined) {
53
+ return [schema.const];
54
+ }
55
+
56
+ return undefined;
57
+ }
58
+
59
+ function ParamOption({
60
+ param,
61
+ label,
62
+ type,
63
+ required,
64
+ }: ParamProps & LabelProps) {
65
+ const schemaEnum = getSchemaEnum(param.schema);
66
+ const itemsEnum = getSchemaEnum(param.schema?.items);
67
+
68
+ if (param.schema?.type === "array" && itemsEnum) {
69
+ return (
70
+ <ParamMultiSelectFormItem
71
+ param={param}
72
+ label={label}
73
+ type={type}
74
+ required={required}
75
+ />
76
+ );
29
77
  }
30
78
 
31
79
  if (param.schema?.type === "array") {
32
- return <ParamArrayFormItem param={param} />;
80
+ return (
81
+ <ParamArrayFormItem
82
+ param={param}
83
+ label={label}
84
+ type={type}
85
+ required={required}
86
+ />
87
+ );
33
88
  }
34
89
 
35
- if (param.schema?.enum) {
36
- return <ParamSelectFormItem param={param} />;
90
+ if (schemaEnum) {
91
+ return (
92
+ <ParamSelectFormItem
93
+ param={param}
94
+ label={label}
95
+ type={type}
96
+ required={required}
97
+ />
98
+ );
37
99
  }
38
100
 
39
101
  if (param.schema?.type === "boolean") {
40
- return <ParamBooleanFormItem param={param} />;
102
+ return (
103
+ <ParamBooleanFormItem
104
+ param={param}
105
+ label={label}
106
+ type={type}
107
+ required={required}
108
+ />
109
+ );
41
110
  }
42
111
 
43
112
  // integer, number, string, int32, int64, float, double, object, byte, binary,
44
113
  // date-time, date, password
45
- return <ParamTextFormItem param={param} />;
114
+ return (
115
+ <ParamTextFormItem
116
+ param={param}
117
+ label={label}
118
+ type={type}
119
+ required={required}
120
+ />
121
+ );
46
122
  }
47
123
 
48
124
  function ParamOptionWrapper({ param }: ParamProps) {
49
125
  return (
50
- <FormItem label={param.name} type={param.in} required={param.required}>
51
- <ParamOption param={param} />
126
+ <FormItem>
127
+ <ParamOption
128
+ param={param}
129
+ label={param.name}
130
+ type={param.in}
131
+ required={param.required}
132
+ />
52
133
  </FormItem>
53
134
  );
54
135
  }
@@ -56,6 +137,8 @@ function ParamOptionWrapper({ param }: ParamProps) {
56
137
  function ParamOptions() {
57
138
  const [showOptional, setShowOptional] = useState(false);
58
139
 
140
+ const optionalId = useId();
141
+
59
142
  const pathParams = useTypedSelector((state: any) => state.params.path);
60
143
  const queryParams = useTypedSelector((state: any) => state.params.query);
61
144
  const cookieParams = useTypedSelector((state: any) => state.params.cookie);
@@ -84,6 +167,8 @@ function ParamOptions() {
84
167
  <button
85
168
  type="button"
86
169
  className="openapi-explorer__show-more-btn"
170
+ aria-expanded={showOptional}
171
+ aria-controls={optionalId}
87
172
  onClick={() => setShowOptional((prev) => !prev)}
88
173
  >
89
174
  <span
@@ -137,6 +222,7 @@ function ParamOptions() {
137
222
  ? "openapi-explorer__show-options"
138
223
  : "openapi-explorer__hide-options"
139
224
  }
225
+ id={optionalId}
140
226
  >
141
227
  {optionalParams.map((param) => (
142
228
  <ParamOptionWrapper
@@ -48,6 +48,17 @@
48
48
  }
49
49
 
50
50
  .openapi-explorer__expand-details-btn {
51
+ -webkit-appearance: none;
52
+ -moz-appearance: none;
53
+ appearance: none;
54
+ padding: 0;
55
+ cursor: pointer;
56
+ border: 0px solid transparent;
57
+ background-color: transparent;
58
+ text-transform: inherit;
59
+ font-weight: inherit;
60
+ font-size: inherit;
61
+
51
62
  &:hover {
52
63
  cursor: pointer;
53
64
  }