@gitbook/react-openapi 1.2.1 → 1.3.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 (83) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/OpenAPICodeSample.jsx +7 -4
  3. package/dist/OpenAPIDisclosure.d.ts +1 -0
  4. package/dist/OpenAPIDisclosure.jsx +6 -3
  5. package/dist/OpenAPIDisclosureGroup.jsx +16 -15
  6. package/dist/OpenAPIRequestBody.jsx +7 -2
  7. package/dist/OpenAPIRequestBodyHeaderType.d.ts +8 -0
  8. package/dist/OpenAPIRequestBodyHeaderType.jsx +25 -0
  9. package/dist/OpenAPIResponse.d.ts +1 -1
  10. package/dist/OpenAPIResponse.jsx +20 -4
  11. package/dist/OpenAPIResponseExample.jsx +15 -3
  12. package/dist/OpenAPIResponses.jsx +6 -1
  13. package/dist/OpenAPISchema.d.ts +9 -2
  14. package/dist/OpenAPISchema.jsx +87 -91
  15. package/dist/OpenAPISchemaName.d.ts +1 -1
  16. package/dist/OpenAPISchemaName.jsx +5 -5
  17. package/dist/OpenAPISecurities.jsx +59 -1
  18. package/dist/OpenAPISelect.jsx +1 -0
  19. package/dist/OpenAPISpec.jsx +16 -1
  20. package/dist/OpenAPIWebhookExample.jsx +1 -1
  21. package/dist/StaticSection.jsx +1 -1
  22. package/dist/code-samples.js +6 -3
  23. package/dist/generateSchemaExample.js +19 -14
  24. package/dist/getDisclosureLabel.d.ts +7 -0
  25. package/dist/getDisclosureLabel.js +18 -0
  26. package/dist/schemas/OpenAPISchemaItem.d.ts +7 -0
  27. package/dist/schemas/OpenAPISchemaItem.jsx +16 -0
  28. package/dist/schemas/OpenAPISchemas.jsx +3 -9
  29. package/dist/translations/de.d.ts +7 -1
  30. package/dist/translations/de.js +10 -4
  31. package/dist/translations/en.d.ts +7 -1
  32. package/dist/translations/en.js +9 -3
  33. package/dist/translations/es.d.ts +7 -1
  34. package/dist/translations/es.js +10 -4
  35. package/dist/translations/fr.d.ts +7 -1
  36. package/dist/translations/fr.js +11 -5
  37. package/dist/translations/index.d.ts +63 -9
  38. package/dist/translations/ja.d.ts +7 -1
  39. package/dist/translations/ja.js +9 -3
  40. package/dist/translations/nl.d.ts +7 -1
  41. package/dist/translations/nl.js +9 -3
  42. package/dist/translations/no.d.ts +7 -1
  43. package/dist/translations/no.js +10 -4
  44. package/dist/translations/pt-br.d.ts +7 -1
  45. package/dist/translations/pt-br.js +10 -4
  46. package/dist/translations/zh.d.ts +7 -1
  47. package/dist/translations/zh.js +10 -4
  48. package/dist/tsconfig.build.tsbuildinfo +1 -1
  49. package/dist/utils.d.ts +1 -0
  50. package/dist/utils.js +38 -0
  51. package/package.json +2 -2
  52. package/src/OpenAPICodeSample.tsx +7 -6
  53. package/src/OpenAPIDisclosure.tsx +7 -3
  54. package/src/OpenAPIDisclosureGroup.tsx +49 -48
  55. package/src/OpenAPIRequestBody.tsx +11 -2
  56. package/src/OpenAPIRequestBodyHeaderType.tsx +36 -0
  57. package/src/OpenAPIResponse.tsx +37 -5
  58. package/src/OpenAPIResponseExample.tsx +46 -35
  59. package/src/OpenAPIResponses.tsx +4 -4
  60. package/src/OpenAPISchema.tsx +157 -130
  61. package/src/OpenAPISchemaName.tsx +10 -8
  62. package/src/OpenAPISecurities.tsx +111 -7
  63. package/src/OpenAPISelect.tsx +1 -1
  64. package/src/OpenAPISpec.tsx +21 -1
  65. package/src/OpenAPIWebhookExample.tsx +2 -2
  66. package/src/StaticSection.tsx +1 -1
  67. package/src/code-samples.test.ts +3 -2
  68. package/src/code-samples.ts +19 -12
  69. package/src/generateSchemaExample.test.ts +20 -0
  70. package/src/generateSchemaExample.ts +9 -1
  71. package/src/getDisclosureLabel.ts +25 -0
  72. package/src/schemas/OpenAPISchemaItem.tsx +34 -0
  73. package/src/schemas/OpenAPISchemas.tsx +7 -13
  74. package/src/translations/de.ts +10 -4
  75. package/src/translations/en.ts +9 -3
  76. package/src/translations/es.ts +10 -4
  77. package/src/translations/fr.ts +11 -5
  78. package/src/translations/ja.ts +9 -3
  79. package/src/translations/nl.ts +9 -3
  80. package/src/translations/no.ts +10 -4
  81. package/src/translations/pt-br.ts +10 -4
  82. package/src/translations/zh.ts +10 -4
  83. package/src/utils.ts +37 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @gitbook/react-openapi
2
2
 
3
+ ## 1.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 957afd9: Add authorization header for OAuth2
8
+ - 7a00880: Improve support for OAuth2 security type
9
+ - a0c06a7: Indent JSON python code sample
10
+ - b403962: Handle nullish OpenAPI mediaTypeObject
11
+ - 1e013cd: Optional label in OpenAPI x-codeSamples
12
+ - 4c9a9d0: Handle nested deprecated properties in generateSchemaExample
13
+ - 40df91a: Deduplicate path parameters from OpenAPI spec
14
+ - 2350baa: Support for OpenAPI Array request body
15
+ - Updated dependencies [1e013cd]
16
+ - Updated dependencies [4f5cbfe]
17
+ - @gitbook/openapi-parser@2.1.5
18
+
19
+ ## 1.3.0
20
+
21
+ ### Minor Changes
22
+
23
+ - 326e28e: Design tweaks to code blocks and OpenAPI pages
24
+
25
+ ### Patch Changes
26
+
27
+ - 42ca7e1: Fix openapi CR preview
28
+ - 5e975ab: Fix code highlighting for HTTP
29
+ - 580101d: Fix schemas disclosure label causing client error
30
+ - 20ebecb: Missing top-level required OpenAPI alternatives
31
+ - 80cb52a: Handle OpenAPI alternatives from schema.items
32
+ - cb5598d: Handle invalid OpenAPI Responses
33
+ - c6637b0: Use default value if string number or boolean in generateSchemaExample
34
+ - a3ec264: Fix Python code sample "null vs None"
35
+ - Updated dependencies [d00dc8c]
36
+ - @gitbook/openapi-parser@2.1.4
37
+
3
38
  ## 1.2.1
4
39
 
5
40
  ### Patch Changes
@@ -164,13 +164,11 @@ function getCustomCodeSamples(props) {
164
164
  if (customSamples && Array.isArray(customSamples)) {
165
165
  customCodeSamples = customSamples
166
166
  .filter(function (sample) {
167
- return (typeof sample.label === 'string' &&
168
- typeof sample.source === 'string' &&
169
- typeof sample.lang === 'string');
167
+ return typeof sample.source === 'string' && typeof sample.lang === 'string';
170
168
  })
171
169
  .map(function (sample, index) { return ({
172
170
  key: "custom-sample-".concat(sample.lang, "-").concat(index),
173
- label: sample.label,
171
+ label: sample.label || sample.lang,
174
172
  body: context.renderCodeBlock({
175
173
  code: sample.source,
176
174
  syntax: sample.lang,
@@ -214,6 +212,11 @@ function getSecurityHeaders(securities) {
214
212
  _a[name_1] = 'YOUR_API_KEY',
215
213
  _a;
216
214
  }
215
+ case 'oauth2': {
216
+ return {
217
+ Authorization: 'Bearer YOUR_OAUTH2_TOKEN',
218
+ };
219
+ }
217
220
  default: {
218
221
  return {};
219
222
  }
@@ -4,6 +4,7 @@ import type React from 'react';
4
4
  */
5
5
  export declare function OpenAPIDisclosure(props: {
6
6
  icon: React.ReactNode;
7
+ header: React.ReactNode;
7
8
  children: React.ReactNode;
8
9
  label: string | ((isExpanded: boolean) => string);
9
10
  className?: string;
@@ -6,7 +6,7 @@ import { Button, Disclosure, DisclosurePanel } from 'react-aria-components';
6
6
  * Display an interactive OpenAPI disclosure.
7
7
  */
8
8
  export function OpenAPIDisclosure(props) {
9
- var icon = props.icon, children = props.children, label = props.label, className = props.className;
9
+ var icon = props.icon, header = props.header, label = props.label, children = props.children, className = props.className;
10
10
  var _a = useState(false), isExpanded = _a[0], setIsExpanded = _a[1];
11
11
  return (<Disclosure className={clsx('openapi-disclosure', className)} isExpanded={isExpanded} onExpandedChange={setIsExpanded}>
12
12
  <Button slot="trigger" className="openapi-disclosure-trigger" style={function (_a) {
@@ -17,8 +17,11 @@ export function OpenAPIDisclosure(props) {
17
17
  : 'none',
18
18
  });
19
19
  }}>
20
- {icon}
21
- <span>{typeof label === 'function' ? label(isExpanded) : label}</span>
20
+ {header}
21
+ <div className="openapi-disclosure-trigger-label">
22
+ <span>{typeof label === 'function' ? label(isExpanded) : label}</span>
23
+ {icon}
24
+ </div>
22
25
  </Button>
23
26
  <DisclosurePanel className="openapi-disclosure-panel">
24
27
  {isExpanded ? children : null}
@@ -50,29 +50,30 @@ function DisclosureItem(props) {
50
50
  var store = useSelectState(selectStateKey, defaultTab);
51
51
  var selectedTab = ((_d = group.tabs) === null || _d === void 0 ? void 0 : _d.find(function (tab) { return tab.key === store.key; })) || ((_e = group.tabs) === null || _e === void 0 ? void 0 : _e[0]);
52
52
  return (<div className="openapi-disclosure-group" aria-expanded={state.isExpanded}>
53
- <div className="openapi-disclosure-group-header">
54
- <button slot="trigger" ref={triggerRef} {...mergeProps(buttonProps, focusProps)} disabled={isDisabled} style={{
53
+ <div slot="trigger" ref={triggerRef} {...mergeProps(buttonProps, focusProps)} aria-disabled={isDisabled} style={{
55
54
  outline: isFocusVisible
56
55
  ? '2px solid rgb(var(--primary-color-500)/0.4)'
57
56
  : 'none',
58
57
  }} className="openapi-disclosure-group-trigger">
59
- <div className="openapi-disclosure-group-icon">
60
- {icon || (<svg viewBox="0 0 24 24" className="openapi-disclosure-group-icon">
61
- <path d="m8.25 4.5 7.5 7.5-7.5 7.5"/>
62
- </svg>)}
63
- </div>
58
+ <div className="openapi-disclosure-group-icon">
59
+ {icon || (<svg viewBox="0 0 24 24" className="openapi-disclosure-group-icon">
60
+ <path d="m8.25 4.5 7.5 7.5-7.5 7.5"/>
61
+ </svg>)}
62
+ </div>
64
63
 
64
+ <div className="openapi-disclosure-group-label">
65
65
  {group.label}
66
- </button>
67
- {group.tabs ? (<div className="openapi-disclosure-group-mediatype" onClick={function (e) { return e.stopPropagation(); }}>
68
- {((_f = group.tabs) === null || _f === void 0 ? void 0 : _f.length) > 1 ? (<OpenAPISelect icon={selectIcon} stateKey={selectStateKey} onSelectionChange={function () {
66
+
67
+ {group.tabs ? (<div className="openapi-disclosure-group-mediatype" onClick={function (e) { return e.stopPropagation(); }}>
68
+ {((_f = group.tabs) === null || _f === void 0 ? void 0 : _f.length) > 1 ? (<OpenAPISelect icon={selectIcon} stateKey={selectStateKey} onSelectionChange={function () {
69
69
  state.expand();
70
70
  }} items={group.tabs} placement="bottom end">
71
- {group.tabs.map(function (tab) { return (<OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
72
- {tab.label}
73
- </OpenAPISelectItem>); })}
74
- </OpenAPISelect>) : ((_g = group.tabs[0]) === null || _g === void 0 ? void 0 : _g.label) ? (<span>{group.tabs[0].label}</span>) : null}
75
- </div>) : null}
71
+ {group.tabs.map(function (tab) { return (<OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
72
+ {tab.label}
73
+ </OpenAPISelectItem>); })}
74
+ </OpenAPISelect>) : ((_g = group.tabs[0]) === null || _g === void 0 ? void 0 : _g.label) ? (<span>{group.tabs[0].label}</span>) : null}
75
+ </div>) : null}
76
+ </div>
76
77
  </div>
77
78
 
78
79
  {state.isExpanded && selectedTab && (<div className="openapi-disclosure-group-panel" ref={panelRef} {...panelProps}>
@@ -1,4 +1,5 @@
1
1
  import { InteractiveSection } from './InteractiveSection';
2
+ import { OpenAPIRequestBodyHeaderType } from './OpenAPIRequestBodyHeaderType';
2
3
  import { OpenAPIRootSchema } from './OpenAPISchemaServer';
3
4
  import { t } from './translate';
4
5
  import { checkIsReference, createStateKey } from './utils';
@@ -11,13 +12,17 @@ export function OpenAPIRequestBody(props) {
11
12
  if (checkIsReference(requestBody)) {
12
13
  return null;
13
14
  }
14
- return (<InteractiveSection header={t(context.translation, 'name' in data ? 'payload' : 'body')} className="openapi-requestbody" stateKey={createStateKey('request-body-media-type', context.blockKey)} selectIcon={context.icons.chevronDown} tabs={Object.entries((_a = requestBody.content) !== null && _a !== void 0 ? _a : {}).map(function (_a) {
15
+ var stateKey = createStateKey('request-body-media-type', context.blockKey);
16
+ return (<InteractiveSection header={<>
17
+ <span>{t(context.translation, 'name' in data ? 'payload' : 'body')}</span>
18
+ <OpenAPIRequestBodyHeaderType requestBody={requestBody} stateKey={stateKey}/>
19
+ </>} className="openapi-requestbody" stateKey={stateKey} selectIcon={context.icons.chevronDown} tabs={Object.entries((_a = requestBody.content) !== null && _a !== void 0 ? _a : {}).map(function (_a) {
15
20
  var _b;
16
21
  var contentType = _a[0], mediaTypeObject = _a[1];
17
22
  return {
18
23
  key: contentType,
19
24
  label: contentType,
20
- body: (<OpenAPIRootSchema schema={(_b = mediaTypeObject.schema) !== null && _b !== void 0 ? _b : {}} context={context}/>),
25
+ body: (<OpenAPIRootSchema schema={(_b = mediaTypeObject.schema) !== null && _b !== void 0 ? _b : {}} context={context} key={contentType}/>),
21
26
  };
22
27
  })}/>);
23
28
  }
@@ -0,0 +1,8 @@
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ /**
3
+ * Display the type of a request body. It only displays the type if the selected content is an array.
4
+ */
5
+ export declare function OpenAPIRequestBodyHeaderType(props: {
6
+ requestBody: OpenAPIV3.RequestBodyObject;
7
+ stateKey: string;
8
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+ import { useSelectState } from './OpenAPISelect';
3
+ import { getSchemaTitle } from './utils';
4
+ /**
5
+ * Display the type of a request body. It only displays the type if the selected content is an array.
6
+ */
7
+ export function OpenAPIRequestBodyHeaderType(props) {
8
+ var _a, _b, _c;
9
+ var requestBody = props.requestBody, stateKey = props.stateKey;
10
+ var content = (_a = requestBody.content) !== null && _a !== void 0 ? _a : {};
11
+ var state = useSelectState(stateKey, Object.keys(content)[0]);
12
+ var selectedContentMediaType = (_b = Object.entries(content).find(function (_a) {
13
+ var contentType = _a[0];
14
+ return contentType === state.key;
15
+ })) === null || _b === void 0 ? void 0 : _b[1];
16
+ // If the selected content is not an array, we don't display the type
17
+ if (!selectedContentMediaType ||
18
+ !((_c = selectedContentMediaType.schema) === null || _c === void 0 ? void 0 : _c.type) ||
19
+ selectedContentMediaType.schema.type !== 'array') {
20
+ return null;
21
+ }
22
+ return (<span className="openapi-requestbody-header-type">
23
+ {"".concat(getSchemaTitle(selectedContentMediaType.schema))}
24
+ </span>);
25
+ }
@@ -5,6 +5,6 @@ import type { OpenAPIClientContext } from './context';
5
5
  */
6
6
  export declare function OpenAPIResponse(props: {
7
7
  response: OpenAPIV3.ResponseObject;
8
- mediaType: OpenAPIV3.MediaTypeObject;
8
+ mediaType: OpenAPIV3.MediaTypeObject | null;
9
9
  context: OpenAPIClientContext;
10
10
  }): import("react").JSX.Element | null;
@@ -10,7 +10,9 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { OpenAPIDisclosure } from './OpenAPIDisclosure';
13
+ import { OpenAPISchemaPresentation } from './OpenAPISchema';
13
14
  import { OpenAPISchemaProperties } from './OpenAPISchemaServer';
15
+ import { tString } from './translate';
14
16
  import { parameterToProperty, resolveDescription } from './utils';
15
17
  /**
16
18
  * Display an interactive response body.
@@ -22,20 +24,34 @@ export function OpenAPIResponse(props) {
22
24
  var name = _a[0], header = _a[1];
23
25
  return [name, header !== null && header !== void 0 ? header : {}];
24
26
  });
25
- var content = Object.entries((_b = mediaType.schema) !== null && _b !== void 0 ? _b : {});
27
+ var content = Object.entries((_b = mediaType === null || mediaType === void 0 ? void 0 : mediaType.schema) !== null && _b !== void 0 ? _b : {});
26
28
  var description = resolveDescription(response);
27
29
  if (content.length === 0 && !description && headers.length === 0) {
28
30
  return null;
29
31
  }
30
32
  return (<div className="openapi-response-body">
31
- {headers.length > 0 ? (<OpenAPIDisclosure icon={context.icons.plus} label="Headers">
33
+ {headers.length > 0 ? (<OpenAPIDisclosure header={<OpenAPISchemaPresentation context={context} property={{
34
+ propertyName: tString(context.translation, 'headers'),
35
+ schema: {
36
+ type: 'object',
37
+ },
38
+ required: null,
39
+ }}/>} icon={context.icons.plus} label={function (isExpanded) {
40
+ return tString(context.translation, isExpanded ? 'hide' : 'show', tString(context.translation, headers.length === 1 ? 'header' : 'headers'));
41
+ }}>
32
42
  <OpenAPISchemaProperties properties={headers.map(function (_a) {
33
43
  var name = _a[0], header = _a[1];
34
44
  return parameterToProperty(__assign({ name: name }, header));
35
45
  })} context={context}/>
36
46
  </OpenAPIDisclosure>) : null}
37
- {mediaType.schema && (<div className="openapi-responsebody">
38
- <OpenAPISchemaProperties id={"response-".concat(context.blockKey)} properties={[{ schema: mediaType.schema }]} context={context}/>
47
+ {(mediaType === null || mediaType === void 0 ? void 0 : mediaType.schema) && (<div className="openapi-responsebody">
48
+ <OpenAPISchemaProperties id={"response-".concat(context.blockKey)} properties={[
49
+ {
50
+ schema: mediaType.schema,
51
+ propertyName: tString(context.translation, 'response'),
52
+ required: null,
53
+ },
54
+ ]} context={context}/>
39
55
  </div>)}
40
56
  </div>);
41
57
  }
@@ -4,8 +4,8 @@ import { OpenAPIMediaTypeContent } from './OpenAPIMediaType';
4
4
  import { OpenAPIResponseExampleContent } from './OpenAPIResponseExampleContent';
5
5
  import { getOpenAPIClientContext } from './context';
6
6
  import { getExampleFromReference, getExamples } from './util/example';
7
- import { createStateKey, getStatusCodeDefaultLabel } from './utils';
8
- import { checkIsReference, resolveDescription } from './utils';
7
+ import { createStateKey, getStatusCodeDefaultLabel, resolveDescription } from './utils';
8
+ import { checkIsReference } from './utils';
9
9
  /**
10
10
  * Display an example of the response content.
11
11
  */
@@ -34,7 +34,12 @@ export function OpenAPIResponseExample(props) {
34
34
  }
35
35
  return Number(a) - Number(b);
36
36
  });
37
- var tabs = responses.map(function (_a) {
37
+ var tabs = responses
38
+ .filter(function (_a) {
39
+ var _ = _a[0], responseObject = _a[1];
40
+ return responseObject && typeof responseObject === 'object';
41
+ })
42
+ .map(function (_a) {
38
43
  var key = _a[0], responseObject = _a[1];
39
44
  var description = resolveDescription(responseObject);
40
45
  var label = description ? (<Markdown source={description}/>) : (getStatusCodeDefaultLabel(key, context));
@@ -75,6 +80,13 @@ function OpenAPIResponse(props) {
75
80
  }
76
81
  var tabs = entries.map(function (entry) {
77
82
  var mediaType = entry[0], mediaTypeObject = entry[1];
83
+ if (!mediaTypeObject) {
84
+ return {
85
+ key: mediaType,
86
+ label: mediaType,
87
+ body: <OpenAPIEmptyExample context={context}/>,
88
+ };
89
+ }
78
90
  return {
79
91
  key: mediaType,
80
92
  label: mediaType,
@@ -13,7 +13,12 @@ import { createStateKey, getStatusCodeClassName, getStatusCodeDefaultLabel } fro
13
13
  export function OpenAPIResponses(props) {
14
14
  var _a;
15
15
  var responses = props.responses, context = props.context;
16
- var groups = Object.entries(responses).map(function (_a) {
16
+ var groups = Object.entries(responses)
17
+ .filter(function (_a) {
18
+ var _ = _a[0], response = _a[1];
19
+ return response && typeof response === 'object';
20
+ })
21
+ .map(function (_a) {
17
22
  var statusCode = _a[0], response = _a[1];
18
23
  var tabs = (function () {
19
24
  var _a;
@@ -1,8 +1,8 @@
1
1
  import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
2
  import type { OpenAPIClientContext } from './context';
3
3
  export interface OpenAPISchemaPropertyEntry {
4
- propertyName?: string | undefined;
5
- required?: boolean | undefined;
4
+ propertyName?: string;
5
+ required?: boolean | null;
6
6
  schema: OpenAPIV3.SchemaObject;
7
7
  }
8
8
  export declare function OpenAPISchemaPropertiesFromServer(props: {
@@ -14,6 +14,13 @@ export declare function OpenAPIRootSchemaFromServer(props: {
14
14
  schema: string;
15
15
  context: OpenAPIClientContext;
16
16
  }): import("react").JSX.Element;
17
+ /**
18
+ * Render the top row of a schema. e.g: name, type, and required status.
19
+ */
20
+ export declare function OpenAPISchemaPresentation(props: {
21
+ property: OpenAPISchemaPropertyEntry;
22
+ context: OpenAPIClientContext;
23
+ }): import("react").JSX.Element;
17
24
  /**
18
25
  * Get the alternatives to display for a schema.
19
26
  */
@@ -10,6 +10,17 @@ var __assign = (this && this.__assign) || function () {
10
10
  };
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
+ var __rest = (this && this.__rest) || function (s, e) {
14
+ var t = {};
15
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
+ t[p] = s[p];
17
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
+ t[p[i]] = s[p[i]];
21
+ }
22
+ return t;
23
+ };
13
24
  var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
14
25
  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
15
26
  if (ar || !(i in from)) {
@@ -26,41 +37,50 @@ import { OpenAPICopyButton } from './OpenAPICopyButton';
26
37
  import { OpenAPIDisclosure } from './OpenAPIDisclosure';
27
38
  import { OpenAPISchemaName } from './OpenAPISchemaName';
28
39
  import { retrocycle } from './decycle';
40
+ import { getDisclosureLabel } from './getDisclosureLabel';
29
41
  import { stringifyOpenAPI } from './stringifyOpenAPI';
30
42
  import { tString } from './translate';
31
- import { checkIsReference, resolveDescription, resolveFirstExample } from './utils';
43
+ import { checkIsReference, getSchemaTitle, resolveDescription, resolveFirstExample } from './utils';
32
44
  /**
33
45
  * Render a property of an OpenAPI schema.
34
46
  */
35
47
  function OpenAPISchemaProperty(props) {
36
- var parentCircularRefs = props.circularRefs, context = props.context, className = props.className, property = props.property;
48
+ var parentCircularRefs = props.circularRefs, context = props.context, className = props.className, property = props.property, rest = __rest(props, ["circularRefs", "context", "className", "property"]);
37
49
  var schema = property.schema;
38
50
  var id = useId();
39
- return (<div id={id} className={clsx('openapi-schema', className)}>
40
- <OpenAPISchemaPresentation context={context} property={property}/>
41
- {(function () {
42
- var circularRefId = parentCircularRefs.get(schema);
43
- // Avoid recursing infinitely, and instead render a link to the parent schema
44
- if (circularRefId) {
45
- return <OpenAPISchemaCircularRef id={circularRefId} schema={schema}/>;
46
- }
47
- var circularRefs = new Map(parentCircularRefs);
48
- circularRefs.set(schema, id);
49
- var properties = getSchemaProperties(schema);
50
- if (properties === null || properties === void 0 ? void 0 : properties.length) {
51
- return (<OpenAPIDisclosure icon={context.icons.plus} label={function (isExpanded) {
52
- return getDisclosureLabel({ schema: schema, isExpanded: isExpanded, context: context });
53
- }}>
54
- <OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context}/>
55
- </OpenAPIDisclosure>);
56
- }
57
- var ancestors = new Set(circularRefs.keys());
58
- var alternatives = getSchemaAlternatives(schema, ancestors);
59
- if (alternatives) {
60
- return alternatives.map(function (schema, index) { return (<OpenAPISchemaAlternative key={index} schema={schema} circularRefs={circularRefs} context={context}/>); });
61
- }
62
- return null;
63
- })()}
51
+ var circularRefId = parentCircularRefs.get(schema);
52
+ // Avoid recursing infinitely, and instead render a link to the parent schema
53
+ if (circularRefId) {
54
+ return <OpenAPISchemaCircularRef id={circularRefId} schema={schema}/>;
55
+ }
56
+ var circularRefs = new Map(parentCircularRefs);
57
+ circularRefs.set(schema, id);
58
+ var properties = getSchemaProperties(schema);
59
+ var ancestors = new Set(circularRefs.keys());
60
+ var alternatives = getSchemaAlternatives(schema, ancestors);
61
+ var header = <OpenAPISchemaPresentation context={context} property={property}/>;
62
+ var content = (function () {
63
+ if (properties === null || properties === void 0 ? void 0 : properties.length) {
64
+ return (<OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context}/>);
65
+ }
66
+ if (alternatives) {
67
+ return (<div className="openapi-schema-alternatives">
68
+ {alternatives.map(function (alternativeSchema, index) { return (<div key={index} className="openapi-schema-alternative">
69
+ <OpenAPISchemaAlternative schema={alternativeSchema} circularRefs={circularRefs} context={context}/>
70
+ {index < alternatives.length - 1 ? (<OpenAPISchemaAlternativeSeparator schema={schema} context={context}/>) : null}
71
+ </div>); })}
72
+ </div>);
73
+ }
74
+ return null;
75
+ })();
76
+ if (properties === null || properties === void 0 ? void 0 : properties.length) {
77
+ return (<OpenAPIDisclosure icon={context.icons.plus} className={clsx('openapi-schema', className)} header={header} label={function (isExpanded) { return getDisclosureLabel({ schema: schema, isExpanded: isExpanded, context: context }); }} {...rest}>
78
+ {content}
79
+ </OpenAPIDisclosure>);
80
+ }
81
+ return (<div id={id} {...rest} className={clsx('openapi-schema', className)}>
82
+ {header}
83
+ {content}
64
84
  </div>);
65
85
  }
66
86
  /**
@@ -70,7 +90,7 @@ function OpenAPISchemaProperties(props) {
70
90
  var id = props.id, properties = props.properties, _a = props.circularRefs, circularRefs = _a === void 0 ? new Map() : _a, context = props.context;
71
91
  return (<div id={id} className="openapi-schema-properties">
72
92
  {properties.map(function (property, index) {
73
- return (<OpenAPISchemaProperty key={index} circularRefs={circularRefs} property={property} context={context}/>);
93
+ return (<OpenAPISchemaProperty key={index} circularRefs={circularRefs} property={property} context={context} style={{ animationDelay: "".concat(index * 0.02, "s") }}/>);
74
94
  })}
75
95
  </div>);
76
96
  }
@@ -105,14 +125,24 @@ export function OpenAPIRootSchemaFromServer(props) {
105
125
  */
106
126
  function OpenAPISchemaAlternative(props) {
107
127
  var schema = props.schema, circularRefs = props.circularRefs, context = props.context;
108
- var description = resolveDescription(schema);
109
128
  var properties = getSchemaProperties(schema);
110
- return (<>
111
- {description ? (<Markdown source={description} className="openapi-schema-description"/>) : null}
112
- <OpenAPIDisclosure icon={context.icons.plus} label={function (isExpanded) { return getDisclosureLabel({ schema: schema, isExpanded: isExpanded, context: context }); }}>
113
- {(properties === null || properties === void 0 ? void 0 : properties.length) ? (<OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context}/>) : (<OpenAPISchemaProperty property={{ schema: schema }} circularRefs={circularRefs} context={context}/>)}
114
- </OpenAPIDisclosure>
115
- </>);
129
+ return (properties === null || properties === void 0 ? void 0 : properties.length) ? (<OpenAPIDisclosure icon={context.icons.plus} header={<OpenAPISchemaPresentation property={{ schema: schema }} context={context}/>} label={function (isExpanded) { return getDisclosureLabel({ schema: schema, isExpanded: isExpanded, context: context }); }}>
130
+ <OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context}/>
131
+ </OpenAPIDisclosure>) : (<OpenAPISchemaProperty property={{ schema: schema }} circularRefs={circularRefs} context={context}/>);
132
+ }
133
+ function OpenAPISchemaAlternativeSeparator(props) {
134
+ var _a, _b, _c;
135
+ var schema = props.schema, context = props.context;
136
+ var anyOf = schema.anyOf || ((_a = schema.items) === null || _a === void 0 ? void 0 : _a.anyOf);
137
+ var oneOf = schema.oneOf || ((_b = schema.items) === null || _b === void 0 ? void 0 : _b.oneOf);
138
+ var allOf = schema.allOf || ((_c = schema.items) === null || _c === void 0 ? void 0 : _c.allOf);
139
+ if (!anyOf && !oneOf && !allOf) {
140
+ return null;
141
+ }
142
+ return (<span className="openapi-schema-alternative-separator">
143
+ {(anyOf || oneOf) && tString(context.translation, 'or')}
144
+ {allOf && tString(context.translation, 'and')}
145
+ </span>);
116
146
  }
117
147
  /**
118
148
  * Render a circular reference to a schema.
@@ -161,7 +191,7 @@ function OpenAPISchemaEnum(props) {
161
191
  return null;
162
192
  }
163
193
  return (<span className="openapi-schema-enum">
164
- Available options:{' '}
194
+ {tString(context.translation, 'possible_values')}:{' '}
165
195
  {enumValues.map(function (item, index) { return (<span key={index} className="openapi-schema-enum-value">
166
196
  <OpenAPICopyButton value={item.value} label={item.description} withTooltip={!!item.description} context={context}>
167
197
  <code>{"".concat(item.value)}</code>
@@ -172,7 +202,7 @@ function OpenAPISchemaEnum(props) {
172
202
  /**
173
203
  * Render the top row of a schema. e.g: name, type, and required status.
174
204
  */
175
- function OpenAPISchemaPresentation(props) {
205
+ export function OpenAPISchemaPresentation(props) {
176
206
  var _a = props.property, schema = _a.schema, propertyName = _a.propertyName, required = _a.required, context = props.context;
177
207
  var description = resolveDescription(schema);
178
208
  var example = resolveFirstExample(schema);
@@ -255,6 +285,11 @@ function getSchemaProperties(schema) {
255
285
  */
256
286
  export function getSchemaAlternatives(schema, ancestors) {
257
287
  if (ancestors === void 0) { ancestors = new Set(); }
288
+ // Search for alternatives in the items property if it exists
289
+ if (schema.items &&
290
+ ('oneOf' in schema.items || 'allOf' in schema.items || 'anyOf' in schema.items)) {
291
+ return getSchemaAlternatives(schema.items, ancestors);
292
+ }
258
293
  var alternatives = (function () {
259
294
  if (schema.anyOf) {
260
295
  return ['anyOf', schema.anyOf];
@@ -332,6 +367,8 @@ function mergeAlternatives(alternativeType, schemasOrRefs) {
332
367
  }
333
368
  }
334
369
  function flattenAlternatives(alternativeType, schemasOrRefs, ancestors) {
370
+ // Get the parent schema's required fields from the most recent ancestor
371
+ var latestAncestor = Array.from(ancestors).pop();
335
372
  return schemasOrRefs.reduce(function (acc, schemaOrRef) {
336
373
  if (checkIsReference(schemaOrRef)) {
337
374
  return acc;
@@ -339,66 +376,25 @@ function flattenAlternatives(alternativeType, schemasOrRefs, ancestors) {
339
376
  if (schemaOrRef[alternativeType] && !ancestors.has(schemaOrRef)) {
340
377
  var schemas = getSchemaAlternatives(schemaOrRef, ancestors);
341
378
  if (schemas) {
342
- acc.push.apply(acc, schemas);
379
+ acc.push.apply(acc, schemas.map(function (schema) { return (__assign(__assign({}, schema), { required: mergeRequiredFields(schema, latestAncestor) })); }));
343
380
  }
344
381
  return acc;
345
382
  }
346
- acc.push(schemaOrRef);
383
+ // For direct schemas, handle required fields
384
+ var schema = __assign(__assign({}, schemaOrRef), { required: mergeRequiredFields(schemaOrRef, latestAncestor) });
385
+ acc.push(schema);
347
386
  return acc;
348
387
  }, []);
349
388
  }
350
- function getSchemaTitle(schema) {
351
- var _a;
352
- // Otherwise try to infer a nice title
353
- var type = 'any';
354
- if (schema.enum || schema['x-enumDescriptions'] || schema['x-gitbook-enum']) {
355
- type = "".concat(schema.type, " \u00B7 enum");
356
- // check array AND schema.items as this is sometimes null despite what the type indicates
357
- }
358
- else if (schema.type === 'array' && !!schema.items) {
359
- type = "".concat(getSchemaTitle(schema.items), "[]");
360
- }
361
- else if (Array.isArray(schema.type)) {
362
- type = schema.type.join(' | ');
363
- }
364
- else if (schema.type || schema.properties) {
365
- type = (_a = schema.type) !== null && _a !== void 0 ? _a : 'object';
366
- if (schema.format) {
367
- type += " \u00B7 ".concat(schema.format);
368
- }
369
- }
370
- if ('anyOf' in schema) {
371
- type = 'any of';
372
- }
373
- else if ('oneOf' in schema) {
374
- type = 'one of';
375
- }
376
- else if ('allOf' in schema) {
377
- type = 'all of';
378
- }
379
- else if ('not' in schema) {
380
- type = 'not';
381
- }
382
- return type;
383
- }
384
- function getDisclosureLabel(props) {
385
- var _a, _b;
386
- var schema = props.schema, isExpanded = props.isExpanded, context = props.context;
387
- var label;
388
- if (schema.type === 'array' && !!schema.items) {
389
- if (schema.items.oneOf) {
390
- label = tString(context.translation, 'available_items').toLowerCase();
391
- }
392
- // Fallback to "child attributes" for enums and objects
393
- else if (schema.items.enum || schema.items.type === 'object') {
394
- label = tString(context.translation, 'child_attributes').toLowerCase();
395
- }
396
- else {
397
- label = (_b = (_a = schema.items.title) !== null && _a !== void 0 ? _a : schema.title) !== null && _b !== void 0 ? _b : getSchemaTitle(schema.items);
398
- }
389
+ /**
390
+ * Merge the required fields of a schema with the required fields of its latest ancestor.
391
+ */
392
+ function mergeRequiredFields(schemaOrRef, latestAncestor) {
393
+ if (!schemaOrRef.required && !(latestAncestor === null || latestAncestor === void 0 ? void 0 : latestAncestor.required)) {
394
+ return undefined;
399
395
  }
400
- else {
401
- label = schema.title || tString(context.translation, 'child_attributes').toLowerCase();
396
+ if (checkIsReference(schemaOrRef)) {
397
+ return latestAncestor === null || latestAncestor === void 0 ? void 0 : latestAncestor.required;
402
398
  }
403
- return "".concat(isExpanded ? tString(context.translation, 'hide') : tString(context.translation, 'show'), " ").concat(label);
399
+ return Array.from(new Set(__spreadArray(__spreadArray([], ((latestAncestor === null || latestAncestor === void 0 ? void 0 : latestAncestor.required) || []), true), (schemaOrRef.required || []), true)));
404
400
  }
@@ -4,7 +4,7 @@ import type { OpenAPIClientContext } from './context';
4
4
  interface OpenAPISchemaNameProps {
5
5
  schema?: OpenAPIV3.SchemaObject;
6
6
  propertyName?: string | React.JSX.Element;
7
- required?: boolean;
7
+ required?: boolean | null;
8
8
  type?: string;
9
9
  context: OpenAPIClientContext;
10
10
  }