docusaurus-theme-openapi-docs 0.0.0-beta.646 → 0.0.0-beta.651

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 (79) hide show
  1. package/lib/theme/ApiDemoPanel/ApiCodeBlock/Content/_Content.scss +1 -0
  2. package/lib/theme/ApiDemoPanel/Body/index.d.ts +3 -1
  3. package/lib/theme/ApiDemoPanel/Body/index.js +30 -32
  4. package/lib/theme/ApiDemoPanel/CodeTabs/_CodeTabs.scss +95 -39
  5. package/lib/theme/ApiDemoPanel/CodeTabs/index.js +24 -6
  6. package/lib/theme/ApiDemoPanel/Curl/index.d.ts +5 -4
  7. package/lib/theme/ApiDemoPanel/Curl/index.js +79 -11
  8. package/lib/theme/ApiDemoPanel/FormItem/_FormItem.scss +11 -2
  9. package/lib/theme/ApiDemoPanel/FormItem/index.d.ts +2 -1
  10. package/lib/theme/ApiDemoPanel/FormItem/index.js +9 -3
  11. package/lib/theme/ApiDemoPanel/FormMultiSelect/_FormMultiSelect.scss +8 -4
  12. package/lib/theme/ApiDemoPanel/FormMultiSelect/index.d.ts +2 -1
  13. package/lib/theme/ApiDemoPanel/FormMultiSelect/index.js +5 -2
  14. package/lib/theme/ApiDemoPanel/FormSelect/_FormSelect.scss +3 -3
  15. package/lib/theme/ApiDemoPanel/FormTextInput/_FormTextInput.scss +24 -5
  16. package/lib/theme/ApiDemoPanel/FormTextInput/index.d.ts +1 -1
  17. package/lib/theme/ApiDemoPanel/FormTextInput/index.js +56 -10
  18. package/lib/theme/ApiDemoPanel/LiveEditor/index.d.ts +5 -2
  19. package/lib/theme/ApiDemoPanel/LiveEditor/index.js +59 -14
  20. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +6 -0
  21. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamArrayFormItem.js +194 -0
  22. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +6 -0
  23. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +63 -0
  24. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +6 -0
  25. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +89 -0
  26. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +6 -0
  27. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamSelectFormItem.js +63 -0
  28. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +6 -0
  29. package/lib/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamTextFormItem.js +38 -0
  30. package/lib/theme/ApiDemoPanel/ParamOptions/_ParamOptions.scss +9 -28
  31. package/lib/theme/ApiDemoPanel/ParamOptions/index.js +24 -176
  32. package/lib/theme/ApiDemoPanel/Request/_Request.scss +93 -20
  33. package/lib/theme/ApiDemoPanel/Request/index.d.ts +1 -1
  34. package/lib/theme/ApiDemoPanel/Request/index.js +316 -37
  35. package/lib/theme/ApiDemoPanel/Response/_Response.scss +54 -0
  36. package/lib/theme/ApiDemoPanel/Response/index.d.ts +4 -1
  37. package/lib/theme/ApiDemoPanel/Response/index.js +56 -31
  38. package/lib/theme/ApiDemoPanel/Server/_Server.scss +10 -0
  39. package/lib/theme/ApiDemoPanel/Server/index.js +10 -11
  40. package/lib/theme/ApiDemoPanel/index.js +1 -1
  41. package/lib/theme/SchemaTabs/_SchemaTabs.scss +0 -1
  42. package/lib/theme/styles.scss +27 -0
  43. package/package.json +7 -4
  44. package/src/theme/ApiDemoPanel/ApiCodeBlock/Content/_Content.scss +1 -0
  45. package/src/theme/ApiDemoPanel/Body/index.tsx +38 -29
  46. package/src/theme/ApiDemoPanel/CodeTabs/_CodeTabs.scss +95 -39
  47. package/src/theme/ApiDemoPanel/CodeTabs/index.js +24 -6
  48. package/src/theme/ApiDemoPanel/Curl/index.tsx +85 -22
  49. package/src/theme/ApiDemoPanel/FormItem/_FormItem.scss +11 -2
  50. package/src/theme/ApiDemoPanel/FormItem/index.tsx +8 -3
  51. package/src/theme/ApiDemoPanel/FormMultiSelect/_FormMultiSelect.scss +8 -4
  52. package/src/theme/ApiDemoPanel/FormMultiSelect/index.tsx +7 -2
  53. package/src/theme/ApiDemoPanel/FormSelect/_FormSelect.scss +3 -3
  54. package/src/theme/ApiDemoPanel/FormTextInput/_FormTextInput.scss +24 -5
  55. package/src/theme/ApiDemoPanel/FormTextInput/index.tsx +58 -10
  56. package/src/theme/ApiDemoPanel/LiveEditor/index.tsx +53 -14
  57. package/src/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +153 -0
  58. package/src/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +64 -0
  59. package/src/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +86 -0
  60. package/src/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +65 -0
  61. package/src/theme/ApiDemoPanel/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +38 -0
  62. package/src/theme/ApiDemoPanel/ParamOptions/_ParamOptions.scss +9 -28
  63. package/src/theme/ApiDemoPanel/ParamOptions/index.tsx +8 -196
  64. package/src/theme/ApiDemoPanel/Request/_Request.scss +93 -20
  65. package/src/theme/ApiDemoPanel/Request/index.tsx +250 -28
  66. package/src/theme/ApiDemoPanel/Response/_Response.scss +54 -0
  67. package/src/theme/ApiDemoPanel/Response/index.tsx +44 -26
  68. package/src/theme/ApiDemoPanel/Server/_Server.scss +10 -0
  69. package/src/theme/ApiDemoPanel/Server/index.tsx +8 -11
  70. package/src/theme/ApiDemoPanel/index.tsx +1 -1
  71. package/src/theme/SchemaTabs/_SchemaTabs.scss +0 -1
  72. package/src/theme/styles.scss +27 -0
  73. package/src/theme-openapi.d.ts +40 -1
  74. package/lib/theme/ApiDemoPanel/Execute/index.d.ts +0 -8
  75. package/lib/theme/ApiDemoPanel/Execute/index.js +0 -213
  76. package/src/theme/ApiDemoPanel/Execute/index.tsx +0 -200
  77. /package/lib/theme/ApiDemoPanel/{Execute → Request}/makeRequest.d.ts +0 -0
  78. /package/lib/theme/ApiDemoPanel/{Execute → Request}/makeRequest.js +0 -0
  79. /package/src/theme/ApiDemoPanel/{Execute → Request}/makeRequest.ts +0 -0
@@ -17,11 +17,12 @@ import { useTypedSelector } from "@theme/ApiItem/hooks";
17
17
  import merge from "lodash/merge";
18
18
 
19
19
  export interface Language {
20
- highlight?: string;
20
+ highlight: string;
21
21
  language: string;
22
- logoClass?: string;
23
- variant?: string;
24
- options?: { [key: string]: boolean };
22
+ logoClass: string;
23
+ variant: string;
24
+ variants: string[];
25
+ options: { [key: string]: boolean };
25
26
  source?: string;
26
27
  }
27
28
 
@@ -36,6 +37,7 @@ export const languageSet: Language[] = [
36
37
  trimRequestBody: true,
37
38
  },
38
39
  variant: "cURL",
40
+ variants: ["curl"],
39
41
  },
40
42
  {
41
43
  highlight: "python",
@@ -46,6 +48,7 @@ export const languageSet: Language[] = [
46
48
  trimRequestBody: true,
47
49
  },
48
50
  variant: "requests",
51
+ variants: ["requests", "http.client"],
49
52
  },
50
53
  {
51
54
  highlight: "go",
@@ -56,6 +59,7 @@ export const languageSet: Language[] = [
56
59
  trimRequestBody: true,
57
60
  },
58
61
  variant: "native",
62
+ variants: ["native"],
59
63
  },
60
64
  {
61
65
  highlight: "javascript",
@@ -67,6 +71,7 @@ export const languageSet: Language[] = [
67
71
  trimRequestBody: true,
68
72
  },
69
73
  variant: "axios",
74
+ variants: ["axios", "native", "request", "unirest"],
70
75
  },
71
76
  {
72
77
  highlight: "ruby",
@@ -77,6 +82,7 @@ export const languageSet: Language[] = [
77
82
  trimRequestBody: true,
78
83
  },
79
84
  variant: "Net::HTTP",
85
+ variants: ["net::http"],
80
86
  },
81
87
  {
82
88
  highlight: "csharp",
@@ -87,6 +93,7 @@ export const languageSet: Language[] = [
87
93
  trimRequestBody: true,
88
94
  },
89
95
  variant: "RestSharp",
96
+ variants: ["restsharp", "httpclient"],
90
97
  },
91
98
  {
92
99
  highlight: "php",
@@ -97,6 +104,7 @@ export const languageSet: Language[] = [
97
104
  trimRequestBody: true,
98
105
  },
99
106
  variant: "cURL",
107
+ variants: ["curl", "guzzle", "pecl_http", "http_request2"],
100
108
  },
101
109
  {
102
110
  highlight: "java",
@@ -107,6 +115,7 @@ export const languageSet: Language[] = [
107
115
  trimRequestBody: true,
108
116
  },
109
117
  variant: "OkHttp",
118
+ variants: ["okhttp", "unirest"],
110
119
  },
111
120
  {
112
121
  highlight: "powershell",
@@ -117,6 +126,7 @@ export const languageSet: Language[] = [
117
126
  trimRequestBody: true,
118
127
  },
119
128
  variant: "RestMethod",
129
+ variants: ["restmethod"],
120
130
  },
121
131
  ];
122
132
 
@@ -173,7 +183,7 @@ function Curl({ postman, codeSamples }: Props) {
173
183
  (lang) =>
174
184
  lang.language === localStorage.getItem("docusaurus.tab.code-samples")
175
185
  );
176
-
186
+ const [selectedVariant, setSelectedVariant] = useState();
177
187
  const [language, setLanguage] = useState(() => {
178
188
  // Return first index if only 1 user-defined language exists
179
189
  if (mergedLangs.length === 1) {
@@ -182,7 +192,6 @@ function Curl({ postman, codeSamples }: Props) {
182
192
  // Fall back to language in localStorage or first user-defined language
183
193
  return defaultLang[0] ?? mergedLangs[0];
184
194
  });
185
-
186
195
  const [codeText, setCodeText] = useState("");
187
196
 
188
197
  useEffect(() => {
@@ -198,7 +207,6 @@ function Curl({ postman, codeSamples }: Props) {
198
207
  server,
199
208
  auth,
200
209
  });
201
-
202
210
  codegen.convert(
203
211
  language.language,
204
212
  language.variant,
@@ -264,36 +272,91 @@ function Curl({ postman, codeSamples }: Props) {
264
272
  mergedLangs,
265
273
  ]);
266
274
 
275
+ useEffect(() => {
276
+ if (selectedVariant && selectedVariant !== language.variant) {
277
+ const postmanRequest = buildPostmanRequest(postman, {
278
+ queryParams,
279
+ pathParams,
280
+ cookieParams,
281
+ contentType,
282
+ accept,
283
+ headerParams,
284
+ body,
285
+ server,
286
+ auth,
287
+ });
288
+ codegen.convert(
289
+ language.language,
290
+ selectedVariant,
291
+ postmanRequest,
292
+ language.options,
293
+ (error: any, snippet: string) => {
294
+ if (error) {
295
+ return;
296
+ }
297
+ setCodeText(snippet);
298
+ }
299
+ );
300
+ }
301
+ });
302
+
267
303
  if (language === undefined) {
268
304
  return null;
269
305
  }
270
306
 
271
307
  return (
272
308
  <>
273
- <CodeTabs groupId="code-samples" action={setLanguage}>
309
+ <CodeTabs
310
+ groupId="code-samples"
311
+ action={{
312
+ setLanguage: setLanguage,
313
+ setSelectedVariant: setSelectedVariant,
314
+ }}
315
+ lazy
316
+ >
274
317
  {mergedLangs.map((lang) => {
275
318
  return (
276
319
  <CodeTab
277
320
  value={lang.language}
278
- label={""}
279
- key={
280
- lang.variant
281
- ? `${lang.language}-${lang.variant}`
282
- : lang.language
283
- }
321
+ label={lang.language}
322
+ key={lang.language}
284
323
  attributes={{
285
324
  className: `openapi-tabs__code-item--${lang.logoClass}`,
286
325
  }}
287
326
  >
288
- {/* @ts-ignore */}
289
- <ApiCodeBlock
290
- language={lang.highlight}
291
- className="openapi-demo__code-block"
292
- title={`${lang.language} / ${lang.variant}`}
293
- showLineNumbers={true}
327
+ <CodeTabs
328
+ className="openapi-tabs__code-container-inner"
329
+ action={{
330
+ setLanguage: setLanguage,
331
+ setSelectedVariant: setSelectedVariant,
332
+ }}
333
+ includeVariant={true}
334
+ currentLanguage={lang.language}
335
+ defaultValue={selectedVariant}
336
+ lazy
294
337
  >
295
- {codeText}
296
- </ApiCodeBlock>
338
+ {lang.variants.map((variant) => {
339
+ return (
340
+ <CodeTab
341
+ value={variant.toLowerCase()}
342
+ label={variant.toUpperCase()}
343
+ key={`${lang.language}-${lang.variant}`}
344
+ attributes={{
345
+ className: `openapi-tabs__code-item--variant`,
346
+ }}
347
+ >
348
+ {/* @ts-ignore */}
349
+ <ApiCodeBlock
350
+ language={lang.highlight}
351
+ className="openapi-demo__code-block"
352
+ showLineNumbers={true}
353
+ >
354
+ {codeText}
355
+ </ApiCodeBlock>
356
+ </CodeTab>
357
+ );
358
+ })}
359
+ </CodeTabs>
297
360
  </CodeTab>
298
361
  );
299
362
  })}
@@ -1,12 +1,21 @@
1
1
  .openapi-demo__form-item {
2
- margin-top: var(--ifm-pre-padding);
2
+ padding: var(--openapi-demo-padding-input);
3
+ font-size: var(--openapi-demo-font-size-input);
3
4
 
4
5
  &:first-child {
5
6
  margin-top: 0;
6
7
  }
7
8
 
8
9
  .required {
9
- font-size: var(--ifm-code-font-size);
10
10
  color: var(--openapi-required);
11
11
  }
12
12
  }
13
+
14
+ .openapi-demo__form-item-body-container {
15
+ padding: 0;
16
+ }
17
+
18
+ .openapi-demo__form-item-label {
19
+ font-family: var(--ifm-font-family-monospace);
20
+ font-weight: bold;
21
+ }
@@ -7,17 +7,22 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import clsx from "clsx";
11
+
10
12
  export interface Props {
11
13
  label?: string;
12
14
  type?: string;
13
15
  required?: boolean | undefined;
14
16
  children?: React.ReactNode;
17
+ className?: string;
15
18
  }
16
19
 
17
- function FormItem({ label, type, required, children }: Props) {
20
+ function FormItem({ label, type, required, children, className }: Props) {
18
21
  return (
19
- <div className="openapi-demo__form-item">
20
- <code>{label}</code>
22
+ <div className={clsx("openapi-demo__form-item", className)}>
23
+ {label && (
24
+ <label className="openapi-demo__form-item-label">{label}</label>
25
+ )}
21
26
  {type && <span style={{ opacity: 0.6 }}> — {type}</span>}
22
27
  {required && (
23
28
  <span>
@@ -1,19 +1,23 @@
1
1
  .openapi-demo__multi-select-input {
2
2
  width: 100%;
3
3
  margin-top: calc(var(--ifm-pre-padding) / 2);
4
- padding: 12px var(--ifm-pre-padding);
4
+ padding: 1rem;
5
5
  border-radius: 4px;
6
- border: 2px solid transparent;
6
+ border: 1px solid transparent;
7
7
  background-color: var(--openapi-input-background);
8
8
  outline: none;
9
- font-size: var(--ifm-code-font-size);
9
+ font-size: var(--openapi-demo-font-size-input);
10
10
  color: var(--ifm-pre-color);
11
11
  -moz-appearance: none;
12
12
  -webkit-appearance: none;
13
13
  appearance: none;
14
14
 
15
15
  &:focus {
16
- border: 2px solid var(--openapi-input-border);
16
+ border: 1px solid var(--openapi-input-border);
17
+ }
18
+
19
+ &.error {
20
+ border: 1px solid var(--ifm-color-danger);
17
21
  }
18
22
 
19
23
  option {
@@ -7,13 +7,16 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import clsx from "clsx";
11
+
10
12
  export interface Props {
11
13
  value?: string;
12
14
  options: string[];
13
15
  onChange?: React.ChangeEventHandler<HTMLSelectElement>;
16
+ showErrors?: boolean;
14
17
  }
15
18
 
16
- function FormMultiSelect({ value, options, onChange }: Props) {
19
+ function FormMultiSelect({ value, options, onChange, showErrors }: Props) {
17
20
  if (options.length === 0) {
18
21
  return null;
19
22
  }
@@ -32,7 +35,9 @@ function FormMultiSelect({ value, options, onChange }: Props) {
32
35
  return (
33
36
  <select
34
37
  style={{ height: height }}
35
- className="openapi-demo__multi-select-input"
38
+ className={clsx("openapi-demo__multi-select-input", {
39
+ error: showErrors,
40
+ })}
36
41
  value={value}
37
42
  onChange={onChange}
38
43
  size={Math.min(6, options.length + 1)}
@@ -4,7 +4,6 @@ html[data-theme="dark"] .openapi-demo__select-input {
4
4
  border: none;
5
5
  outline: none;
6
6
  width: 100%;
7
- font-size: var(--ifm-code-font-size);
8
7
  color: var(--ifm-pre-color);
9
8
 
10
9
  border-radius: 4px;
@@ -21,12 +20,13 @@ html[data-theme="dark"] .openapi-demo__select-input {
21
20
  .openapi-demo__select-input {
22
21
  width: 100%;
23
22
  margin-top: calc(var(--ifm-pre-padding) / 2);
24
- padding: 12px 48px 12px var(--ifm-pre-padding);
23
+ padding: var(--openapi-demo-padding-input);
25
24
  border: none;
26
25
  outline: none;
27
26
  border-radius: 4px;
28
27
  background-color: var(--openapi-input-background);
29
- font-size: var(--ifm-code-font-size);
28
+ font-size: var(--openapi-demo-font-size-input);
29
+ font-family: var(--ifm-font-family-monospace);
30
30
  color: var(--ifm-pre-color);
31
31
  -moz-appearance: none;
32
32
  -webkit-appearance: none;
@@ -1,15 +1,34 @@
1
- .openapi-demo__input {
1
+ .openapi-demo__form-item-input {
2
2
  margin-top: calc(var(--ifm-pre-padding) / 2);
3
3
  background-color: var(--openapi-input-background);
4
- border: none;
4
+ border: 1px solid transparent;
5
5
  outline: none;
6
6
  width: 100%;
7
- font-size: var(--ifm-code-font-size);
8
7
  color: var(--ifm-pre-color);
9
- padding: 12px var(--ifm-pre-padding);
8
+ padding: var(--openapi-demo-padding-input);
10
9
  border-radius: 4px;
11
10
 
11
+ &:hover {
12
+ border: 1px solid var(--ifm-toc-border-color);
13
+ }
14
+
12
15
  &:focus {
13
- box-shadow: inset 0px 0px 0px 2px var(--openapi-input-border);
16
+ border: 1px solid var(--ifm-color-primary);
17
+ box-shadow: none;
18
+ }
19
+
20
+ &.error {
21
+ border: 1px solid var(--openapi-required);
22
+ }
23
+ }
24
+
25
+ .openapi-demo__input-error {
26
+ font-size: var(--openapi-demo-font-size-input);
27
+ color: var(--openapi-required);
28
+ padding-top: var(--openapi-demo-padding-input);
29
+
30
+ &::before {
31
+ display: inline;
32
+ content: "⚠ ";
14
33
  }
15
34
  }
@@ -5,8 +5,13 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
+ // @ts-nocheck
8
9
  import React from "react";
9
10
 
11
+ import { ErrorMessage } from "@hookform/error-message";
12
+ import clsx from "clsx";
13
+ import { useFormContext } from "react-hook-form";
14
+
10
15
  export interface Props {
11
16
  value?: string;
12
17
  placeholder?: string;
@@ -14,18 +19,61 @@ export interface Props {
14
19
  onChange?: React.ChangeEventHandler<HTMLInputElement>;
15
20
  }
16
21
 
17
- function FormTextInput({ value, placeholder, password, onChange }: Props) {
22
+ function FormTextInput({
23
+ isRequired,
24
+ value,
25
+ placeholder,
26
+ password,
27
+ onChange,
28
+ paramName,
29
+ }: Props) {
18
30
  placeholder = placeholder?.split("\n")[0];
31
+
32
+ const {
33
+ register,
34
+ formState: { errors },
35
+ } = useFormContext();
36
+
37
+ const showErrorMessage = errors?.[paramName]?.message;
38
+
19
39
  return (
20
- <input
21
- className="openapi-demo__input"
22
- type={password ? "password" : "text"}
23
- placeholder={placeholder}
24
- title={placeholder}
25
- value={value}
26
- onChange={onChange}
27
- autoComplete="off"
28
- />
40
+ <>
41
+ {paramName ? (
42
+ <input
43
+ {...register(paramName, {
44
+ required: isRequired ? "This field is required" : false,
45
+ })}
46
+ className={clsx("openapi-demo__form-item-input", {
47
+ error: showErrorMessage,
48
+ })}
49
+ type={password ? "password" : "text"}
50
+ placeholder={placeholder}
51
+ title={placeholder}
52
+ value={value}
53
+ onChange={onChange}
54
+ autoComplete="off"
55
+ />
56
+ ) : (
57
+ <input
58
+ className="openapi-demo__form-item-input"
59
+ type={password ? "password" : "text"}
60
+ placeholder={placeholder}
61
+ title={placeholder}
62
+ value={value}
63
+ onChange={onChange}
64
+ autoComplete="off"
65
+ />
66
+ )}
67
+ {showErrorMessage && (
68
+ <ErrorMessage
69
+ errors={errors}
70
+ name={paramName}
71
+ render={({ message }) => (
72
+ <div className="openapi-demo__input-error">{message}</div>
73
+ )}
74
+ />
75
+ )}
76
+ </>
29
77
  );
30
78
  }
31
79
 
@@ -9,29 +9,31 @@ import React, { useEffect, useState } from "react";
9
9
 
10
10
  import { usePrismTheme } from "@docusaurus/theme-common";
11
11
  import useIsBrowser from "@docusaurus/useIsBrowser";
12
+ import { ErrorMessage } from "@hookform/error-message";
12
13
  import { setStringRawBody } from "@theme/ApiDemoPanel/Body/slice";
14
+ import clsx from "clsx";
15
+ import { Controller, useFormContext } from "react-hook-form";
13
16
  import { LiveProvider, LiveEditor, withLive } from "react-live";
14
17
 
15
- function Live({ onEdit }: any) {
18
+ function Live({ onEdit, showErrors }: any) {
16
19
  const isBrowser = useIsBrowser();
17
20
  const [editorDisabled, setEditorDisabled] = useState(false);
18
21
 
19
- // TODO: Temporary solution for disabling tab key
20
- const handleKeydown = (event: React.KeyboardEvent) => {
21
- if (event.key === "Tab") {
22
- event.preventDefault();
23
- setEditorDisabled(true);
24
- }
25
- };
26
-
27
22
  return (
28
- <div onClick={() => setEditorDisabled(false)}>
23
+ <div
24
+ onClick={() => setEditorDisabled(false)}
25
+ onBlur={() => setEditorDisabled(true)}
26
+ >
29
27
  <LiveEditor
30
28
  key={String(isBrowser)}
31
- className="openapi-demo__playground-editor"
29
+ className={clsx({
30
+ "openapi-demo__playground-editor": true,
31
+ "openapi-demo__form-item-input": showErrors,
32
+ error: showErrors,
33
+ })}
32
34
  onChange={onEdit}
33
35
  disabled={editorDisabled}
34
- onKeyDown={handleKeydown}
36
+ tabMode="focus"
35
37
  />
36
38
  </div>
37
39
  );
@@ -45,6 +47,7 @@ function App({
45
47
  value,
46
48
  language,
47
49
  action,
50
+ required: isRequired,
48
51
  ...props
49
52
  }: any): JSX.Element {
50
53
  const prismTheme = usePrismTheme();
@@ -54,8 +57,24 @@ function App({
54
57
  action(setStringRawBody(code));
55
58
  }, [action, code]);
56
59
 
60
+ const {
61
+ control,
62
+ formState: { errors },
63
+ } = useFormContext();
64
+
65
+ const showErrorMessage = errors?.requestBody;
66
+
67
+ const handleChange = (snippet: string, onChange: any) => {
68
+ setCode(snippet);
69
+ onChange(snippet);
70
+ };
71
+
57
72
  return (
58
- <div className="openapi-demo__playground-container">
73
+ <div
74
+ className={clsx({
75
+ "openapi-demo__playground-container": true,
76
+ })}
77
+ >
59
78
  <LiveProvider
60
79
  code={children.replace(/\n$/, "")}
61
80
  transformCode={transformCode ?? ((code) => `${code};`)}
@@ -63,7 +82,27 @@ function App({
63
82
  language={language}
64
83
  {...props}
65
84
  >
66
- <LiveComponent onEdit={setCode} />
85
+ <Controller
86
+ control={control}
87
+ rules={{ required: isRequired ? "This field is required" : false }}
88
+ name="requestBody"
89
+ render={({ field: { onChange, name } }) => (
90
+ <LiveComponent
91
+ onEdit={(e: any) => handleChange(e, onChange)}
92
+ name={name}
93
+ showErrors={showErrorMessage}
94
+ />
95
+ )}
96
+ />
97
+ {showErrorMessage && (
98
+ <ErrorMessage
99
+ errors={errors}
100
+ name="requestBody"
101
+ render={({ message }) => (
102
+ <div className="openapi-demo__input-error">{message}</div>
103
+ )}
104
+ />
105
+ )}
67
106
  </LiveProvider>
68
107
  </div>
69
108
  );