@gitbook/react-openapi 1.1.8 → 1.1.10
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.
- package/CHANGELOG.md +21 -0
- package/dist/InteractiveSection.jsx +7 -6
- package/dist/OpenAPICodeSample.d.ts +2 -2
- package/dist/OpenAPICodeSample.jsx +3 -8
- package/dist/OpenAPICodeSampleInteractive.jsx +31 -19
- package/dist/OpenAPICodeSampleSelector.d.ts +15 -0
- package/dist/OpenAPICodeSampleSelector.jsx +49 -0
- package/dist/OpenAPIExample.d.ts +34 -0
- package/dist/OpenAPIExample.jsx +103 -0
- package/dist/OpenAPIOperation.d.ts +2 -2
- package/dist/OpenAPIOperation.jsx +3 -7
- package/dist/OpenAPIPath.d.ts +10 -2
- package/dist/OpenAPIPath.jsx +9 -4
- package/dist/OpenAPIResponse.jsx +3 -3
- package/dist/OpenAPIResponseExample.d.ts +2 -2
- package/dist/OpenAPIResponseExample.jsx +4 -90
- package/dist/OpenAPIResponses.jsx +23 -10
- package/dist/OpenAPISchema.jsx +26 -15
- package/dist/OpenAPISchemaName.jsx +2 -7
- package/dist/OpenAPISecurities.jsx +6 -6
- package/dist/OpenAPISelect.d.ts +15 -0
- package/dist/OpenAPISelect.jsx +32 -0
- package/dist/OpenAPITabs.jsx +9 -9
- package/dist/context.d.ts +54 -0
- package/dist/context.js +11 -0
- package/dist/generateSchemaExample.d.ts +1 -1
- package/dist/generateSchemaExample.js +28 -26
- package/dist/getOrCreateStoreByKey.d.ts +10 -0
- package/dist/getOrCreateStoreByKey.js +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/resolveOpenAPIOperation.js +10 -5
- package/dist/schemas/OpenAPISchemas.d.ts +5 -6
- package/dist/schemas/OpenAPISchemas.jsx +45 -38
- package/dist/schemas/resolveOpenAPISchemas.d.ts +4 -3
- package/dist/schemas/resolveOpenAPISchemas.js +0 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types.d.ts +32 -26
- package/package.json +1 -1
- package/src/InteractiveSection.tsx +10 -8
- package/src/OpenAPICodeSample.tsx +8 -15
- package/src/OpenAPICodeSampleInteractive.tsx +43 -26
- package/src/OpenAPICodeSampleSelector.tsx +87 -0
- package/src/OpenAPIExample.tsx +129 -0
- package/src/OpenAPIOperation.tsx +6 -10
- package/src/OpenAPIPath.tsx +23 -6
- package/src/OpenAPIResponse.tsx +9 -7
- package/src/OpenAPIResponseExample.tsx +13 -113
- package/src/OpenAPIResponses.tsx +37 -12
- package/src/OpenAPISchema.tsx +40 -25
- package/src/OpenAPISchemaName.tsx +2 -8
- package/src/OpenAPISecurities.tsx +22 -9
- package/src/OpenAPISelect.tsx +70 -0
- package/src/OpenAPITabs.tsx +9 -9
- package/src/context.ts +64 -0
- package/src/generateSchemaExample.test.ts +1020 -0
- package/src/generateSchemaExample.ts +103 -36
- package/src/getOrCreateStoreByKey.ts +35 -0
- package/src/index.ts +1 -1
- package/src/resolveOpenAPIOperation.ts +14 -3
- package/src/schemas/OpenAPISchemas.tsx +75 -70
- package/src/schemas/resolveOpenAPISchemas.ts +4 -5
- package/src/types.ts +36 -29
- package/dist/useSyncedTabsGlobalState.d.ts +0 -10
- package/dist/useSyncedTabsGlobalState.js +0 -20
- package/src/useSyncedTabsGlobalState.ts +0 -35
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
2
|
import { Markdown } from './Markdown';
|
|
3
|
+
import {
|
|
4
|
+
OpenAPIEmptyExample,
|
|
5
|
+
OpenAPIExample,
|
|
6
|
+
getExampleFromReference,
|
|
7
|
+
getExamplesFromMediaTypeObject,
|
|
8
|
+
} from './OpenAPIExample';
|
|
3
9
|
import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
|
|
4
10
|
import { StaticSection } from './StaticSection';
|
|
5
|
-
import {
|
|
6
|
-
import { json2xml } from './json2xml';
|
|
7
|
-
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
8
|
-
import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
|
|
11
|
+
import type { OpenAPIContext, OpenAPIOperationData } from './types';
|
|
9
12
|
import { checkIsReference, createStateKey, resolveDescription } from './utils';
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -13,7 +16,7 @@ import { checkIsReference, createStateKey, resolveDescription } from './utils';
|
|
|
13
16
|
*/
|
|
14
17
|
export function OpenAPIResponseExample(props: {
|
|
15
18
|
data: OpenAPIOperationData;
|
|
16
|
-
context:
|
|
19
|
+
context: OpenAPIContext;
|
|
17
20
|
}) {
|
|
18
21
|
const { data, context } = props;
|
|
19
22
|
|
|
@@ -62,7 +65,7 @@ export function OpenAPIResponseExample(props: {
|
|
|
62
65
|
return {
|
|
63
66
|
key: key,
|
|
64
67
|
label: key,
|
|
65
|
-
body: <
|
|
68
|
+
body: <OpenAPIEmptyExample />,
|
|
66
69
|
footer: description ? <Markdown source={description} /> : undefined,
|
|
67
70
|
};
|
|
68
71
|
}
|
|
@@ -81,7 +84,7 @@ export function OpenAPIResponseExample(props: {
|
|
|
81
84
|
|
|
82
85
|
return (
|
|
83
86
|
<OpenAPITabs stateKey={createStateKey('response-example')} items={tabs}>
|
|
84
|
-
<StaticSection header={<OpenAPITabsList />} className="openapi-
|
|
87
|
+
<StaticSection header={<OpenAPITabsList />} className="openapi-panel">
|
|
85
88
|
<OpenAPITabsPanels />
|
|
86
89
|
</StaticSection>
|
|
87
90
|
</OpenAPITabs>
|
|
@@ -89,7 +92,7 @@ export function OpenAPIResponseExample(props: {
|
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
function OpenAPIResponse(props: {
|
|
92
|
-
context:
|
|
95
|
+
context: OpenAPIContext;
|
|
93
96
|
content: {
|
|
94
97
|
[media: string]: OpenAPIV3.MediaTypeObject;
|
|
95
98
|
};
|
|
@@ -141,7 +144,7 @@ function OpenAPIResponse(props: {
|
|
|
141
144
|
function OpenAPIResponseMediaType(props: {
|
|
142
145
|
mediaTypeObject: OpenAPIV3.MediaTypeObject;
|
|
143
146
|
mediaType: string;
|
|
144
|
-
context:
|
|
147
|
+
context: OpenAPIContext;
|
|
145
148
|
}) {
|
|
146
149
|
const { mediaTypeObject, mediaType } = props;
|
|
147
150
|
const examples = getExamplesFromMediaTypeObject({ mediaTypeObject, mediaType });
|
|
@@ -149,7 +152,7 @@ function OpenAPIResponseMediaType(props: {
|
|
|
149
152
|
const firstExample = examples[0];
|
|
150
153
|
|
|
151
154
|
if (!firstExample) {
|
|
152
|
-
return <
|
|
155
|
+
return <OpenAPIEmptyExample />;
|
|
153
156
|
}
|
|
154
157
|
|
|
155
158
|
if (examples.length === 1) {
|
|
@@ -184,42 +187,6 @@ function OpenAPIResponseMediaType(props: {
|
|
|
184
187
|
);
|
|
185
188
|
}
|
|
186
189
|
|
|
187
|
-
/**
|
|
188
|
-
* Display an example.
|
|
189
|
-
*/
|
|
190
|
-
function OpenAPIExample(props: {
|
|
191
|
-
example: OpenAPIV3.ExampleObject;
|
|
192
|
-
context: OpenAPIContextProps;
|
|
193
|
-
syntax: string;
|
|
194
|
-
}) {
|
|
195
|
-
const { example, context, syntax } = props;
|
|
196
|
-
const code = stringifyExample({ example, xml: syntax === 'xml' });
|
|
197
|
-
|
|
198
|
-
if (code === null) {
|
|
199
|
-
return <OpenAPIEmptyResponseExample />;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return context.renderCodeBlock({ code, syntax });
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function stringifyExample(args: { example: OpenAPIV3.ExampleObject; xml: boolean }): string | null {
|
|
206
|
-
const { example, xml } = args;
|
|
207
|
-
|
|
208
|
-
if (!example.value) {
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (typeof example.value === 'string') {
|
|
213
|
-
return example.value;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (xml) {
|
|
217
|
-
return json2xml(example.value);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return stringifyOpenAPI(example.value, null, 2);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
190
|
/**
|
|
224
191
|
* Get the syntax from a media type.
|
|
225
192
|
*/
|
|
@@ -234,70 +201,3 @@ function getSyntaxFromMediaType(mediaType: string): string {
|
|
|
234
201
|
|
|
235
202
|
return 'text';
|
|
236
203
|
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Get examples from a media type object.
|
|
240
|
-
*/
|
|
241
|
-
function getExamplesFromMediaTypeObject(args: {
|
|
242
|
-
mediaType: string;
|
|
243
|
-
mediaTypeObject: OpenAPIV3.MediaTypeObject;
|
|
244
|
-
}): { key: string; example: OpenAPIV3.ExampleObject }[] {
|
|
245
|
-
const { mediaTypeObject, mediaType } = args;
|
|
246
|
-
if (mediaTypeObject.examples) {
|
|
247
|
-
return Object.entries(mediaTypeObject.examples).map(([key, example]) => {
|
|
248
|
-
return {
|
|
249
|
-
key,
|
|
250
|
-
example: checkIsReference(example) ? getExampleFromReference(example) : example,
|
|
251
|
-
};
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (mediaTypeObject.example) {
|
|
256
|
-
return [{ key: 'default', example: { value: mediaTypeObject.example } }];
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (mediaTypeObject.schema) {
|
|
260
|
-
if (mediaType === 'application/xml') {
|
|
261
|
-
// @TODO normally we should use the name of the schema but we don't have it
|
|
262
|
-
// fix it when we got the reference name
|
|
263
|
-
const root = mediaTypeObject.schema.xml?.name ?? 'object';
|
|
264
|
-
return [
|
|
265
|
-
{
|
|
266
|
-
key: 'default',
|
|
267
|
-
example: {
|
|
268
|
-
value: {
|
|
269
|
-
[root]: generateSchemaExample(mediaTypeObject.schema, {
|
|
270
|
-
xml: mediaType === 'application/xml',
|
|
271
|
-
}),
|
|
272
|
-
},
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
];
|
|
276
|
-
}
|
|
277
|
-
return [
|
|
278
|
-
{
|
|
279
|
-
key: 'default',
|
|
280
|
-
example: { value: generateSchemaExample(mediaTypeObject.schema) },
|
|
281
|
-
},
|
|
282
|
-
];
|
|
283
|
-
}
|
|
284
|
-
return [];
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Empty response example.
|
|
289
|
-
*/
|
|
290
|
-
function OpenAPIEmptyResponseExample() {
|
|
291
|
-
return (
|
|
292
|
-
<pre className="openapi-response-example-empty">
|
|
293
|
-
<p>No body</p>
|
|
294
|
-
</pre>
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Generate an example from a reference object.
|
|
300
|
-
*/
|
|
301
|
-
function getExampleFromReference(ref: OpenAPIV3.ReferenceObject): OpenAPIV3.ExampleObject {
|
|
302
|
-
return { summary: 'Unresolved reference', value: { $ref: ref.$ref } };
|
|
303
|
-
}
|
package/src/OpenAPIResponses.tsx
CHANGED
|
@@ -21,7 +21,42 @@ export function OpenAPIResponses(props: {
|
|
|
21
21
|
icon={context.icons.chevronRight}
|
|
22
22
|
groups={Object.entries(responses).map(
|
|
23
23
|
([statusCode, response]: [string, OpenAPIV3.ResponseObject]) => {
|
|
24
|
-
const
|
|
24
|
+
const tabs = (() => {
|
|
25
|
+
// If there is no content, but there are headers, we need to show the headers
|
|
26
|
+
if (
|
|
27
|
+
(!response.content || !Object.keys(response.content).length) &&
|
|
28
|
+
response.headers &&
|
|
29
|
+
Object.keys(response.headers).length
|
|
30
|
+
) {
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
id: 'default',
|
|
34
|
+
body: (
|
|
35
|
+
<OpenAPIResponse
|
|
36
|
+
response={response}
|
|
37
|
+
mediaType={{}}
|
|
38
|
+
context={context}
|
|
39
|
+
/>
|
|
40
|
+
),
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return Object.entries(response.content ?? {}).map(
|
|
46
|
+
([contentType, mediaType]) => ({
|
|
47
|
+
id: contentType,
|
|
48
|
+
label: contentType,
|
|
49
|
+
body: (
|
|
50
|
+
<OpenAPIResponse
|
|
51
|
+
response={response}
|
|
52
|
+
mediaType={mediaType}
|
|
53
|
+
context={context}
|
|
54
|
+
/>
|
|
55
|
+
),
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
})();
|
|
59
|
+
|
|
25
60
|
const description = response.description;
|
|
26
61
|
|
|
27
62
|
return {
|
|
@@ -39,17 +74,7 @@ export function OpenAPIResponses(props: {
|
|
|
39
74
|
) : null}
|
|
40
75
|
</div>
|
|
41
76
|
),
|
|
42
|
-
tabs
|
|
43
|
-
id: contentType,
|
|
44
|
-
label: contentType,
|
|
45
|
-
body: (
|
|
46
|
-
<OpenAPIResponse
|
|
47
|
-
response={response}
|
|
48
|
-
mediaType={mediaType}
|
|
49
|
-
context={context}
|
|
50
|
-
/>
|
|
51
|
-
),
|
|
52
|
-
})),
|
|
77
|
+
tabs,
|
|
53
78
|
};
|
|
54
79
|
}
|
|
55
80
|
)}
|
package/src/OpenAPISchema.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import { OpenAPICopyButton } from './OpenAPICopyButton';
|
|
|
11
11
|
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
|
|
12
12
|
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
|
13
13
|
import { retrocycle } from './decycle';
|
|
14
|
+
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
14
15
|
import type { OpenAPIClientContext } from './types';
|
|
15
16
|
import { checkIsReference, resolveDescription, resolveFirstExample } from './utils';
|
|
16
17
|
|
|
@@ -145,17 +146,23 @@ function OpenAPIRootSchema(props: {
|
|
|
145
146
|
|
|
146
147
|
const id = useId();
|
|
147
148
|
const properties = getSchemaProperties(schema);
|
|
149
|
+
const description = resolveDescription(schema);
|
|
148
150
|
|
|
149
151
|
if (properties?.length) {
|
|
150
152
|
const circularRefs = new Map(parentCircularRefs);
|
|
151
153
|
circularRefs.set(schema, id);
|
|
152
154
|
|
|
153
155
|
return (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
<>
|
|
157
|
+
{description ? (
|
|
158
|
+
<Markdown source={description} className="openapi-schema-root-description" />
|
|
159
|
+
) : null}
|
|
160
|
+
<OpenAPISchemaProperties
|
|
161
|
+
properties={properties}
|
|
162
|
+
circularRefs={circularRefs}
|
|
163
|
+
context={context}
|
|
164
|
+
/>
|
|
165
|
+
</>
|
|
159
166
|
);
|
|
160
167
|
}
|
|
161
168
|
|
|
@@ -275,22 +282,20 @@ function OpenAPISchemaEnum(props: {
|
|
|
275
282
|
}
|
|
276
283
|
|
|
277
284
|
return (
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
{
|
|
282
|
-
<
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
>
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
</div>
|
|
293
|
-
</div>
|
|
285
|
+
<span className="openapi-schema-enum">
|
|
286
|
+
Available options:{' '}
|
|
287
|
+
{enumValues.map((item, index) => (
|
|
288
|
+
<span key={index} className="openapi-schema-enum-value">
|
|
289
|
+
<OpenAPICopyButton
|
|
290
|
+
value={item.value}
|
|
291
|
+
label={item.description}
|
|
292
|
+
withTooltip={!!item.description}
|
|
293
|
+
>
|
|
294
|
+
<code>{`${item.value}`}</code>
|
|
295
|
+
</OpenAPICopyButton>
|
|
296
|
+
</span>
|
|
297
|
+
))}
|
|
298
|
+
</span>
|
|
294
299
|
);
|
|
295
300
|
}
|
|
296
301
|
|
|
@@ -324,15 +329,25 @@ function OpenAPISchemaPresentation(props: { property: OpenAPISchemaPropertyEntry
|
|
|
324
329
|
{description ? (
|
|
325
330
|
<Markdown source={description} className="openapi-schema-description" />
|
|
326
331
|
) : null}
|
|
332
|
+
{schema.default !== undefined ? (
|
|
333
|
+
<span className="openapi-schema-default">
|
|
334
|
+
Default:{' '}
|
|
335
|
+
<code>
|
|
336
|
+
{typeof schema.default === 'string' && schema.default
|
|
337
|
+
? schema.default
|
|
338
|
+
: stringifyOpenAPI(schema.default)}
|
|
339
|
+
</code>
|
|
340
|
+
</span>
|
|
341
|
+
) : null}
|
|
327
342
|
{typeof example === 'string' ? (
|
|
328
|
-
<
|
|
343
|
+
<span className="openapi-schema-example">
|
|
329
344
|
Example: <code>{example}</code>
|
|
330
|
-
</
|
|
345
|
+
</span>
|
|
331
346
|
) : null}
|
|
332
347
|
{schema.pattern ? (
|
|
333
|
-
<
|
|
348
|
+
<span className="openapi-schema-pattern">
|
|
334
349
|
Pattern: <code>{schema.pattern}</code>
|
|
335
|
-
</
|
|
350
|
+
</span>
|
|
336
351
|
) : null}
|
|
337
352
|
<OpenAPISchemaEnum schema={schema} />
|
|
338
353
|
</div>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
2
|
import type React from 'react';
|
|
3
|
-
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
4
3
|
|
|
5
4
|
interface OpenAPISchemaNameProps {
|
|
6
5
|
schema?: OpenAPIV3.SchemaObject;
|
|
@@ -19,7 +18,7 @@ export function OpenAPISchemaName(props: OpenAPISchemaNameProps) {
|
|
|
19
18
|
const additionalItems = schema && getAdditionalItems(schema);
|
|
20
19
|
|
|
21
20
|
return (
|
|
22
|
-
<
|
|
21
|
+
<span className="openapi-schema-name">
|
|
23
22
|
{propertyName ? (
|
|
24
23
|
<span data-deprecated={schema?.deprecated} className="openapi-schema-propertyname">
|
|
25
24
|
{propertyName}
|
|
@@ -41,7 +40,7 @@ export function OpenAPISchemaName(props: OpenAPISchemaNameProps) {
|
|
|
41
40
|
<span className="openapi-schema-optional">optional</span>
|
|
42
41
|
)}
|
|
43
42
|
{schema?.deprecated ? <span className="openapi-deprecated">Deprecated</span> : null}
|
|
44
|
-
</
|
|
43
|
+
</span>
|
|
45
44
|
);
|
|
46
45
|
}
|
|
47
46
|
|
|
@@ -56,11 +55,6 @@ function getAdditionalItems(schema: OpenAPIV3.SchemaObject): string {
|
|
|
56
55
|
additionalItems += ` · max: ${schema.maximum || schema.maxLength || schema.maxItems}`;
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
// If the schema has a default value, we display it
|
|
60
|
-
if (typeof schema.default !== 'undefined') {
|
|
61
|
-
additionalItems += ` · default: ${stringifyOpenAPI(schema.default)}`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
58
|
if (schema.nullable) {
|
|
65
59
|
additionalItems = ' | nullable';
|
|
66
60
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import type { OpenAPIV3_1 } from '@gitbook/openapi-parser';
|
|
2
1
|
import { InteractiveSection } from './InteractiveSection';
|
|
3
2
|
import { Markdown } from './Markdown';
|
|
4
3
|
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
|
5
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
OpenAPIClientContext,
|
|
6
|
+
OpenAPIOperationData,
|
|
7
|
+
OpenAPISecurityWithRequired,
|
|
8
|
+
} from './types';
|
|
6
9
|
import { resolveDescription } from './utils';
|
|
7
10
|
|
|
8
11
|
/**
|
|
@@ -50,26 +53,36 @@ export function OpenAPISecurities(props: {
|
|
|
50
53
|
);
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
function getLabelForType(security:
|
|
56
|
+
function getLabelForType(security: OpenAPISecurityWithRequired) {
|
|
54
57
|
switch (security.type) {
|
|
55
58
|
case 'apiKey':
|
|
56
59
|
return (
|
|
57
60
|
<OpenAPISchemaName
|
|
58
61
|
propertyName={security.name ?? 'apiKey'}
|
|
59
62
|
type="string"
|
|
60
|
-
required
|
|
63
|
+
required={security.required}
|
|
61
64
|
/>
|
|
62
65
|
);
|
|
63
66
|
case 'http':
|
|
64
67
|
if (security.scheme === 'basic') {
|
|
65
|
-
return
|
|
68
|
+
return (
|
|
69
|
+
<OpenAPISchemaName
|
|
70
|
+
propertyName="Authorization"
|
|
71
|
+
type="string"
|
|
72
|
+
required={security.required}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
if (security.scheme === 'bearer') {
|
|
69
78
|
const description = resolveDescription(security);
|
|
70
79
|
return (
|
|
71
80
|
<>
|
|
72
|
-
<OpenAPISchemaName
|
|
81
|
+
<OpenAPISchemaName
|
|
82
|
+
propertyName="Authorization"
|
|
83
|
+
type="string"
|
|
84
|
+
required={security.required}
|
|
85
|
+
/>
|
|
73
86
|
{/** Show a default description if none is provided */}
|
|
74
87
|
{!description ? (
|
|
75
88
|
<Markdown
|
|
@@ -81,11 +94,11 @@ function getLabelForType(security: OpenAPIV3_1.SecuritySchemeObject) {
|
|
|
81
94
|
);
|
|
82
95
|
}
|
|
83
96
|
|
|
84
|
-
return <OpenAPISchemaName propertyName="HTTP" required />;
|
|
97
|
+
return <OpenAPISchemaName propertyName="HTTP" required={security.required} />;
|
|
85
98
|
case 'oauth2':
|
|
86
|
-
return <OpenAPISchemaName propertyName="OAuth2" required />;
|
|
99
|
+
return <OpenAPISchemaName propertyName="OAuth2" required={security.required} />;
|
|
87
100
|
case 'openIdConnect':
|
|
88
|
-
return <OpenAPISchemaName propertyName="OpenID Connect" required />;
|
|
101
|
+
return <OpenAPISchemaName propertyName="OpenID Connect" required={security.required} />;
|
|
89
102
|
default:
|
|
90
103
|
// @ts-ignore
|
|
91
104
|
return security.type;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
type Key,
|
|
7
|
+
ListBox,
|
|
8
|
+
ListBoxItem,
|
|
9
|
+
type ListBoxItemProps,
|
|
10
|
+
Popover,
|
|
11
|
+
type PopoverProps,
|
|
12
|
+
Select,
|
|
13
|
+
type SelectProps,
|
|
14
|
+
SelectValue,
|
|
15
|
+
} from 'react-aria-components';
|
|
16
|
+
|
|
17
|
+
export type OpenAPISelectItem = {
|
|
18
|
+
key: Key;
|
|
19
|
+
label: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
interface OpenAPISelectProps<T extends OpenAPISelectItem> extends Omit<SelectProps<T>, 'children'> {
|
|
23
|
+
items: T[];
|
|
24
|
+
children: React.ReactNode | ((item: T) => React.ReactNode);
|
|
25
|
+
selectedKey?: Key;
|
|
26
|
+
onChange?: (key: string | number) => void;
|
|
27
|
+
placement?: PopoverProps['placement'];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function OpenAPISelect<T extends OpenAPISelectItem>(props: OpenAPISelectProps<T>) {
|
|
31
|
+
const { items, children, className, placement } = props;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Select {...props} className={clsx('openapi-select', className)}>
|
|
35
|
+
<Button>
|
|
36
|
+
<SelectValue />
|
|
37
|
+
<span aria-hidden="true">
|
|
38
|
+
<svg
|
|
39
|
+
className="gb-icon"
|
|
40
|
+
style={{
|
|
41
|
+
maskImage:
|
|
42
|
+
"url('https://ka-p.fontawesome.com/releases/v6.6.0/svgs/regular/chevron-down.svg?v=2&token=a463935e93')",
|
|
43
|
+
maskRepeat: 'no-repeat',
|
|
44
|
+
maskPosition: 'center center',
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
</span>
|
|
48
|
+
</Button>
|
|
49
|
+
<Popover placement={placement} className="openapi-select-popover">
|
|
50
|
+
<ListBox className="openapi-select-listbox" items={items}>
|
|
51
|
+
{children}
|
|
52
|
+
</ListBox>
|
|
53
|
+
</Popover>
|
|
54
|
+
</Select>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function OpenAPISelectItem(props: ListBoxItemProps) {
|
|
59
|
+
return (
|
|
60
|
+
<ListBoxItem
|
|
61
|
+
{...props}
|
|
62
|
+
className={({ isFocused, isSelected }) =>
|
|
63
|
+
clsx('openapi-select-item', {
|
|
64
|
+
'openapi-select-item-focused': isFocused,
|
|
65
|
+
'openapi-select-item-selected': isSelected,
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
package/src/OpenAPITabs.tsx
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { type Key, Tab, TabList, TabPanel, Tabs, type TabsProps } from 'react-aria-components';
|
|
5
5
|
import { useEventCallback } from 'usehooks-ts';
|
|
6
|
-
import {
|
|
6
|
+
import { getOrCreateStoreByKey } from './getOrCreateStoreByKey';
|
|
7
7
|
|
|
8
8
|
export type TabItem = {
|
|
9
9
|
key: Key;
|
|
@@ -36,8 +36,8 @@ export function OpenAPITabs(
|
|
|
36
36
|
const { children, items, stateKey } = props;
|
|
37
37
|
const [tabKey, setTabKey] = useState<Key | null>(() => {
|
|
38
38
|
if (stateKey && typeof window !== 'undefined') {
|
|
39
|
-
const store =
|
|
40
|
-
const tabKey = store.getState().
|
|
39
|
+
const store = getOrCreateStoreByKey(stateKey);
|
|
40
|
+
const tabKey = store.getState().key;
|
|
41
41
|
if (tabKey) {
|
|
42
42
|
return tabKey;
|
|
43
43
|
}
|
|
@@ -60,10 +60,10 @@ export function OpenAPITabs(
|
|
|
60
60
|
if (!stateKey) {
|
|
61
61
|
return undefined;
|
|
62
62
|
}
|
|
63
|
-
const store =
|
|
63
|
+
const store = getOrCreateStoreByKey(stateKey);
|
|
64
64
|
return store.subscribe((state) => {
|
|
65
65
|
cancelDeferRef.current?.();
|
|
66
|
-
cancelDeferRef.current = defer(() => selectTab(state.
|
|
66
|
+
cancelDeferRef.current = defer(() => selectTab(state.key));
|
|
67
67
|
});
|
|
68
68
|
}, [stateKey, selectTab]);
|
|
69
69
|
useEffect(() => {
|
|
@@ -77,8 +77,8 @@ export function OpenAPITabs(
|
|
|
77
77
|
onSelectionChange={(tabKey) => {
|
|
78
78
|
selectTab(tabKey);
|
|
79
79
|
if (stateKey) {
|
|
80
|
-
const store =
|
|
81
|
-
store.setState({ tabKey });
|
|
80
|
+
const store = getOrCreateStoreByKey(stateKey);
|
|
81
|
+
store.setState({ key: tabKey });
|
|
82
82
|
}
|
|
83
83
|
}}
|
|
84
84
|
selectedKey={tabKey}
|
|
@@ -138,9 +138,9 @@ export function OpenAPITabsPanels() {
|
|
|
138
138
|
|
|
139
139
|
return (
|
|
140
140
|
<TabPanel id={key} className="openapi-tabs-panel">
|
|
141
|
-
<div className="openapi-
|
|
141
|
+
<div className="openapi-panel-body">{selectedTab.body}</div>
|
|
142
142
|
{selectedTab.footer ? (
|
|
143
|
-
<div className="openapi-
|
|
143
|
+
<div className="openapi-panel-footer">{selectedTab.footer}</div>
|
|
144
144
|
) : null}
|
|
145
145
|
</TabPanel>
|
|
146
146
|
);
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface OpenAPIClientContext {
|
|
2
|
+
/**
|
|
3
|
+
* Icons used in the block.
|
|
4
|
+
*/
|
|
5
|
+
icons: {
|
|
6
|
+
chevronDown: React.ReactNode;
|
|
7
|
+
chevronRight: React.ReactNode;
|
|
8
|
+
plus: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Force all sections to be opened by default.
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
defaultInteractiveOpened?: boolean;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The key of the block
|
|
19
|
+
*/
|
|
20
|
+
blockKey?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Optional id attached to the heading and used as an anchor.
|
|
24
|
+
*/
|
|
25
|
+
id?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface OpenAPIContext extends OpenAPIClientContext {
|
|
29
|
+
/**
|
|
30
|
+
* Render a code block.
|
|
31
|
+
*/
|
|
32
|
+
renderCodeBlock: (props: { code: string; syntax: string }) => React.ReactNode;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Render the heading of the operation.
|
|
36
|
+
*/
|
|
37
|
+
renderHeading: (props: {
|
|
38
|
+
deprecated: boolean;
|
|
39
|
+
title: string;
|
|
40
|
+
stability?: string;
|
|
41
|
+
}) => React.ReactNode;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Render the document of the operation.
|
|
45
|
+
*/
|
|
46
|
+
renderDocument: (props: { document: object }) => React.ReactNode;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Specification URL.
|
|
50
|
+
*/
|
|
51
|
+
specUrl: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get the client context from the OpenAPI context.
|
|
56
|
+
*/
|
|
57
|
+
export function getOpenAPIClientContext(context: OpenAPIContext): OpenAPIClientContext {
|
|
58
|
+
return {
|
|
59
|
+
icons: context.icons,
|
|
60
|
+
defaultInteractiveOpened: context.defaultInteractiveOpened,
|
|
61
|
+
blockKey: context.blockKey,
|
|
62
|
+
id: context.id,
|
|
63
|
+
};
|
|
64
|
+
}
|