@gitbook/react-openapi 1.1.5 → 1.1.7

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 (59) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/InteractiveSection.d.ts +0 -2
  3. package/dist/InteractiveSection.jsx +3 -4
  4. package/dist/OpenAPICodeSample.d.ts +9 -0
  5. package/dist/OpenAPICodeSample.jsx +117 -58
  6. package/dist/OpenAPICodeSampleInteractive.d.ts +11 -0
  7. package/dist/OpenAPICodeSampleInteractive.jsx +85 -0
  8. package/dist/OpenAPICopyButton.d.ts +7 -0
  9. package/dist/OpenAPICopyButton.jsx +6 -6
  10. package/dist/OpenAPIOperation.jsx +21 -1
  11. package/dist/OpenAPIPath.jsx +2 -2
  12. package/dist/OpenAPIRequestBody.jsx +1 -1
  13. package/dist/OpenAPIResponse.jsx +1 -1
  14. package/dist/OpenAPIResponses.jsx +2 -2
  15. package/dist/OpenAPISchema.d.ts +5 -14
  16. package/dist/OpenAPISchema.jsx +79 -28
  17. package/dist/OpenAPISchemaName.jsx +8 -6
  18. package/dist/OpenAPISchemaServer.d.ts +12 -0
  19. package/dist/OpenAPISchemaServer.jsx +8 -0
  20. package/dist/OpenAPISpec.d.ts +0 -6
  21. package/dist/OpenAPISpec.jsx +5 -11
  22. package/dist/OpenAPITabs.jsx +3 -11
  23. package/dist/code-samples.d.ts +1 -2
  24. package/dist/code-samples.js +46 -11
  25. package/dist/decycle.d.ts +2 -0
  26. package/dist/decycle.js +70 -0
  27. package/dist/generateSchemaExample.d.ts +31 -2
  28. package/dist/generateSchemaExample.js +307 -24
  29. package/dist/schemas/OpenAPISchemas.jsx +1 -1
  30. package/dist/schemas/resolveOpenAPISchemas.d.ts +2 -6
  31. package/dist/schemas/resolveOpenAPISchemas.js +1 -21
  32. package/dist/tsconfig.build.tsbuildinfo +1 -1
  33. package/dist/types.d.ts +2 -5
  34. package/dist/utils.d.ts +1 -1
  35. package/dist/utils.js +11 -7
  36. package/package.json +3 -3
  37. package/src/InteractiveSection.tsx +2 -6
  38. package/src/OpenAPICodeSample.tsx +187 -78
  39. package/src/OpenAPICodeSampleInteractive.tsx +139 -0
  40. package/src/OpenAPICopyButton.tsx +17 -4
  41. package/src/OpenAPIOperation.tsx +39 -2
  42. package/src/OpenAPIPath.tsx +2 -2
  43. package/src/OpenAPIRequestBody.tsx +1 -1
  44. package/src/OpenAPIResponse.tsx +4 -4
  45. package/src/OpenAPIResponses.tsx +1 -5
  46. package/src/OpenAPISchema.tsx +152 -58
  47. package/src/OpenAPISchemaName.tsx +14 -6
  48. package/src/OpenAPISchemaServer.tsx +34 -0
  49. package/src/OpenAPISpec.tsx +13 -11
  50. package/src/OpenAPITabs.tsx +3 -13
  51. package/src/code-samples.test.ts +69 -1
  52. package/src/code-samples.ts +48 -12
  53. package/src/decycle.ts +68 -0
  54. package/src/generateSchemaExample.ts +412 -25
  55. package/src/resolveOpenAPIOperation.test.ts +6 -6
  56. package/src/schemas/OpenAPISchemas.tsx +1 -1
  57. package/src/schemas/resolveOpenAPISchemas.ts +3 -31
  58. package/src/types.ts +6 -6
  59. package/src/utils.ts +13 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @gitbook/react-openapi
2
2
 
3
+ ## 1.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - bd35348: Fix missing alternative schemas
8
+ - ae78fc5: Fix XML in code sample
9
+ - 7bb37c7: Move filterSelectedOpenAPISchemas to @gitbook/openapi-parser
10
+ - 373183a: Safe parse OpenAPI JSON schema
11
+ - 1505ddb: Fix multiple request examples selector not showing
12
+ - 61db166: Add OpenAPI write-only indicator
13
+ - 5b1e01c: Support for x-stability property
14
+ - cd99ed5: Fix spec properties rendering and missing keys
15
+ - 813b2af: Support for x-enumDescriptions and x-gitbook-enum
16
+ - a25fded: Replace $ref with $reference in json-decycle
17
+ - Updated dependencies [7bb37c7]
18
+ - Updated dependencies [5b1e01c]
19
+ - Updated dependencies [813b2af]
20
+ - @gitbook/openapi-parser@2.1.2
21
+
22
+ ## 1.1.6
23
+
24
+ ### Patch Changes
25
+
26
+ - 6eae764: Support body examples
27
+ - 7212973: Update scalar
28
+ - d2facb2: Mark properties as optional if not required
29
+ - 73e2b47: Fix write only properties in request example
30
+ - 70be2c6: Stringify default value
31
+ - fc00b51: Remove default value in generateSchemaExample
32
+ - a84b06b: Update resolveDescription and add minItems/maxItems
33
+ - Updated dependencies [48c18c0]
34
+ - Updated dependencies [7212973]
35
+ - @gitbook/openapi-parser@2.1.1
36
+
3
37
  ## 1.1.5
4
38
 
5
39
  ### Patch Changes
@@ -23,8 +23,6 @@ export declare function InteractiveSection(props: {
23
23
  defaultTab?: string;
24
24
  /** Content of the header */
25
25
  header?: React.ReactNode;
26
- /** Body of the section */
27
- children?: React.ReactNode;
28
26
  /** Children to display within the container */
29
27
  overlay?: React.ReactNode;
30
28
  }): import("react").JSX.Element;
@@ -10,7 +10,7 @@ import { Section, SectionBody, SectionHeader, SectionHeaderContent } from './Sta
10
10
  */
11
11
  export function InteractiveSection(props) {
12
12
  var _a, _b, _c;
13
- var id = props.id, className = props.className, _d = props.toggeable, toggeable = _d === void 0 ? false : _d, _e = props.defaultOpened, defaultOpened = _e === void 0 ? true : _e, _f = props.tabs, tabs = _f === void 0 ? [] : _f, _g = props.defaultTab, defaultTab = _g === void 0 ? (_a = tabs[0]) === null || _a === void 0 ? void 0 : _a.key : _g, header = props.header, children = props.children, overlay = props.overlay, _h = props.toggleIcon, toggleIcon = _h === void 0 ? '▶' : _h;
13
+ var id = props.id, className = props.className, _d = props.toggeable, toggeable = _d === void 0 ? false : _d, _e = props.defaultOpened, defaultOpened = _e === void 0 ? true : _e, _f = props.tabs, tabs = _f === void 0 ? [] : _f, _g = props.defaultTab, defaultTab = _g === void 0 ? (_a = tabs[0]) === null || _a === void 0 ? void 0 : _a.key : _g, header = props.header, overlay = props.overlay, _h = props.toggleIcon, toggleIcon = _h === void 0 ? '▶' : _h;
14
14
  var _j = useState(defaultTab), selectedTabKey = _j[0], setSelectedTab = _j[1];
15
15
  var selectedTab = (_b = tabs.find(function (tab) { return tab.key === selectedTabKey; })) !== null && _b !== void 0 ? _b : tabs[0];
16
16
  var state = useDisclosureState({
@@ -28,7 +28,7 @@ export function InteractiveSection(props) {
28
28
  }
29
29
  }} className={className}>
30
30
  <SectionHeaderContent className={className}>
31
- {(children || (selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.body)) && toggeable ? (<button {...mergeProps(buttonProps, focusProps)} ref={triggerRef} className={clsx('openapi-section-toggle', "".concat(className, "-toggle"))} style={{
31
+ {(selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.body) && toggeable ? (<button {...mergeProps(buttonProps, focusProps)} ref={triggerRef} className={clsx('openapi-section-toggle', "".concat(className, "-toggle"))} style={{
32
32
  outline: isFocusVisible
33
33
  ? '2px solid rgb(var(--primary-color-500) / 0.4)'
34
34
  : 'none',
@@ -50,8 +50,7 @@ export function InteractiveSection(props) {
50
50
  </select>) : null}
51
51
  </div>
52
52
  </SectionHeader>) : null}
53
- {(!toggeable || state.isExpanded) && (children || (selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.body)) ? (<SectionBody ref={panelRef} {...panelProps} className={className}>
54
- {children}
53
+ {(!toggeable || state.isExpanded) && (selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.body) ? (<SectionBody ref={panelRef} {...panelProps} className={className}>
55
54
  {selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.body}
56
55
  </SectionBody>) : null}
57
56
  {overlay ? (<div className={clsx('openapi-section-overlay', "".concat(className, "-overlay"))}>
@@ -1,3 +1,4 @@
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
1
2
  import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
2
3
  /**
3
4
  * Display code samples to execute the operation.
@@ -7,3 +8,11 @@ export declare function OpenAPICodeSample(props: {
7
8
  data: OpenAPIOperationData;
8
9
  context: OpenAPIContextProps;
9
10
  }): import("react").JSX.Element | null;
11
+ export interface MediaTypeRenderer {
12
+ mediaType: string;
13
+ element: React.ReactNode;
14
+ examples: Array<{
15
+ example: OpenAPIV3.ExampleObject;
16
+ element: React.ReactNode;
17
+ }>;
18
+ }
@@ -9,20 +9,47 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ import { OpenAPIMediaTypeExamplesBody, OpenAPIMediaTypeExamplesSelector, } from './OpenAPICodeSampleInteractive';
12
13
  import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
13
14
  import { ScalarApiButton } from './ScalarApiButton';
14
15
  import { StaticSection } from './StaticSection';
15
16
  import { codeSampleGenerators } from './code-samples';
16
- import { generateMediaTypeExample, generateSchemaExample } from './generateSchemaExample';
17
+ import { generateMediaTypeExamples, generateSchemaExample } from './generateSchemaExample';
17
18
  import { stringifyOpenAPI } from './stringifyOpenAPI';
18
19
  import { getDefaultServerURL } from './util/server';
19
20
  import { checkIsReference, createStateKey } from './utils';
21
+ var CUSTOM_CODE_SAMPLES_KEYS = ['x-custom-examples', 'x-code-samples', 'x-codeSamples'];
20
22
  /**
21
23
  * Display code samples to execute the operation.
22
24
  * It supports the Redocly custom syntax as well (https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples/)
23
25
  */
24
26
  export function OpenAPICodeSample(props) {
25
- var _a;
27
+ var data = props.data;
28
+ // If code samples are disabled at operation level, we don't display the code samples.
29
+ if (data.operation['x-codeSamples'] === false) {
30
+ return null;
31
+ }
32
+ var customCodeSamples = getCustomCodeSamples(props);
33
+ // If code samples are disabled at the top-level and not custom code samples are defined,
34
+ // we don't display the code samples.
35
+ if (data['x-codeSamples'] === false && !customCodeSamples) {
36
+ return null;
37
+ }
38
+ var samples = customCodeSamples !== null && customCodeSamples !== void 0 ? customCodeSamples : generateCodeSamples(props);
39
+ if (samples.length === 0) {
40
+ return null;
41
+ }
42
+ return (<OpenAPITabs stateKey={createStateKey('codesample')} items={samples}>
43
+ <StaticSection header={<OpenAPITabsList />} className="openapi-codesample">
44
+ <OpenAPITabsPanels />
45
+ </StaticSection>
46
+ </OpenAPITabs>);
47
+ }
48
+ /**
49
+ * Generate code samples for the operation.
50
+ */
51
+ function generateCodeSamples(props) {
52
+ var _a, _b;
26
53
  var data = props.data, context = props.context;
27
54
  var searchParams = new URLSearchParams();
28
55
  var headersObject = {};
@@ -51,34 +78,92 @@ export function OpenAPICodeSample(props) {
51
78
  var requestBody = !checkIsReference(data.operation.requestBody)
52
79
  ? data.operation.requestBody
53
80
  : undefined;
54
- var requestBodyContentEntries = (requestBody === null || requestBody === void 0 ? void 0 : requestBody.content)
55
- ? Object.entries(requestBody.content)
56
- : undefined;
57
- var requestBodyContent = requestBodyContentEntries === null || requestBodyContentEntries === void 0 ? void 0 : requestBodyContentEntries[0];
58
- var input = {
59
- url: getDefaultServerURL(data.servers) +
60
- data.path +
61
- (searchParams.size ? "?".concat(searchParams.toString()) : ''),
62
- method: data.method,
63
- body: requestBodyContent ? generateMediaTypeExample(requestBodyContent[1]) : undefined,
64
- headers: __assign(__assign(__assign({}, getSecurityHeaders(data.securities)), headersObject), (requestBodyContent
65
- ? {
66
- 'Content-Type': requestBodyContent[0],
67
- }
68
- : undefined)),
69
- };
70
- var autoCodeSamples = codeSampleGenerators.map(function (generator) { return ({
71
- key: "default-".concat(generator.id),
72
- label: generator.label,
73
- body: context.renderCodeBlock({
74
- code: generator.generate(input),
75
- syntax: generator.syntax,
76
- }),
77
- footer: <OpenAPICodeSampleFooter data={data} context={context}/>,
78
- }); });
79
- // Use custom samples if defined
81
+ var url = getDefaultServerURL(data.servers) +
82
+ data.path +
83
+ (searchParams.size ? "?".concat(searchParams.toString()) : '');
84
+ var genericHeaders = __assign(__assign({}, getSecurityHeaders(data.securities)), headersObject);
85
+ var mediaTypeRendererFactories = Object.entries((_b = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) !== null && _b !== void 0 ? _b : {}).map(function (_a) {
86
+ var mediaType = _a[0], mediaTypeObject = _a[1];
87
+ return function (generator) {
88
+ var mediaTypeHeaders = __assign(__assign({}, genericHeaders), { 'Content-Type': mediaType });
89
+ return {
90
+ mediaType: mediaType,
91
+ element: context.renderCodeBlock({
92
+ code: generator.generate({
93
+ url: url,
94
+ method: data.method,
95
+ body: undefined,
96
+ headers: mediaTypeHeaders,
97
+ }),
98
+ syntax: generator.syntax,
99
+ }),
100
+ examples: generateMediaTypeExamples(mediaTypeObject, {
101
+ mode: 'write',
102
+ }).map(function (example) { return ({
103
+ example: example,
104
+ element: context.renderCodeBlock({
105
+ code: generator.generate({
106
+ url: url,
107
+ method: data.method,
108
+ body: example.value,
109
+ headers: mediaTypeHeaders,
110
+ }),
111
+ syntax: generator.syntax,
112
+ }),
113
+ }); }),
114
+ };
115
+ };
116
+ });
117
+ return codeSampleGenerators.map(function (generator) {
118
+ if (mediaTypeRendererFactories.length > 0) {
119
+ var renderers = mediaTypeRendererFactories.map(function (generate) { return generate(generator); });
120
+ return {
121
+ key: "default-".concat(generator.id),
122
+ label: generator.label,
123
+ body: (<OpenAPIMediaTypeExamplesBody method={data.method} path={data.path} renderers={renderers}/>),
124
+ footer: (<OpenAPICodeSampleFooter renderers={renderers} data={data} context={context}/>),
125
+ };
126
+ }
127
+ return {
128
+ key: "default-".concat(generator.id),
129
+ label: generator.label,
130
+ body: context.renderCodeBlock({
131
+ code: generator.generate({
132
+ url: url,
133
+ method: data.method,
134
+ body: undefined,
135
+ headers: genericHeaders,
136
+ }),
137
+ syntax: generator.syntax,
138
+ }),
139
+ footer: <OpenAPICodeSampleFooter data={data} renderers={[]} context={context}/>,
140
+ };
141
+ });
142
+ }
143
+ function OpenAPICodeSampleFooter(props) {
144
+ var data = props.data, context = props.context, renderers = props.renderers;
145
+ var method = data.method, path = data.path;
146
+ var specUrl = context.specUrl;
147
+ var hideTryItPanel = data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'];
148
+ var hasMultipleMediaTypes = renderers.length > 1 || renderers.some(function (renderer) { return renderer.examples.length > 0; });
149
+ if (hideTryItPanel && !hasMultipleMediaTypes) {
150
+ return null;
151
+ }
152
+ if (!validateHttpMethod(method)) {
153
+ return null;
154
+ }
155
+ return (<div className="openapi-codesample-footer">
156
+ {hasMultipleMediaTypes ? (<OpenAPIMediaTypeExamplesSelector method={data.method} path={data.path} renderers={renderers}/>) : (<span />)}
157
+ {!hideTryItPanel && <ScalarApiButton method={method} path={path} specUrl={specUrl}/>}
158
+ </div>);
159
+ }
160
+ /**
161
+ * Get custom code samples for the operation.
162
+ */
163
+ function getCustomCodeSamples(props) {
164
+ var data = props.data, context = props.context;
80
165
  var customCodeSamples = null;
81
- ['x-custom-examples', 'x-code-samples', 'x-codeSamples'].forEach(function (key) {
166
+ CUSTOM_CODE_SAMPLES_KEYS.forEach(function (key) {
82
167
  var customSamples = data.operation[key];
83
168
  if (customSamples && Array.isArray(customSamples)) {
84
169
  customCodeSamples = customSamples
@@ -88,43 +173,17 @@ export function OpenAPICodeSample(props) {
88
173
  typeof sample.lang === 'string');
89
174
  })
90
175
  .map(function (sample, index) { return ({
91
- key: "redocly-".concat(sample.lang, "-").concat(index),
176
+ key: "custom-sample-".concat(sample.lang, "-").concat(index),
92
177
  label: sample.label,
93
178
  body: context.renderCodeBlock({
94
179
  code: sample.source,
95
180
  syntax: sample.lang,
96
181
  }),
97
- footer: <OpenAPICodeSampleFooter data={data} context={context}/>,
182
+ footer: (<OpenAPICodeSampleFooter renderers={[]} data={data} context={context}/>),
98
183
  }); });
99
184
  }
100
185
  });
101
- // Code samples can be disabled at the top-level or at the operation level
102
- // If code samples are defined at the operation level, it will override the top-level setting
103
- var codeSamplesDisabled = data['x-codeSamples'] === false || data.operation['x-codeSamples'] === false;
104
- var samples = customCodeSamples !== null && customCodeSamples !== void 0 ? customCodeSamples : (!codeSamplesDisabled ? autoCodeSamples : []);
105
- if (samples.length === 0) {
106
- return null;
107
- }
108
- return (<OpenAPITabs stateKey={createStateKey('codesample')} items={samples}>
109
- <StaticSection header={<OpenAPITabsList />} className="openapi-codesample">
110
- <OpenAPITabsPanels />
111
- </StaticSection>
112
- </OpenAPITabs>);
113
- }
114
- function OpenAPICodeSampleFooter(props) {
115
- var data = props.data, context = props.context;
116
- var method = data.method, path = data.path;
117
- var specUrl = context.specUrl;
118
- var hideTryItPanel = data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'];
119
- if (hideTryItPanel) {
120
- return null;
121
- }
122
- if (!validateHttpMethod(method)) {
123
- return null;
124
- }
125
- return (<div className="openapi-codesample-footer">
126
- <ScalarApiButton method={method} path={path} specUrl={specUrl}/>
127
- </div>);
186
+ return customCodeSamples;
128
187
  }
129
188
  function getSecurityHeaders(securities) {
130
189
  var _a;
@@ -0,0 +1,11 @@
1
+ import type { MediaTypeRenderer } from './OpenAPICodeSample';
2
+ export declare function OpenAPIMediaTypeExamplesSelector(props: {
3
+ method: string;
4
+ path: string;
5
+ renderers: MediaTypeRenderer[];
6
+ }): import("react").JSX.Element;
7
+ export declare function OpenAPIMediaTypeExamplesBody(props: {
8
+ method: string;
9
+ path: string;
10
+ renderers: MediaTypeRenderer[];
11
+ }): string | number | boolean | Iterable<import("react").ReactNode> | import("react").JSX.Element | null | undefined;
@@ -0,0 +1,85 @@
1
+ 'use client';
2
+ import clsx from 'clsx';
3
+ import { useCallback } from 'react';
4
+ import { useStore } from 'zustand';
5
+ import { getOrCreateTabStoreByKey } from './useSyncedTabsGlobalState';
6
+ function useMediaTypeState(data, defaultKey) {
7
+ var method = data.method, path = data.path;
8
+ var store = useStore(getOrCreateTabStoreByKey("media-type-".concat(method, "-").concat(path), defaultKey));
9
+ if (typeof store.tabKey !== 'string') {
10
+ throw new Error('Media type key is not a string');
11
+ }
12
+ return {
13
+ mediaType: store.tabKey,
14
+ setMediaType: useCallback(function (index) { return store.setTabKey(index); }, [store.setTabKey]),
15
+ };
16
+ }
17
+ function useMediaTypeSampleIndexState(data, mediaType) {
18
+ var method = data.method, path = data.path;
19
+ var store = useStore(getOrCreateTabStoreByKey("media-type-sample-".concat(mediaType, "-").concat(method, "-").concat(path), 0));
20
+ if (typeof store.tabKey !== 'number') {
21
+ throw new Error('Example key is not a number');
22
+ }
23
+ return {
24
+ index: store.tabKey,
25
+ setIndex: useCallback(function (index) { return store.setTabKey(index); }, [store.setTabKey]),
26
+ };
27
+ }
28
+ export function OpenAPIMediaTypeExamplesSelector(props) {
29
+ var method = props.method, path = props.path, renderers = props.renderers;
30
+ if (!renderers[0]) {
31
+ throw new Error('No renderers provided');
32
+ }
33
+ var state = useMediaTypeState({ method: method, path: path }, renderers[0].mediaType);
34
+ var selected = renderers.find(function (r) { return r.mediaType === state.mediaType; }) || renderers[0];
35
+ return (<div className="openapi-codesample-selectors">
36
+ <MediaTypeSelector state={state} renderers={renderers}/>
37
+ <ExamplesSelector method={method} path={path} renderer={selected}/>
38
+ </div>);
39
+ }
40
+ function MediaTypeSelector(props) {
41
+ var renderers = props.renderers, state = props.state;
42
+ if (renderers.length < 2) {
43
+ return null;
44
+ }
45
+ return (<select className={clsx('openapi-select')} value={state.mediaType} onChange={function (e) { return state.setMediaType(e.target.value); }}>
46
+ {renderers.map(function (renderer) { return (<option key={renderer.mediaType} value={renderer.mediaType}>
47
+ {renderer.mediaType}
48
+ </option>); })}
49
+ </select>);
50
+ }
51
+ function ExamplesSelector(props) {
52
+ var method = props.method, path = props.path, renderer = props.renderer;
53
+ var state = useMediaTypeSampleIndexState({ method: method, path: path }, renderer.mediaType);
54
+ if (renderer.examples.length < 2) {
55
+ return null;
56
+ }
57
+ return (<select className={clsx('openapi-select')} value={String(state.index)} onChange={function (e) { return state.setIndex(Number(e.target.value)); }}>
58
+ {renderer.examples.map(function (example, index) { return (<option key={index} value={index}>
59
+ {example.example.summary || "Example ".concat(index + 1)}
60
+ </option>); })}
61
+ </select>);
62
+ }
63
+ export function OpenAPIMediaTypeExamplesBody(props) {
64
+ var _a;
65
+ var renderers = props.renderers, method = props.method, path = props.path;
66
+ if (!renderers[0]) {
67
+ throw new Error('No renderers provided');
68
+ }
69
+ var mediaTypeState = useMediaTypeState({ method: method, path: path }, renderers[0].mediaType);
70
+ var selected = (_a = renderers.find(function (r) { return r.mediaType === mediaTypeState.mediaType; })) !== null && _a !== void 0 ? _a : renderers[0];
71
+ if (selected.examples.length === 0) {
72
+ return selected.element;
73
+ }
74
+ return <ExamplesBody method={method} path={path} renderer={selected}/>;
75
+ }
76
+ function ExamplesBody(props) {
77
+ var _a;
78
+ var method = props.method, path = props.path, renderer = props.renderer;
79
+ var exampleState = useMediaTypeSampleIndexState({ method: method, path: path }, renderer.mediaType);
80
+ var example = (_a = renderer.examples[exampleState.index]) !== null && _a !== void 0 ? _a : renderer.examples[0];
81
+ if (!example) {
82
+ throw new Error("No example found for index ".concat(exampleState.index));
83
+ }
84
+ return example.element;
85
+ }
@@ -1,4 +1,11 @@
1
1
  import { type ButtonProps } from 'react-aria-components';
2
2
  export declare function OpenAPICopyButton(props: ButtonProps & {
3
3
  value: string;
4
+ children: React.ReactNode;
5
+ label?: string;
6
+ /**
7
+ * Whether to show a tooltip.
8
+ * @default true
9
+ */
10
+ withTooltip?: boolean;
4
11
  }): import("react").JSX.Element;
@@ -2,10 +2,9 @@
2
2
  import { useState } from 'react';
3
3
  import { Button, Tooltip, TooltipTrigger } from 'react-aria-components';
4
4
  export function OpenAPICopyButton(props) {
5
- var value = props.value;
6
- var children = props.children, onPress = props.onPress, className = props.className;
7
- var _a = useState(false), copied = _a[0], setCopied = _a[1];
8
- var _b = useState(false), isOpen = _b[0], setIsOpen = _b[1];
5
+ var value = props.value, label = props.label, children = props.children, onPress = props.onPress, className = props.className, _a = props.withTooltip, withTooltip = _a === void 0 ? true : _a;
6
+ var _b = useState(false), copied = _b[0], setCopied = _b[1];
7
+ var _c = useState(false), isOpen = _c[0], setIsOpen = _c[1];
9
8
  var handleCopy = function () {
10
9
  if (!value)
11
10
  return;
@@ -14,10 +13,11 @@ export function OpenAPICopyButton(props) {
14
13
  setCopied(true);
15
14
  setTimeout(function () {
16
15
  setCopied(false);
16
+ setIsOpen(false);
17
17
  }, 2000);
18
18
  });
19
19
  };
20
- return (<TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen} closeDelay={200} delay={200}>
20
+ return (<TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen} isDisabled={!withTooltip} closeDelay={200} delay={200}>
21
21
  <Button type="button" preventFocusOnPress onPress={function (e) {
22
22
  handleCopy();
23
23
  onPress === null || onPress === void 0 ? void 0 : onPress(e);
@@ -26,7 +26,7 @@ export function OpenAPICopyButton(props) {
26
26
  </Button>
27
27
 
28
28
  <Tooltip isOpen={isOpen} onOpenChange={setIsOpen} placement="top" offset={4} className="openapi-tooltip">
29
- {copied ? 'Copied' : 'Copy to clipboard'}{' '}
29
+ {copied ? 'Copied' : label || 'Copy to clipboard'}
30
30
  </Tooltip>
31
31
  </TooltipTrigger>);
32
32
  }
@@ -19,14 +19,18 @@ export function OpenAPIOperation(props) {
19
19
  };
20
20
  return (<div className={clsx('openapi-operation', className)}>
21
21
  <div className="openapi-summary" id={operation.summary ? undefined : context.id}>
22
+ {(operation.deprecated || operation['x-stability']) && (<div className="openapi-summary-tags">
23
+ {operation.deprecated && (<div className="openapi-deprecated">Deprecated</div>)}
24
+ {operation['x-stability'] && (<OpenAPIOperationStability stability={operation['x-stability']}/>)}
25
+ </div>)}
22
26
  {operation.summary
23
27
  ? context.renderHeading({
24
28
  deprecated: (_a = operation.deprecated) !== null && _a !== void 0 ? _a : false,
29
+ stability: operation['x-stability'],
25
30
  title: operation.summary,
26
31
  })
27
32
  : null}
28
33
  <OpenAPIPath data={data} context={context}/>
29
- {operation.deprecated && <div className="openapi-deprecated">Deprecated</div>}
30
34
  </div>
31
35
  <div className="openapi-columns">
32
36
  <div className="openapi-column-spec">
@@ -66,3 +70,19 @@ function OpenAPIOperationDescription(props) {
66
70
  <Markdown className="openapi-description" source={description}/>
67
71
  </div>);
68
72
  }
73
+ var stabilityEnum = {
74
+ experimental: 'Experimental',
75
+ alpha: 'Alpha',
76
+ beta: 'Beta',
77
+ stable: 'Stable',
78
+ };
79
+ function OpenAPIOperationStability(props) {
80
+ var stability = props.stability;
81
+ var foundStability = stabilityEnum[stability];
82
+ if (!foundStability) {
83
+ return null;
84
+ }
85
+ return (<div className={"openapi-stability openapi-stability-".concat(foundStability.toLowerCase())}>
86
+ {foundStability}
87
+ </div>);
88
+ }
@@ -30,7 +30,7 @@ function formatPath(path) {
30
30
  if (offset > lastIndex) {
31
31
  parts.push(path.slice(lastIndex, offset));
32
32
  }
33
- parts.push(<span key={offset} className="openapi-path-variable">
33
+ parts.push(<span key={"offset-".concat(offset)} className="openapi-path-variable">
34
34
  {match}
35
35
  </span>);
36
36
  lastIndex = offset + match.length;
@@ -41,7 +41,7 @@ function formatPath(path) {
41
41
  }
42
42
  var formattedPath = parts.map(function (part, index) {
43
43
  if (typeof part === 'string') {
44
- return <span key={index}>{part}</span>;
44
+ return <span key={"part-".concat(index)}>{part}</span>;
45
45
  }
46
46
  return part;
47
47
  });
@@ -1,5 +1,5 @@
1
1
  import { InteractiveSection } from './InteractiveSection';
2
- import { OpenAPIRootSchema } from './OpenAPISchema';
2
+ import { OpenAPIRootSchema } from './OpenAPISchemaServer';
3
3
  import { checkIsReference } from './utils';
4
4
  /**
5
5
  * Display an interactive request body.
@@ -10,7 +10,7 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { OpenAPIDisclosure } from './OpenAPIDisclosure';
13
- import { OpenAPISchemaProperties } from './OpenAPISchema';
13
+ import { OpenAPISchemaProperties } from './OpenAPISchemaServer';
14
14
  import { parameterToProperty, resolveDescription } from './utils';
15
15
  /**
16
16
  * Display an interactive response body.
@@ -15,7 +15,7 @@ export function OpenAPIResponses(props) {
15
15
  var description = response.description;
16
16
  return {
17
17
  id: statusCode,
18
- label: (<div className="openapi-response-tab-content" key={"response-".concat(statusCode)}>
18
+ label: (<div className="openapi-response-tab-content">
19
19
  <span className="openapi-response-statuscode">
20
20
  {statusCode}
21
21
  </span>
@@ -26,7 +26,7 @@ export function OpenAPIResponses(props) {
26
26
  return ({
27
27
  id: contentType,
28
28
  label: contentType,
29
- body: (<OpenAPIResponse key={"$response-".concat(statusCode, "-").concat(contentType)} response={response} mediaType={mediaType} context={context}/>),
29
+ body: (<OpenAPIResponse response={response} mediaType={mediaType} context={context}/>),
30
30
  });
31
31
  }),
32
32
  };
@@ -1,29 +1,20 @@
1
1
  import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
2
  import type { OpenAPIClientContext } from './types';
3
- type CircularRefsIds = Map<OpenAPIV3.SchemaObject, string>;
4
- interface OpenAPISchemaPropertyEntry {
3
+ export interface OpenAPISchemaPropertyEntry {
5
4
  propertyName?: string | undefined;
6
5
  required?: boolean | undefined;
7
6
  schema: OpenAPIV3.SchemaObject;
8
7
  }
9
- /**
10
- * Render a set of properties of an OpenAPI schema.
11
- */
12
- export declare function OpenAPISchemaProperties(props: {
8
+ export declare function OpenAPISchemaPropertiesFromServer(props: {
13
9
  id?: string;
14
- properties: OpenAPISchemaPropertyEntry[];
15
- circularRefs?: CircularRefsIds;
10
+ properties: string;
16
11
  context: OpenAPIClientContext;
17
12
  }): import("react").JSX.Element;
18
- /**
19
- * Render a root schema (such as the request body or response body).
20
- */
21
- export declare function OpenAPIRootSchema(props: {
22
- schema: OpenAPIV3.SchemaObject;
13
+ export declare function OpenAPIRootSchemaFromServer(props: {
14
+ schema: string;
23
15
  context: OpenAPIClientContext;
24
16
  }): import("react").JSX.Element;
25
17
  /**
26
18
  * Get the alternatives to display for a schema.
27
19
  */
28
20
  export declare function getSchemaAlternatives(schema: OpenAPIV3.SchemaObject, ancestors?: Set<OpenAPIV3.SchemaObject>): OpenAPIV3.SchemaObject[] | null;
29
- export {};