@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/dist/types.d.ts CHANGED
@@ -1,47 +1,7 @@
1
- import type { OpenAPICustomOperationProperties, OpenAPICustomSpecProperties, OpenAPISchema, OpenAPIV3 } from '@gitbook/openapi-parser';
2
- export interface OpenAPIContextProps extends OpenAPIClientContext {
3
- /**
4
- * Render a code block.
5
- */
6
- renderCodeBlock: (props: {
7
- code: string;
8
- syntax: string;
9
- }) => React.ReactNode;
10
- /**
11
- * Render the heading of the operation.
12
- */
13
- renderHeading: (props: {
14
- deprecated: boolean;
15
- title: string;
16
- stability?: string;
17
- }) => React.ReactNode;
18
- /**
19
- * Render the document of the operation.
20
- */
21
- renderDocument: (props: {
22
- document: object;
23
- }) => React.ReactNode;
24
- /** Spec url for the Scalar Api Client */
25
- specUrl: string;
26
- }
27
- export interface OpenAPIClientContext {
28
- icons: {
29
- chevronDown: React.ReactNode;
30
- chevronRight: React.ReactNode;
31
- plus: React.ReactNode;
32
- };
33
- /**
34
- * Force all sections to be opened by default.
35
- * @default false
36
- */
37
- defaultInteractiveOpened?: boolean;
38
- /**
39
- * The key of the block
40
- */
41
- blockKey?: string;
42
- /** Optional id attached to the OpenAPI Operation heading and used as an anchor */
43
- id?: string;
44
- }
1
+ import type { OpenAPICustomOperationProperties, OpenAPICustomSpecProperties, OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ export type OpenAPISecurityWithRequired = OpenAPIV3.SecuritySchemeObject & {
3
+ required?: boolean;
4
+ };
45
5
  export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
46
6
  path: string;
47
7
  method: string;
@@ -50,9 +10,13 @@ export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
50
10
  /** Spec of the operation */
51
11
  operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
52
12
  /** Securities that should be used for this operation */
53
- securities: [string, OpenAPIV3.SecuritySchemeObject][];
13
+ securities: [string, OpenAPISecurityWithRequired][];
54
14
  }
55
- export interface OpenAPISchemasData {
56
- /** Components schemas to be used for schemas */
57
- schemas: OpenAPISchema[];
15
+ export interface OpenAPIWebhookData extends OpenAPICustomSpecProperties {
16
+ name: string;
17
+ method: string;
18
+ /** Servers to be used for this operation */
19
+ servers: OpenAPIV3.ServerObject[];
20
+ /** Spec of the webhook */
21
+ operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
58
22
  }
@@ -0,0 +1,35 @@
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ import type { OpenAPIContext } from '../context';
3
+ /**
4
+ * Generate an example from a reference object.
5
+ */
6
+ export declare function getExampleFromReference(ref: OpenAPIV3.ReferenceObject, context: OpenAPIContext): OpenAPIV3.ExampleObject;
7
+ /**
8
+ * Get examples from a media type object.
9
+ */
10
+ export declare function getExamplesFromMediaTypeObject(args: {
11
+ mediaType: string;
12
+ mediaTypeObject: OpenAPIV3.MediaTypeObject;
13
+ context: OpenAPIContext;
14
+ }): {
15
+ key: string;
16
+ example: OpenAPIV3.ExampleObject;
17
+ }[];
18
+ /**
19
+ * Get example from a schema object.
20
+ */
21
+ export declare function getExampleFromSchema(args: {
22
+ schema: OpenAPIV3.SchemaObject;
23
+ }): OpenAPIV3.ExampleObject;
24
+ /**
25
+ * Get the examples from a media type object.
26
+ */
27
+ export declare function getExamples(props: {
28
+ mediaTypeObject: OpenAPIV3.MediaTypeObject;
29
+ mediaType: string;
30
+ context: OpenAPIContext;
31
+ }): {
32
+ key: string;
33
+ label: string;
34
+ body: import("react").JSX.Element;
35
+ }[];
@@ -0,0 +1,103 @@
1
+ import { OpenAPIExample } from '../OpenAPIExample';
2
+ import { generateSchemaExample } from '../generateSchemaExample';
3
+ import { tString } from '../translate';
4
+ import { checkIsReference } from '../utils';
5
+ /**
6
+ * Generate an example from a reference object.
7
+ */
8
+ export function getExampleFromReference(ref, context) {
9
+ return {
10
+ summary: tString(context.translation, 'unresolved_reference'),
11
+ value: { $ref: ref.$ref },
12
+ };
13
+ }
14
+ /**
15
+ * Get examples from a media type object.
16
+ */
17
+ export function getExamplesFromMediaTypeObject(args) {
18
+ var _a;
19
+ var _b, _c;
20
+ var mediaTypeObject = args.mediaTypeObject, mediaType = args.mediaType, context = args.context;
21
+ if (mediaTypeObject.examples) {
22
+ return Object.entries(mediaTypeObject.examples).map(function (_a) {
23
+ var key = _a[0], example = _a[1];
24
+ return {
25
+ key: key,
26
+ example: checkIsReference(example)
27
+ ? getExampleFromReference(example, context)
28
+ : example,
29
+ };
30
+ });
31
+ }
32
+ if (mediaTypeObject.example) {
33
+ return [{ key: 'default', example: { value: mediaTypeObject.example } }];
34
+ }
35
+ if (mediaTypeObject.schema) {
36
+ if (mediaType === 'application/xml') {
37
+ // @TODO normally we should use the name of the schema but we don't have it
38
+ // fix it when we got the reference name
39
+ var root = (_c = (_b = mediaTypeObject.schema.xml) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : 'object';
40
+ return [
41
+ {
42
+ key: 'default',
43
+ example: {
44
+ value: (_a = {},
45
+ _a[root] = generateSchemaExample(mediaTypeObject.schema, {
46
+ xml: mediaType === 'application/xml',
47
+ mode: 'read',
48
+ }),
49
+ _a),
50
+ },
51
+ },
52
+ ];
53
+ }
54
+ return [
55
+ {
56
+ key: 'default',
57
+ example: {
58
+ value: generateSchemaExample(mediaTypeObject.schema, {
59
+ mode: 'read',
60
+ }),
61
+ },
62
+ },
63
+ ];
64
+ }
65
+ return [];
66
+ }
67
+ /**
68
+ * Get example from a schema object.
69
+ */
70
+ export function getExampleFromSchema(args) {
71
+ var schema = args.schema;
72
+ if (schema.example) {
73
+ return { value: schema.example };
74
+ }
75
+ return { value: generateSchemaExample(schema, { mode: 'read' }) };
76
+ }
77
+ /**
78
+ * Get the examples from a media type object.
79
+ */
80
+ export function getExamples(props) {
81
+ var mediaTypeObject = props.mediaTypeObject, mediaType = props.mediaType, context = props.context;
82
+ var examples = getExamplesFromMediaTypeObject({ mediaTypeObject: mediaTypeObject, mediaType: mediaType, context: context });
83
+ var syntax = getSyntaxFromMediaType(mediaType);
84
+ return examples.map(function (example) {
85
+ return {
86
+ key: example.key,
87
+ label: example.example.summary || example.key,
88
+ body: (<OpenAPIExample example={example.example} context={props.context} syntax={syntax}/>),
89
+ };
90
+ });
91
+ }
92
+ /**
93
+ * Get the syntax from a media type.
94
+ */
95
+ function getSyntaxFromMediaType(mediaType) {
96
+ if (mediaType.includes('json')) {
97
+ return 'json';
98
+ }
99
+ if (mediaType === 'application/xml') {
100
+ return 'xml';
101
+ }
102
+ return 'text';
103
+ }
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { AnyObject, OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
2
+ import type { OpenAPIUniversalContext } from './context';
2
3
  export declare function checkIsReference(input: unknown): input is OpenAPIV3.ReferenceObject;
3
4
  export declare function createStateKey(key: string, scope?: string): string;
4
5
  /**
@@ -29,3 +30,20 @@ export declare function parameterToProperty(parameter: OpenAPIV3.ParameterObject
29
30
  schema: OpenAPIV3.SchemaObject;
30
31
  required: boolean | undefined;
31
32
  };
33
+ /**
34
+ * Get the class name for a status code.
35
+ * 1xx: informational
36
+ * 2xx: success
37
+ * 3xx: redirect
38
+ * 4xx, 5xx: error
39
+ */
40
+ export declare function getStatusCodeClassName(statusCode: number | string): string;
41
+ /**
42
+ * Get a default label for a status code.
43
+ * This is used when there is no label provided in the OpenAPI spec.
44
+ * 1xx: Information
45
+ * 2xx: Success
46
+ * 3xx: Redirect
47
+ * 4xx, 5xx: Error
48
+ */
49
+ export declare function getStatusCodeDefaultLabel(statusCode: number | string, context: OpenAPIUniversalContext): string;
package/dist/utils.js CHANGED
@@ -10,6 +10,7 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { stringifyOpenAPI } from './stringifyOpenAPI';
13
+ import { tString } from './translate';
13
14
  export function checkIsReference(input) {
14
15
  return typeof input === 'object' && !!input && '$ref' in input;
15
16
  }
@@ -127,3 +128,59 @@ function shouldDisplayExample(schema) {
127
128
  schema.example !== null &&
128
129
  Object.keys(schema.example).length > 0));
129
130
  }
131
+ /**
132
+ * Get the class name for a status code.
133
+ * 1xx: informational
134
+ * 2xx: success
135
+ * 3xx: redirect
136
+ * 4xx, 5xx: error
137
+ */
138
+ export function getStatusCodeClassName(statusCode) {
139
+ var category = getStatusCodeCategory(statusCode);
140
+ switch (category) {
141
+ case 1:
142
+ return 'informational';
143
+ case 2:
144
+ return 'success';
145
+ case 3:
146
+ return 'redirect';
147
+ case 4:
148
+ case 5:
149
+ return 'error';
150
+ default:
151
+ return 'unknown';
152
+ }
153
+ }
154
+ /**
155
+ * Get a default label for a status code.
156
+ * This is used when there is no label provided in the OpenAPI spec.
157
+ * 1xx: Information
158
+ * 2xx: Success
159
+ * 3xx: Redirect
160
+ * 4xx, 5xx: Error
161
+ */
162
+ export function getStatusCodeDefaultLabel(statusCode, context) {
163
+ var category = getStatusCodeCategory(statusCode);
164
+ switch (category) {
165
+ case 1:
166
+ return tString(context.translation, 'information');
167
+ case 2:
168
+ return tString(context.translation, 'success');
169
+ case 3:
170
+ return tString(context.translation, 'redirect');
171
+ case 4:
172
+ case 5:
173
+ return tString(context.translation, 'error');
174
+ default:
175
+ return '';
176
+ }
177
+ }
178
+ function getStatusCodeCategory(statusCode) {
179
+ var code = typeof statusCode === 'string' ? Number.parseInt(statusCode, 10) : statusCode;
180
+ if (Number.isNaN(code) || code < 100 || code >= 600) {
181
+ return 'unknown';
182
+ }
183
+ // Determine the category of the status code based on the first digit
184
+ var category = Math.floor(code / 100);
185
+ return category;
186
+ }
package/package.json CHANGED
@@ -8,12 +8,12 @@
8
8
  "default": "./dist/index.js"
9
9
  }
10
10
  },
11
- "version": "1.1.9",
11
+ "version": "1.2.0",
12
12
  "sideEffects": false,
13
13
  "dependencies": {
14
14
  "@gitbook/openapi-parser": "workspace:*",
15
- "@scalar/api-client-react": "^1.2.5",
16
- "@scalar/oas-utils": "^0.2.120",
15
+ "@scalar/api-client-react": "^1.2.19",
16
+ "@scalar/oas-utils": "^0.2.130",
17
17
  "clsx": "^2.1.1",
18
18
  "flatted": "^3.2.9",
19
19
  "json-xml-parse": "^1.3.0",
@@ -1,9 +1,10 @@
1
1
  'use client';
2
2
 
3
3
  import clsx from 'clsx';
4
- import { useRef, useState } from 'react';
4
+ import { useRef } from 'react';
5
5
  import { mergeProps, useButton, useDisclosure, useFocusRing } from 'react-aria';
6
6
  import { useDisclosureState } from 'react-stately';
7
+ import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
7
8
  import { Section, SectionBody, SectionHeader, SectionHeaderContent } from './StaticSection';
8
9
 
9
10
  interface InteractiveSectionTab {
@@ -34,6 +35,10 @@ export function InteractiveSection(props: {
34
35
  header?: React.ReactNode;
35
36
  /** Children to display within the container */
36
37
  overlay?: React.ReactNode;
38
+ /** State key to use with a store */
39
+ stateKey?: string;
40
+ /** Icon for the tabs select */
41
+ selectIcon?: React.ReactNode;
37
42
  }) {
38
43
  const {
39
44
  id,
@@ -45,12 +50,9 @@ export function InteractiveSection(props: {
45
50
  header,
46
51
  overlay,
47
52
  toggleIcon = '▶',
53
+ selectIcon,
54
+ stateKey = 'interactive-section',
48
55
  } = props;
49
-
50
- const [selectedTabKey, setSelectedTab] = useState(defaultTab);
51
- const selectedTab: InteractiveSectionTab | undefined =
52
- tabs.find((tab) => tab.key === selectedTabKey) ?? tabs[0];
53
-
54
56
  const state = useDisclosureState({
55
57
  defaultExpanded: defaultOpened,
56
58
  });
@@ -59,6 +61,10 @@ export function InteractiveSection(props: {
59
61
  const { buttonProps: triggerProps, panelProps } = useDisclosure({}, state, panelRef);
60
62
  const { buttonProps } = useButton(triggerProps, triggerRef);
61
63
  const { isFocusVisible, focusProps } = useFocusRing();
64
+ const store = useSelectState(stateKey, defaultTab);
65
+
66
+ const selectedTab: InteractiveSectionTab | undefined =
67
+ tabs.find((tab) => tab.key === store.key) ?? tabs[0];
62
68
 
63
69
  return (
64
70
  <Section
@@ -96,6 +102,7 @@ export function InteractiveSection(props: {
96
102
  ) : null}
97
103
  {header}
98
104
  </SectionHeaderContent>
105
+ {/* biome-ignore lint/a11y/useKeyWithClickEvents: we prevent default here */}
99
106
  <div
100
107
  className={clsx(
101
108
  'openapi-section-header-controls',
@@ -106,24 +113,21 @@ export function InteractiveSection(props: {
106
113
  }}
107
114
  >
108
115
  {tabs.length > 1 ? (
109
- <select
110
- className={clsx(
111
- 'openapi-section-select',
112
- 'openapi-select',
113
- `${className}-tabs-select`
114
- )}
115
- value={selectedTab?.key ?? ''}
116
- onChange={(event) => {
117
- setSelectedTab(event.target.value);
116
+ <OpenAPISelect
117
+ stateKey={stateKey}
118
+ items={tabs}
119
+ onSelectionChange={() => {
118
120
  state.expand();
119
121
  }}
122
+ icon={selectIcon}
123
+ placement="bottom end"
120
124
  >
121
125
  {tabs.map((tab) => (
122
- <option key={tab.key} value={tab.key}>
126
+ <OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
123
127
  {tab.label}
124
- </option>
128
+ </OpenAPISelectItem>
125
129
  ))}
126
- </select>
130
+ </OpenAPISelect>
127
131
  ) : null}
128
132
  </div>
129
133
  </SectionHeader>
@@ -3,15 +3,15 @@ import {
3
3
  OpenAPIMediaTypeExamplesBody,
4
4
  OpenAPIMediaTypeExamplesSelector,
5
5
  } from './OpenAPICodeSampleInteractive';
6
- import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
6
+ import { OpenAPICodeSampleBody } from './OpenAPICodeSampleSelector';
7
7
  import { ScalarApiButton } from './ScalarApiButton';
8
- import { StaticSection } from './StaticSection';
9
8
  import { type CodeSampleGenerator, codeSampleGenerators } from './code-samples';
9
+ import { type OpenAPIContext, getOpenAPIClientContext } from './context';
10
10
  import { generateMediaTypeExamples, generateSchemaExample } from './generateSchemaExample';
11
11
  import { stringifyOpenAPI } from './stringifyOpenAPI';
12
- import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
12
+ import type { OpenAPIOperationData } from './types';
13
13
  import { getDefaultServerURL } from './util/server';
14
- import { checkIsReference, createStateKey } from './utils';
14
+ import { checkIsReference } from './utils';
15
15
 
16
16
  const CUSTOM_CODE_SAMPLES_KEYS = ['x-custom-examples', 'x-code-samples', 'x-codeSamples'] as const;
17
17
 
@@ -21,9 +21,9 @@ const CUSTOM_CODE_SAMPLES_KEYS = ['x-custom-examples', 'x-code-samples', 'x-code
21
21
  */
22
22
  export function OpenAPICodeSample(props: {
23
23
  data: OpenAPIOperationData;
24
- context: OpenAPIContextProps;
24
+ context: OpenAPIContext;
25
25
  }) {
26
- const { data } = props;
26
+ const { data, context } = props;
27
27
 
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) {
@@ -45,11 +45,12 @@ export function OpenAPICodeSample(props: {
45
45
  }
46
46
 
47
47
  return (
48
- <OpenAPITabs stateKey={createStateKey('codesample')} items={samples}>
49
- <StaticSection header={<OpenAPITabsList />} className="openapi-codesample">
50
- <OpenAPITabsPanels />
51
- </StaticSection>
52
- </OpenAPITabs>
48
+ <OpenAPICodeSampleBody
49
+ context={getOpenAPIClientContext(context)}
50
+ data={data}
51
+ items={samples}
52
+ selectIcon={context.icons.chevronDown}
53
+ />
53
54
  );
54
55
  }
55
56
 
@@ -58,7 +59,7 @@ export function OpenAPICodeSample(props: {
58
59
  */
59
60
  function generateCodeSamples(props: {
60
61
  data: OpenAPIOperationData;
61
- context: OpenAPIContextProps;
62
+ context: OpenAPIContext;
62
63
  }) {
63
64
  const { data, context } = props;
64
65
 
@@ -153,6 +154,7 @@ function generateCodeSamples(props: {
153
154
  method={data.method}
154
155
  path={data.path}
155
156
  renderers={renderers}
157
+ blockKey={context.blockKey}
156
158
  />
157
159
  ),
158
160
  footer: (
@@ -189,7 +191,7 @@ export interface MediaTypeRenderer {
189
191
  function OpenAPICodeSampleFooter(props: {
190
192
  data: OpenAPIOperationData;
191
193
  renderers: MediaTypeRenderer[];
192
- context: OpenAPIContextProps;
194
+ context: OpenAPIContext;
193
195
  }) {
194
196
  const { data, context, renderers } = props;
195
197
  const { method, path } = data;
@@ -213,11 +215,20 @@ function OpenAPICodeSampleFooter(props: {
213
215
  method={data.method}
214
216
  path={data.path}
215
217
  renderers={renderers}
218
+ selectIcon={context.icons.chevronDown}
219
+ blockKey={context.blockKey}
216
220
  />
217
221
  ) : (
218
222
  <span />
219
223
  )}
220
- {!hideTryItPanel && <ScalarApiButton method={method} path={path} specUrl={specUrl} />}
224
+ {!hideTryItPanel && (
225
+ <ScalarApiButton
226
+ context={getOpenAPIClientContext(context)}
227
+ method={method}
228
+ path={path}
229
+ specUrl={specUrl}
230
+ />
231
+ )}
221
232
  </div>
222
233
  );
223
234
  }
@@ -227,7 +238,7 @@ function OpenAPICodeSampleFooter(props: {
227
238
  */
228
239
  function getCustomCodeSamples(props: {
229
240
  data: OpenAPIOperationData;
230
- context: OpenAPIContextProps;
241
+ context: OpenAPIContext;
231
242
  }) {
232
243
  const { data, context } = props;
233
244