@gitbook/react-openapi 1.1.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/InteractiveSection.d.ts +4 -0
  3. package/dist/InteractiveSection.jsx +14 -13
  4. package/dist/OpenAPICodeSample.d.ts +3 -2
  5. package/dist/OpenAPICodeSample.jsx +8 -12
  6. package/dist/OpenAPICodeSampleInteractive.d.ts +3 -0
  7. package/dist/OpenAPICodeSampleInteractive.jsx +37 -49
  8. package/dist/OpenAPICodeSampleSelector.d.ts +14 -0
  9. package/dist/OpenAPICodeSampleSelector.jsx +44 -0
  10. package/dist/OpenAPICopyButton.d.ts +2 -0
  11. package/dist/OpenAPICopyButton.jsx +5 -2
  12. package/dist/OpenAPIDisclosure.d.ts +4 -3
  13. package/dist/OpenAPIDisclosure.jsx +8 -11
  14. package/dist/OpenAPIDisclosureGroup.d.ts +7 -3
  15. package/dist/OpenAPIDisclosureGroup.jsx +18 -18
  16. package/dist/OpenAPIExample.d.ts +16 -0
  17. package/dist/OpenAPIExample.jsx +36 -0
  18. package/dist/OpenAPIMediaType.d.ts +21 -0
  19. package/dist/OpenAPIMediaType.jsx +61 -0
  20. package/dist/OpenAPIOperation.d.ts +3 -2
  21. package/dist/OpenAPIOperation.jsx +9 -72
  22. package/dist/OpenAPIOperationDescription.d.ts +9 -0
  23. package/dist/OpenAPIOperationDescription.jsx +22 -0
  24. package/dist/OpenAPIOperationStability.d.ts +9 -0
  25. package/dist/OpenAPIOperationStability.jsx +27 -0
  26. package/dist/OpenAPIPath.d.ts +12 -2
  27. package/dist/OpenAPIPath.jsx +10 -4
  28. package/dist/OpenAPIRequestBody.d.ts +3 -1
  29. package/dist/OpenAPIRequestBody.jsx +4 -3
  30. package/dist/OpenAPIResponse.d.ts +1 -1
  31. package/dist/OpenAPIResponse.jsx +1 -1
  32. package/dist/OpenAPIResponseExample.d.ts +4 -3
  33. package/dist/OpenAPIResponseExample.jsx +24 -154
  34. package/dist/OpenAPIResponseExampleContent.d.ts +19 -0
  35. package/dist/OpenAPIResponseExampleContent.jsx +57 -0
  36. package/dist/OpenAPIResponses.d.ts +1 -1
  37. package/dist/OpenAPIResponses.jsx +49 -36
  38. package/dist/OpenAPISchema.d.ts +1 -1
  39. package/dist/OpenAPISchema.jsx +121 -20
  40. package/dist/OpenAPISchemaName.d.ts +2 -0
  41. package/dist/OpenAPISchemaName.jsx +21 -17
  42. package/dist/OpenAPISchemaServer.d.ts +1 -1
  43. package/dist/OpenAPISecurities.d.ts +2 -1
  44. package/dist/OpenAPISecurities.jsx +11 -10
  45. package/dist/OpenAPISelect.d.ts +22 -0
  46. package/dist/OpenAPISelect.jsx +43 -0
  47. package/dist/OpenAPISpec.d.ts +3 -2
  48. package/dist/OpenAPISpec.jsx +11 -9
  49. package/dist/OpenAPITabs.jsx +9 -9
  50. package/dist/OpenAPIWebhook.d.ts +10 -0
  51. package/dist/OpenAPIWebhook.jsx +23 -0
  52. package/dist/OpenAPIWebhookExample.d.ts +6 -0
  53. package/dist/OpenAPIWebhookExample.jsx +41 -0
  54. package/dist/ScalarApiButton.d.ts +2 -0
  55. package/dist/ScalarApiButton.jsx +4 -3
  56. package/dist/StaticSection.d.ts +4 -1
  57. package/dist/StaticSection.jsx +13 -4
  58. package/dist/code-samples.js +57 -39
  59. package/dist/common/OpenAPIColumnSpec.d.ts +6 -0
  60. package/dist/common/OpenAPIColumnSpec.jsx +20 -0
  61. package/dist/common/OpenAPIOperationDescription.d.ts +6 -0
  62. package/dist/common/OpenAPIOperationDescription.jsx +19 -0
  63. package/dist/common/OpenAPIStability.d.ts +4 -0
  64. package/dist/common/OpenAPIStability.jsx +15 -0
  65. package/dist/common/OpenAPISummary.d.ts +6 -0
  66. package/dist/common/OpenAPISummary.jsx +30 -0
  67. package/dist/context.d.ts +75 -0
  68. package/dist/context.js +43 -0
  69. package/dist/generateSchemaExample.js +4 -0
  70. package/dist/getOrCreateStoreByKey.d.ts +10 -0
  71. package/dist/getOrCreateStoreByKey.js +19 -0
  72. package/dist/index.d.ts +5 -1
  73. package/dist/index.js +3 -0
  74. package/dist/resolveOpenAPIOperation.js +10 -5
  75. package/dist/resolveOpenAPIWebhook.d.ts +11 -0
  76. package/dist/resolveOpenAPIWebhook.js +127 -0
  77. package/dist/schemas/OpenAPISchemas.d.ts +5 -6
  78. package/dist/schemas/OpenAPISchemas.jsx +52 -49
  79. package/dist/schemas/resolveOpenAPISchemas.d.ts +4 -3
  80. package/dist/schemas/resolveOpenAPISchemas.js +0 -1
  81. package/dist/stringifyOpenAPI.d.ts +1 -1
  82. package/dist/stringifyOpenAPI.js +6 -3
  83. package/dist/translate.d.ts +10 -0
  84. package/dist/translate.jsx +75 -0
  85. package/dist/translations/de.d.ts +37 -0
  86. package/dist/translations/de.js +37 -0
  87. package/dist/translations/en.d.ts +37 -0
  88. package/dist/translations/en.js +37 -0
  89. package/dist/translations/es.d.ts +37 -0
  90. package/dist/translations/es.js +37 -0
  91. package/dist/translations/fr.d.ts +37 -0
  92. package/dist/translations/fr.js +37 -0
  93. package/dist/translations/index.d.ts +341 -0
  94. package/dist/translations/index.js +27 -0
  95. package/dist/translations/ja.d.ts +37 -0
  96. package/dist/translations/ja.js +37 -0
  97. package/dist/translations/nl.d.ts +37 -0
  98. package/dist/translations/nl.js +37 -0
  99. package/dist/translations/no.d.ts +37 -0
  100. package/dist/translations/no.js +37 -0
  101. package/dist/translations/pt-br.d.ts +37 -0
  102. package/dist/translations/pt-br.js +37 -0
  103. package/dist/translations/types.d.ts +5 -0
  104. package/dist/translations/types.js +1 -0
  105. package/dist/translations/zh.d.ts +37 -0
  106. package/dist/translations/zh.js +37 -0
  107. package/dist/tsconfig.build.tsbuildinfo +1 -1
  108. package/dist/types.d.ts +12 -48
  109. package/dist/util/example.d.ts +35 -0
  110. package/dist/util/example.jsx +103 -0
  111. package/dist/utils.d.ts +18 -0
  112. package/dist/utils.js +57 -0
  113. package/package.json +3 -3
  114. package/src/InteractiveSection.tsx +22 -18
  115. package/src/OpenAPICodeSample.tsx +26 -15
  116. package/src/OpenAPICodeSampleInteractive.tsx +67 -70
  117. package/src/OpenAPICodeSampleSelector.tsx +94 -0
  118. package/src/OpenAPICopyButton.tsx +7 -2
  119. package/src/OpenAPIDisclosure.tsx +20 -22
  120. package/src/OpenAPIDisclosureGroup.tsx +40 -22
  121. package/src/OpenAPIExample.tsx +55 -0
  122. package/src/OpenAPIMediaType.tsx +139 -0
  123. package/src/OpenAPIOperation.tsx +11 -104
  124. package/src/OpenAPIOperationDescription.tsx +34 -0
  125. package/src/OpenAPIOperationStability.tsx +39 -0
  126. package/src/OpenAPIPath.tsx +26 -6
  127. package/src/OpenAPIRequestBody.tsx +9 -4
  128. package/src/OpenAPIResponse.tsx +2 -2
  129. package/src/OpenAPIResponseExample.tsx +41 -215
  130. package/src/OpenAPIResponseExampleContent.tsx +123 -0
  131. package/src/OpenAPIResponses.tsx +83 -62
  132. package/src/OpenAPISchema.test.ts +80 -0
  133. package/src/OpenAPISchema.tsx +149 -25
  134. package/src/OpenAPISchemaName.tsx +28 -19
  135. package/src/OpenAPISchemaServer.tsx +1 -1
  136. package/src/OpenAPISecurities.tsx +46 -12
  137. package/src/OpenAPISelect.tsx +96 -0
  138. package/src/OpenAPISpec.tsx +21 -10
  139. package/src/OpenAPITabs.tsx +9 -9
  140. package/src/OpenAPIWebhook.tsx +33 -0
  141. package/src/OpenAPIWebhookExample.tsx +60 -0
  142. package/src/ScalarApiButton.tsx +6 -6
  143. package/src/StaticSection.tsx +37 -5
  144. package/src/code-samples.test.ts +3 -1
  145. package/src/code-samples.ts +67 -54
  146. package/src/common/OpenAPIColumnSpec.tsx +31 -0
  147. package/src/common/OpenAPIOperationDescription.tsx +31 -0
  148. package/src/common/OpenAPIStability.tsx +23 -0
  149. package/src/common/OpenAPISummary.tsx +45 -0
  150. package/src/context.ts +99 -0
  151. package/src/generateSchemaExample.test.ts +1020 -0
  152. package/src/generateSchemaExample.ts +5 -0
  153. package/src/getOrCreateStoreByKey.ts +33 -0
  154. package/src/index.ts +5 -1
  155. package/src/resolveOpenAPIOperation.ts +14 -3
  156. package/src/resolveOpenAPIWebhook.ts +99 -0
  157. package/src/schemas/OpenAPISchemas.tsx +76 -71
  158. package/src/schemas/resolveOpenAPISchemas.ts +4 -5
  159. package/src/stringifyOpenAPI.ts +11 -3
  160. package/src/translate.tsx +80 -0
  161. package/src/translations/de.ts +37 -0
  162. package/src/translations/en.ts +37 -0
  163. package/src/translations/es.ts +37 -0
  164. package/src/translations/fr.ts +37 -0
  165. package/src/translations/index.ts +33 -0
  166. package/src/translations/ja.ts +37 -0
  167. package/src/translations/nl.ts +37 -0
  168. package/src/translations/no.ts +37 -0
  169. package/src/translations/pt-br.ts +37 -0
  170. package/src/translations/types.ts +7 -0
  171. package/src/translations/zh.ts +37 -0
  172. package/src/types.ts +11 -46
  173. package/src/util/example.tsx +129 -0
  174. package/src/utils.ts +67 -0
  175. package/dist/useSyncedTabsGlobalState.d.ts +0 -10
  176. package/dist/useSyncedTabsGlobalState.js +0 -20
  177. package/src/useSyncedTabsGlobalState.ts +0 -35
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @gitbook/react-openapi
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d67699a: Add OpenAPI Webhook block
8
+
9
+ ### Patch Changes
10
+
11
+ - eeb977f: Fix Python code example for JSON payload
12
+ - 3363a18: Merge simple alternatives
13
+ - 8ed1bda: Translate OpenAPI blocks
14
+ - 7588cfe: Improve OpenAPIResponses examples and schemas
15
+ - ad1dc0b: Bump scalar packages
16
+
17
+ ## 1.1.10
18
+
19
+ ### Patch Changes
20
+
21
+ - 70c4182: Improve OpenAPI schema style
22
+ - 2b6c593: Remove stable from x-stability
23
+ - cbd768a: Improve OpenAPI codesample (add OpenAPISelect component)
24
+ - e59076a: Improve OpenAPI schemas block ungrouped style. Classnames have changed, please refer to this PR to update GBX.
25
+ - eedefdd: Handle optional security headers
26
+ - 23cedd2: Hide deprecated properties in examples
27
+ - Updated dependencies [2b6c593]
28
+ - @gitbook/openapi-parser@2.1.3
29
+
3
30
  ## 1.1.9
4
31
 
5
32
  ### Patch Changes
@@ -25,5 +25,9 @@ export declare function InteractiveSection(props: {
25
25
  header?: React.ReactNode;
26
26
  /** Children to display within the container */
27
27
  overlay?: React.ReactNode;
28
+ /** State key to use with a store */
29
+ stateKey?: string;
30
+ /** Icon for the tabs select */
31
+ selectIcon?: React.ReactNode;
28
32
  }): import("react").JSX.Element;
29
33
  export {};
@@ -1,26 +1,27 @@
1
1
  'use client';
2
2
  import clsx from 'clsx';
3
- import { useRef, useState } from 'react';
3
+ import { useRef } from 'react';
4
4
  import { mergeProps, useButton, useDisclosure, useFocusRing } from 'react-aria';
5
5
  import { useDisclosureState } from 'react-stately';
6
+ import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
6
7
  import { Section, SectionBody, SectionHeader, SectionHeaderContent } from './StaticSection';
7
8
  /**
8
9
  * To optimize rendering, most of the components are server-components,
9
10
  * and the interactiveness is mainly handled by a few key components like this one.
10
11
  */
11
12
  export function InteractiveSection(props) {
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, overlay = props.overlay, _h = props.toggleIcon, toggleIcon = _h === void 0 ? '▶' : _h;
14
- var _j = useState(defaultTab), selectedTabKey = _j[0], setSelectedTab = _j[1];
15
- var selectedTab = (_b = tabs.find(function (tab) { return tab.key === selectedTabKey; })) !== null && _b !== void 0 ? _b : tabs[0];
13
+ var _a, _b;
14
+ var id = props.id, className = props.className, _c = props.toggeable, toggeable = _c === void 0 ? false : _c, _d = props.defaultOpened, defaultOpened = _d === void 0 ? true : _d, _e = props.tabs, tabs = _e === void 0 ? [] : _e, _f = props.defaultTab, defaultTab = _f === void 0 ? (_a = tabs[0]) === null || _a === void 0 ? void 0 : _a.key : _f, header = props.header, overlay = props.overlay, _g = props.toggleIcon, toggleIcon = _g === void 0 ? '▶' : _g, selectIcon = props.selectIcon, _h = props.stateKey, stateKey = _h === void 0 ? 'interactive-section' : _h;
16
15
  var state = useDisclosureState({
17
16
  defaultExpanded: defaultOpened,
18
17
  });
19
18
  var panelRef = useRef(null);
20
19
  var triggerRef = useRef(null);
21
- var _k = useDisclosure({}, state, panelRef), triggerProps = _k.buttonProps, panelProps = _k.panelProps;
20
+ var _j = useDisclosure({}, state, panelRef), triggerProps = _j.buttonProps, panelProps = _j.panelProps;
22
21
  var buttonProps = useButton(triggerProps, triggerRef).buttonProps;
23
- var _l = useFocusRing(), isFocusVisible = _l.isFocusVisible, focusProps = _l.focusProps;
22
+ var _k = useFocusRing(), isFocusVisible = _k.isFocusVisible, focusProps = _k.focusProps;
23
+ var store = useSelectState(stateKey, defaultTab);
24
+ var selectedTab = (_b = tabs.find(function (tab) { return tab.key === store.key; })) !== null && _b !== void 0 ? _b : tabs[0];
24
25
  return (<Section id={id} className={clsx('openapi-section', toggeable ? 'openapi-section-toggeable' : null, className, toggeable ? "".concat(className, "-").concat(state.isExpanded ? 'opened' : 'closed') : null)}>
25
26
  {header ? (<SectionHeader onClick={function () {
26
27
  if (toggeable) {
@@ -37,17 +38,17 @@ export function InteractiveSection(props) {
37
38
  </button>) : null}
38
39
  {header}
39
40
  </SectionHeaderContent>
41
+ {/* biome-ignore lint/a11y/useKeyWithClickEvents: we prevent default here */}
40
42
  <div className={clsx('openapi-section-header-controls', "".concat(className, "-header-controls"))} onClick={function (event) {
41
43
  event.stopPropagation();
42
44
  }}>
43
- {tabs.length > 1 ? (<select className={clsx('openapi-section-select', 'openapi-select', "".concat(className, "-tabs-select"))} value={(_c = selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.key) !== null && _c !== void 0 ? _c : ''} onChange={function (event) {
44
- setSelectedTab(event.target.value);
45
+ {tabs.length > 1 ? (<OpenAPISelect stateKey={stateKey} items={tabs} onSelectionChange={function () {
45
46
  state.expand();
46
- }}>
47
- {tabs.map(function (tab) { return (<option key={tab.key} value={tab.key}>
47
+ }} icon={selectIcon} placement="bottom end">
48
+ {tabs.map(function (tab) { return (<OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
48
49
  {tab.label}
49
- </option>); })}
50
- </select>) : null}
50
+ </OpenAPISelectItem>); })}
51
+ </OpenAPISelect>) : null}
51
52
  </div>
52
53
  </SectionHeader>) : null}
53
54
  {(!toggeable || state.isExpanded) && (selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.body) ? (<SectionBody ref={panelRef} {...panelProps} className={className}>
@@ -1,12 +1,13 @@
1
1
  import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
- import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
2
+ import { type OpenAPIContext } from './context';
3
+ import type { OpenAPIOperationData } from './types';
3
4
  /**
4
5
  * Display code samples to execute the operation.
5
6
  * It supports the Redocly custom syntax as well (https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples/)
6
7
  */
7
8
  export declare function OpenAPICodeSample(props: {
8
9
  data: OpenAPIOperationData;
9
- context: OpenAPIContextProps;
10
+ context: OpenAPIContext;
10
11
  }): import("react").JSX.Element | null;
11
12
  export interface MediaTypeRenderer {
12
13
  mediaType: string;
@@ -10,21 +10,21 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { OpenAPIMediaTypeExamplesBody, OpenAPIMediaTypeExamplesSelector, } from './OpenAPICodeSampleInteractive';
13
- import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
13
+ import { OpenAPICodeSampleBody } from './OpenAPICodeSampleSelector';
14
14
  import { ScalarApiButton } from './ScalarApiButton';
15
- import { StaticSection } from './StaticSection';
16
15
  import { codeSampleGenerators } from './code-samples';
16
+ import { getOpenAPIClientContext } from './context';
17
17
  import { generateMediaTypeExamples, generateSchemaExample } from './generateSchemaExample';
18
18
  import { stringifyOpenAPI } from './stringifyOpenAPI';
19
19
  import { getDefaultServerURL } from './util/server';
20
- import { checkIsReference, createStateKey } from './utils';
20
+ import { checkIsReference } from './utils';
21
21
  var CUSTOM_CODE_SAMPLES_KEYS = ['x-custom-examples', 'x-code-samples', 'x-codeSamples'];
22
22
  /**
23
23
  * Display code samples to execute the operation.
24
24
  * It supports the Redocly custom syntax as well (https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples/)
25
25
  */
26
26
  export function OpenAPICodeSample(props) {
27
- var data = props.data;
27
+ var data = props.data, context = props.context;
28
28
  // If code samples are disabled at operation level, we don't display the code samples.
29
29
  if (data.operation['x-codeSamples'] === false) {
30
30
  return null;
@@ -39,11 +39,7 @@ export function OpenAPICodeSample(props) {
39
39
  if (samples.length === 0) {
40
40
  return null;
41
41
  }
42
- return (<OpenAPITabs stateKey={createStateKey('codesample')} items={samples}>
43
- <StaticSection header={<OpenAPITabsList />} className="openapi-codesample">
44
- <OpenAPITabsPanels />
45
- </StaticSection>
46
- </OpenAPITabs>);
42
+ return (<OpenAPICodeSampleBody context={getOpenAPIClientContext(context)} data={data} items={samples} selectIcon={context.icons.chevronDown}/>);
47
43
  }
48
44
  /**
49
45
  * Generate code samples for the operation.
@@ -120,7 +116,7 @@ function generateCodeSamples(props) {
120
116
  return {
121
117
  key: "default-".concat(generator.id),
122
118
  label: generator.label,
123
- body: (<OpenAPIMediaTypeExamplesBody method={data.method} path={data.path} renderers={renderers}/>),
119
+ body: (<OpenAPIMediaTypeExamplesBody method={data.method} path={data.path} renderers={renderers} blockKey={context.blockKey}/>),
124
120
  footer: (<OpenAPICodeSampleFooter renderers={renderers} data={data} context={context}/>),
125
121
  };
126
122
  }
@@ -153,8 +149,8 @@ function OpenAPICodeSampleFooter(props) {
153
149
  return null;
154
150
  }
155
151
  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}/>}
152
+ {hasMultipleMediaTypes ? (<OpenAPIMediaTypeExamplesSelector method={data.method} path={data.path} renderers={renderers} selectIcon={context.icons.chevronDown} blockKey={context.blockKey}/>) : (<span />)}
153
+ {!hideTryItPanel && (<ScalarApiButton context={getOpenAPIClientContext(context)} method={method} path={path} specUrl={specUrl}/>)}
158
154
  </div>);
159
155
  }
160
156
  /**
@@ -3,9 +3,12 @@ export declare function OpenAPIMediaTypeExamplesSelector(props: {
3
3
  method: string;
4
4
  path: string;
5
5
  renderers: MediaTypeRenderer[];
6
+ selectIcon?: React.ReactNode;
7
+ blockKey?: string;
6
8
  }): import("react").JSX.Element;
7
9
  export declare function OpenAPIMediaTypeExamplesBody(props: {
8
10
  method: string;
9
11
  path: string;
10
12
  renderers: MediaTypeRenderer[];
13
+ blockKey?: string;
11
14
  }): string | number | boolean | Iterable<import("react").ReactNode> | import("react").JSX.Element | null | undefined;
@@ -1,73 +1,61 @@
1
1
  'use client';
2
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
- }
3
+ import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
4
+ import { createStateKey } from './utils';
28
5
  export function OpenAPIMediaTypeExamplesSelector(props) {
29
- var method = props.method, path = props.path, renderers = props.renderers;
6
+ var method = props.method, path = props.path, renderers = props.renderers, selectIcon = props.selectIcon, blockKey = props.blockKey;
30
7
  if (!renderers[0]) {
31
8
  throw new Error('No renderers provided');
32
9
  }
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];
10
+ var stateKey = createStateKey('request-body-media-type', blockKey);
11
+ var state = useSelectState(stateKey, renderers[0].mediaType);
12
+ var selected = renderers.find(function (r) { return r.mediaType === state.key; }) || renderers[0];
35
13
  return (<div className="openapi-codesample-selectors">
36
- <MediaTypeSelector state={state} renderers={renderers}/>
37
- <ExamplesSelector method={method} path={path} renderer={selected}/>
14
+ <MediaTypeSelector selectIcon={selectIcon} stateKey={stateKey} renderers={renderers}/>
15
+ <ExamplesSelector selectIcon={selectIcon} method={method} path={path} renderer={selected}/>
38
16
  </div>);
39
17
  }
40
18
  function MediaTypeSelector(props) {
41
- var renderers = props.renderers, state = props.state;
19
+ var renderers = props.renderers, stateKey = props.stateKey, selectIcon = props.selectIcon;
42
20
  if (renderers.length < 2) {
43
21
  return null;
44
22
  }
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>);
23
+ var items = renderers.map(function (renderer) { return ({
24
+ key: renderer.mediaType,
25
+ label: renderer.mediaType,
26
+ }); });
27
+ return (<OpenAPISelect className={clsx('openapi-select')} items={renderers.map(function (renderer) { return ({
28
+ key: renderer.mediaType,
29
+ label: renderer.mediaType,
30
+ }); })} icon={selectIcon} stateKey={stateKey} placement="bottom start">
31
+ {items.map(function (item) { return (<OpenAPISelectItem key={item.key} id={item.key} value={item}>
32
+ {item.label}
33
+ </OpenAPISelectItem>); })}
34
+ </OpenAPISelect>);
50
35
  }
51
36
  function ExamplesSelector(props) {
52
- var method = props.method, path = props.path, renderer = props.renderer;
53
- var state = useMediaTypeSampleIndexState({ method: method, path: path }, renderer.mediaType);
37
+ var method = props.method, path = props.path, renderer = props.renderer, selectIcon = props.selectIcon;
54
38
  if (renderer.examples.length < 2) {
55
39
  return null;
56
40
  }
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>);
41
+ var items = renderer.examples.map(function (example, index) { return ({
42
+ key: index,
43
+ label: example.example.summary || "Example ".concat(index + 1),
44
+ }); });
45
+ return (<OpenAPISelect items={items} icon={selectIcon} stateKey={"media-type-sample-".concat(renderer.mediaType, "-").concat(method, "-").concat(path)} placement="bottom start">
46
+ {items.map(function (item) { return (<OpenAPISelectItem key={item.key} id={item.key} value={item}>
47
+ {item.label}
48
+ </OpenAPISelectItem>); })}
49
+ </OpenAPISelect>);
62
50
  }
63
51
  export function OpenAPIMediaTypeExamplesBody(props) {
64
52
  var _a;
65
- var renderers = props.renderers, method = props.method, path = props.path;
53
+ var renderers = props.renderers, method = props.method, path = props.path, blockKey = props.blockKey;
66
54
  if (!renderers[0]) {
67
55
  throw new Error('No renderers provided');
68
56
  }
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];
57
+ var mediaTypeState = useSelectState(createStateKey('request-body-media-type', blockKey), renderers[0].mediaType);
58
+ var selected = (_a = renderers.find(function (r) { return r.mediaType === mediaTypeState.key; })) !== null && _a !== void 0 ? _a : renderers[0];
71
59
  if (selected.examples.length === 0) {
72
60
  return selected.element;
73
61
  }
@@ -76,10 +64,10 @@ export function OpenAPIMediaTypeExamplesBody(props) {
76
64
  function ExamplesBody(props) {
77
65
  var _a;
78
66
  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];
67
+ var exampleState = useSelectState("media-type-sample-".concat(renderer.mediaType, "-").concat(method, "-").concat(path), renderer.mediaType);
68
+ var example = (_a = renderer.examples[Number(exampleState.key)]) !== null && _a !== void 0 ? _a : renderer.examples[0];
81
69
  if (!example) {
82
- throw new Error("No example found for index ".concat(exampleState.index));
70
+ throw new Error("No example found for key ".concat(exampleState.key));
83
71
  }
84
72
  return example.element;
85
73
  }
@@ -0,0 +1,14 @@
1
+ import { OpenAPISelectItem } from './OpenAPISelect';
2
+ import type { OpenAPIClientContext } from './context';
3
+ import type { OpenAPIOperationData } from './types';
4
+ type CodeSampleItem = OpenAPISelectItem & {
5
+ body: React.ReactNode;
6
+ footer?: React.ReactNode;
7
+ };
8
+ export declare function OpenAPICodeSampleBody(props: {
9
+ items: CodeSampleItem[];
10
+ data: OpenAPIOperationData;
11
+ selectIcon?: React.ReactNode;
12
+ context: OpenAPIClientContext;
13
+ }): import("react").JSX.Element | null;
14
+ export {};
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import { useCallback } from 'react';
3
+ import { useStore } from 'zustand';
4
+ import { OpenAPIPath } from './OpenAPIPath';
5
+ import { OpenAPISelect, OpenAPISelectItem } from './OpenAPISelect';
6
+ import { StaticSection } from './StaticSection';
7
+ import { getOrCreateStoreByKey } from './getOrCreateStoreByKey';
8
+ function useCodeSampleState(initialKey) {
9
+ if (initialKey === void 0) { initialKey = 'default'; }
10
+ var store = useStore(getOrCreateStoreByKey('codesample', initialKey));
11
+ return {
12
+ key: store.key,
13
+ setKey: useCallback(function (key) { return store.setKey(key); }, [store.setKey]),
14
+ };
15
+ }
16
+ function OpenAPICodeSampleHeader(props) {
17
+ var data = props.data, items = props.items, selectIcon = props.selectIcon, context = props.context;
18
+ return (<>
19
+ <OpenAPIPath context={context} canCopy={false} withServer={false} data={data}/>
20
+ {items.length > 1 ? (<OpenAPISelect icon={selectIcon} items={items} stateKey="codesample" placement="bottom end">
21
+ {items.map(function (item) { return (<OpenAPISelectItem key={item.key} id={item.key} value={item}>
22
+ {item.label}
23
+ </OpenAPISelectItem>); })}
24
+ </OpenAPISelect>) : items[0] ? (<span className="openapi-codesample-label">{items[0].label}</span>) : null}
25
+ </>);
26
+ }
27
+ export function OpenAPICodeSampleBody(props) {
28
+ var _a;
29
+ var items = props.items, data = props.data, selectIcon = props.selectIcon, context = props.context;
30
+ if (!items[0]) {
31
+ throw new Error('No items provided');
32
+ }
33
+ var state = useCodeSampleState((_a = items[0]) === null || _a === void 0 ? void 0 : _a.key);
34
+ var selected = items.find(function (item) { return item.key === state.key; }) || items[0];
35
+ if (!selected) {
36
+ return null;
37
+ }
38
+ return (<StaticSection header={<OpenAPICodeSampleHeader context={context} selectIcon={selectIcon} data={data} items={items}/>} className="openapi-codesample">
39
+ <div id={selected.key} className="openapi-codesample-panel">
40
+ {selected.body ? selected.body : null}
41
+ {selected.footer ? selected.footer : null}
42
+ </div>
43
+ </StaticSection>);
44
+ }
@@ -1,7 +1,9 @@
1
1
  import { type ButtonProps } from 'react-aria-components';
2
+ import type { OpenAPIClientContext } from './context';
2
3
  export declare function OpenAPICopyButton(props: ButtonProps & {
3
4
  value: string;
4
5
  children: React.ReactNode;
6
+ context: OpenAPIClientContext;
5
7
  label?: string;
6
8
  /**
7
9
  * Whether to show a tooltip.
@@ -1,8 +1,9 @@
1
1
  'use client';
2
2
  import { useState } from 'react';
3
3
  import { Button, Tooltip, TooltipTrigger } from 'react-aria-components';
4
+ import { t } from './translate';
4
5
  export function OpenAPICopyButton(props) {
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 value = props.value, label = props.label, children = props.children, onPress = props.onPress, className = props.className, context = props.context, _a = props.withTooltip, withTooltip = _a === void 0 ? true : _a;
6
7
  var _b = useState(false), copied = _b[0], setCopied = _b[1];
7
8
  var _c = useState(false), isOpen = _c[0], setIsOpen = _c[1];
8
9
  var handleCopy = function () {
@@ -26,7 +27,9 @@ export function OpenAPICopyButton(props) {
26
27
  </Button>
27
28
 
28
29
  <Tooltip isOpen={isOpen} onOpenChange={setIsOpen} placement="top" offset={4} className="openapi-tooltip">
29
- {copied ? 'Copied' : label || 'Copy to clipboard'}
30
+ {copied
31
+ ? t(context.translation, 'copied')
32
+ : label || t(context.translation, 'copy_to_clipboard')}
30
33
  </Tooltip>
31
34
  </TooltipTrigger>);
32
35
  }
@@ -1,9 +1,10 @@
1
- import type { OpenAPIClientContext } from './types';
1
+ import type React from 'react';
2
2
  /**
3
3
  * Display an interactive OpenAPI disclosure.
4
4
  */
5
5
  export declare function OpenAPIDisclosure(props: {
6
- context: OpenAPIClientContext;
6
+ icon: React.ReactNode;
7
7
  children: React.ReactNode;
8
- label: string;
8
+ label: string | ((isExpanded: boolean) => string);
9
+ className?: string;
9
10
  }): React.JSX.Element;
@@ -1,15 +1,15 @@
1
1
  'use client';
2
+ import clsx from 'clsx';
2
3
  import { useState } from 'react';
3
- import { Button, Disclosure, DisclosurePanel, Heading } from 'react-aria-components';
4
+ import { Button, Disclosure, DisclosurePanel } from 'react-aria-components';
4
5
  /**
5
6
  * Display an interactive OpenAPI disclosure.
6
7
  */
7
8
  export function OpenAPIDisclosure(props) {
8
- var context = props.context, children = props.children, label = props.label;
9
+ var icon = props.icon, children = props.children, label = props.label, className = props.className;
9
10
  var _a = useState(false), isExpanded = _a[0], setIsExpanded = _a[1];
10
- return (<Disclosure className="openapi-disclosure" isExpanded={isExpanded} onExpandedChange={setIsExpanded}>
11
- <Heading>
12
- <Button slot="trigger" className="openapi-disclosure-trigger" style={function (_a) {
11
+ return (<Disclosure className={clsx('openapi-disclosure', className)} isExpanded={isExpanded} onExpandedChange={setIsExpanded}>
12
+ <Button slot="trigger" className="openapi-disclosure-trigger" style={function (_a) {
13
13
  var isFocusVisible = _a.isFocusVisible;
14
14
  return ({
15
15
  outline: isFocusVisible
@@ -17,12 +17,9 @@ export function OpenAPIDisclosure(props) {
17
17
  : 'none',
18
18
  });
19
19
  }}>
20
- {context.icons.plus}
21
- <span>
22
- {isExpanded ? 'Hide' : 'Show'} {label}
23
- </span>
24
- </Button>
25
- </Heading>
20
+ {icon}
21
+ <span>{typeof label === 'function' ? label(isExpanded) : label}</span>
22
+ </Button>
26
23
  <DisclosurePanel className="openapi-disclosure-panel">
27
24
  {isExpanded ? children : null}
28
25
  </DisclosurePanel>
@@ -2,13 +2,17 @@ import { type DisclosureGroupProps } from 'react-stately';
2
2
  interface Props {
3
3
  groups: TDisclosureGroup[];
4
4
  icon?: React.ReactNode;
5
+ /** State key to use with a store */
6
+ selectStateKey?: string;
7
+ /** Icon to display for the select */
8
+ selectIcon?: React.ReactNode;
5
9
  }
6
10
  type TDisclosureGroup = {
7
- id: string;
11
+ key: string;
8
12
  label: string | React.ReactNode;
9
13
  tabs?: {
10
- id: string;
11
- label?: string | React.ReactNode;
14
+ key: string;
15
+ label: string | React.ReactNode;
12
16
  body?: React.ReactNode;
13
17
  }[];
14
18
  };
@@ -10,25 +10,26 @@ var __assign = (this && this.__assign) || function () {
10
10
  };
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
- import { createContext, useContext, useRef, useState } from 'react';
13
+ import { createContext, useContext, useRef } from 'react';
14
14
  import { mergeProps, useButton, useDisclosure, useFocusRing, useId } from 'react-aria';
15
15
  import { useDisclosureGroupState, useDisclosureState, } from 'react-stately';
16
+ import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
16
17
  var DisclosureGroupStateContext = createContext(null);
17
18
  /**
18
19
  * Display an interactive OpenAPI disclosure group.
19
20
  */
20
21
  export function OpenAPIDisclosureGroup(props) {
21
- var icon = props.icon, groups = props.groups;
22
+ var icon = props.icon, groups = props.groups, selectStateKey = props.selectStateKey, selectIcon = props.selectIcon;
22
23
  var state = useDisclosureGroupState(props);
23
24
  return (<DisclosureGroupStateContext.Provider value={state}>
24
- {groups.map(function (group) { return (<DisclosureItem icon={icon} key={group.id} group={group}/>); })}
25
+ {groups.map(function (group) { return (<DisclosureItem selectStateKey={selectStateKey} selectIcon={selectIcon} icon={icon} key={group.key} group={group}/>); })}
25
26
  </DisclosureGroupStateContext.Provider>);
26
27
  }
27
28
  function DisclosureItem(props) {
28
- var _a, _b, _c, _d, _e, _f;
29
- var icon = props.icon, group = props.group;
29
+ var _a, _b, _c, _d, _e, _f, _g;
30
+ var icon = props.icon, group = props.group, selectStateKey = props.selectStateKey, selectIcon = props.selectIcon;
30
31
  var defaultId = useId();
31
- var id = group.id || defaultId;
32
+ var id = group.key || defaultId;
32
33
  var groupState = useContext(DisclosureGroupStateContext);
33
34
  var isExpanded = (groupState === null || groupState === void 0 ? void 0 : groupState.expandedKeys.has(id)) || false;
34
35
  var state = useDisclosureState({
@@ -42,12 +43,12 @@ function DisclosureItem(props) {
42
43
  var panelRef = useRef(null);
43
44
  var triggerRef = useRef(null);
44
45
  var isDisabled = (groupState === null || groupState === void 0 ? void 0 : groupState.isDisabled) || !((_a = group.tabs) === null || _a === void 0 ? void 0 : _a.length) || false;
45
- var _g = useDisclosure(__assign(__assign({}, props), { isExpanded: isExpanded, isDisabled: isDisabled }), state, panelRef), triggerProps = _g.buttonProps, panelProps = _g.panelProps;
46
+ var _h = useDisclosure(__assign(__assign({}, props), { isExpanded: isExpanded, isDisabled: isDisabled }), state, panelRef), triggerProps = _h.buttonProps, panelProps = _h.panelProps;
46
47
  var buttonProps = useButton(triggerProps, triggerRef).buttonProps;
47
- var _h = useFocusRing(), isFocusVisible = _h.isFocusVisible, focusProps = _h.focusProps;
48
- var defaultTab = ((_c = (_b = group.tabs) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.id) || '';
49
- var _j = useState(defaultTab), selectedTabKey = _j[0], setSelectedTabKey = _j[1];
50
- var selectedTab = (_d = group.tabs) === null || _d === void 0 ? void 0 : _d.find(function (tab) { return tab.id === selectedTabKey; });
48
+ var _j = useFocusRing(), isFocusVisible = _j.isFocusVisible, focusProps = _j.focusProps;
49
+ var defaultTab = ((_c = (_b = group.tabs) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.key) || '';
50
+ var store = useSelectState(selectStateKey, defaultTab);
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]);
51
52
  return (<div className="openapi-disclosure-group" aria-expanded={state.isExpanded}>
52
53
  <div className="openapi-disclosure-group-header">
53
54
  <button slot="trigger" ref={triggerRef} {...mergeProps(buttonProps, focusProps)} disabled={isDisabled} style={{
@@ -63,15 +64,14 @@ function DisclosureItem(props) {
63
64
 
64
65
  {group.label}
65
66
  </button>
66
- {group.tabs ? (<div className="openapi-disclosure-group-mediatype">
67
- {((_e = group.tabs) === null || _e === void 0 ? void 0 : _e.length) > 1 ? (<select className="openapi-section-select openapi-select openapi-disclosure-group-tabs-select" onClick={function (event) { return event.stopPropagation(); }} value={selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.id} onChange={function (event) {
68
- setSelectedTabKey(event.target.value);
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
- }}>
71
- {group.tabs.map(function (tab) { return (<option key={tab.id} value={tab.id}>
70
+ }} items={group.tabs}>
71
+ {group.tabs.map(function (tab) { return (<OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
72
72
  {tab.label}
73
- </option>); })}
74
- </select>) : ((_f = group.tabs[0]) === null || _f === void 0 ? void 0 : _f.label) ? (<span>{group.tabs[0].label}</span>) : null}
73
+ </OpenAPISelectItem>); })}
74
+ </OpenAPISelect>) : ((_g = group.tabs[0]) === null || _g === void 0 ? void 0 : _g.label) ? (<span>{group.tabs[0].label}</span>) : null}
75
75
  </div>) : null}
76
76
  </div>
77
77
 
@@ -0,0 +1,16 @@
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ import type { OpenAPIContext, OpenAPIUniversalContext } from './context';
3
+ /**
4
+ * Display an example.
5
+ */
6
+ export declare function OpenAPIExample(props: {
7
+ example: OpenAPIV3.ExampleObject;
8
+ context: OpenAPIContext;
9
+ syntax: string;
10
+ }): string | number | boolean | Iterable<import("react").ReactNode> | import("react").JSX.Element | null | undefined;
11
+ /**
12
+ * Empty response example.
13
+ */
14
+ export declare function OpenAPIEmptyExample(props: {
15
+ context: OpenAPIUniversalContext;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,36 @@
1
+ import { json2xml } from './json2xml';
2
+ import { stringifyOpenAPI } from './stringifyOpenAPI';
3
+ import { t } from './translate';
4
+ /**
5
+ * Display an example.
6
+ */
7
+ export function OpenAPIExample(props) {
8
+ var example = props.example, context = props.context, syntax = props.syntax;
9
+ var code = stringifyExample({ example: example, xml: syntax === 'xml' });
10
+ if (code === null) {
11
+ return <OpenAPIEmptyExample context={context}/>;
12
+ }
13
+ return context.renderCodeBlock({ code: code, syntax: syntax });
14
+ }
15
+ function stringifyExample(args) {
16
+ var example = args.example, xml = args.xml;
17
+ if (!example.value) {
18
+ return null;
19
+ }
20
+ if (typeof example.value === 'string') {
21
+ return example.value;
22
+ }
23
+ if (xml) {
24
+ return json2xml(example.value);
25
+ }
26
+ return stringifyOpenAPI(example.value, null, 2);
27
+ }
28
+ /**
29
+ * Empty response example.
30
+ */
31
+ export function OpenAPIEmptyExample(props) {
32
+ var context = props.context;
33
+ return (<pre className="openapi-example-empty">
34
+ <p>{t(context.translation, 'no_content')}</p>
35
+ </pre>);
36
+ }
@@ -0,0 +1,21 @@
1
+ import type { Key } from 'react-aria';
2
+ import { OpenAPISelectItem } from './OpenAPISelect';
3
+ import type { OpenAPIClientContext } from './context';
4
+ type OpenAPIMediaTypeItem = OpenAPISelectItem & {
5
+ body: React.ReactNode;
6
+ examples?: OpenAPIMediaTypeItem[];
7
+ };
8
+ /**
9
+ * Get the state of the response examples select.
10
+ */
11
+ export declare function useMediaTypesState(stateKey: string | undefined, initialKey?: Key): {
12
+ key: (string | number) | null;
13
+ setKey: (key: Key | null) => void;
14
+ };
15
+ export declare function OpenAPIMediaTypeContent(props: {
16
+ items: OpenAPIMediaTypeItem[];
17
+ selectIcon?: React.ReactNode;
18
+ stateKey: string;
19
+ context: OpenAPIClientContext;
20
+ }): import("react").JSX.Element | null;
21
+ export {};