fumadocs-openapi 8.1.3 → 8.1.4

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 (47) hide show
  1. package/dist/generate-file.d.ts.map +1 -1
  2. package/dist/generate-file.js +40 -23
  3. package/dist/playground/client.d.ts +5 -16
  4. package/dist/playground/client.d.ts.map +1 -1
  5. package/dist/playground/client.js +39 -44
  6. package/dist/playground/get-default-values.d.ts +2 -2
  7. package/dist/playground/get-default-values.d.ts.map +1 -1
  8. package/dist/playground/get-default-values.js +21 -22
  9. package/dist/playground/index.d.ts +4 -38
  10. package/dist/playground/index.d.ts.map +1 -1
  11. package/dist/playground/index.js +43 -139
  12. package/dist/playground/inputs.d.ts +11 -13
  13. package/dist/playground/inputs.d.ts.map +1 -1
  14. package/dist/playground/inputs.js +72 -129
  15. package/dist/playground/schema.d.ts +38 -0
  16. package/dist/playground/schema.d.ts.map +1 -0
  17. package/dist/playground/schema.js +93 -0
  18. package/dist/render/operation/get-request-data.d.ts +1 -2
  19. package/dist/render/operation/get-request-data.d.ts.map +1 -1
  20. package/dist/render/operation/get-request-data.js +2 -2
  21. package/dist/render/operation/index.d.ts.map +1 -1
  22. package/dist/render/operation/index.js +5 -5
  23. package/dist/render/schema.d.ts +3 -3
  24. package/dist/render/schema.d.ts.map +1 -1
  25. package/dist/render/schema.js +70 -100
  26. package/dist/ui/client.d.ts +3 -0
  27. package/dist/ui/client.d.ts.map +1 -1
  28. package/dist/ui/client.js +15 -0
  29. package/dist/ui/components/dialog.d.ts.map +1 -1
  30. package/dist/ui/components/dialog.js +4 -3
  31. package/dist/ui/components/select.js +1 -1
  32. package/dist/ui/index.js +1 -1
  33. package/dist/ui/server-select.d.ts +2 -7
  34. package/dist/ui/server-select.d.ts.map +1 -1
  35. package/dist/ui/server-select.js +52 -19
  36. package/dist/utils/combine-schema.d.ts.map +1 -1
  37. package/dist/utils/combine-schema.js +12 -2
  38. package/dist/utils/schema-to-string.d.ts +3 -0
  39. package/dist/utils/schema-to-string.d.ts.map +1 -0
  40. package/dist/utils/schema-to-string.js +62 -0
  41. package/dist/utils/schema.d.ts +9 -4
  42. package/dist/utils/schema.d.ts.map +1 -1
  43. package/dist/utils/schema.js +2 -0
  44. package/package.json +6 -5
  45. package/dist/playground/resolve.d.ts +0 -6
  46. package/dist/playground/resolve.d.ts.map +0 -1
  47. package/dist/playground/resolve.js +0 -14
@@ -0,0 +1,93 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Ajv2020 } from 'ajv/dist/2020';
3
+ import { createContext, useContext, useMemo, useState } from 'react';
4
+ import { useFormContext } from 'react-hook-form';
5
+ import { useEffectEvent } from 'fumadocs-core/utils/use-effect-event';
6
+ import { getDefaultValue } from '../playground/get-default-values.js';
7
+ const SchemaContext = createContext(undefined);
8
+ export const anyFields = {
9
+ type: ['string', 'number', 'boolean', 'array', 'object'],
10
+ items: true,
11
+ additionalProperties: true,
12
+ };
13
+ export function SchemaProvider({ references, fieldInfoMap, children, }) {
14
+ const ajv = useMemo(() => new Ajv2020({
15
+ strict: false,
16
+ validateSchema: false,
17
+ validateFormats: false,
18
+ schemas: references,
19
+ }), [references]);
20
+ return (_jsx(SchemaContext.Provider, { value: useMemo(() => ({ references, fieldInfoMap, ajv }), [fieldInfoMap, references, ajv]), children: children }));
21
+ }
22
+ /**
23
+ * A hook to store dynamic info of a field, such as selected schema of `oneOf`.
24
+ *
25
+ * @param fieldName - field name of form.
26
+ * @param schema - The JSON Schema to generate initial values.
27
+ * @param depth - The depth to avoid duplicated field name with same schema (e.g. nested `oneOf`).
28
+ */
29
+ export function useFieldInfo(fieldName, schema, depth) {
30
+ const { fieldInfoMap, ajv } = useContext(SchemaContext);
31
+ const [_, trigger] = useState(0);
32
+ const form = useFormContext();
33
+ const keyName = `${fieldName}:${depth}`;
34
+ const value = form.getValues(fieldName);
35
+ const info = fieldInfoMap.get(keyName) ?? {
36
+ oneOf: -1,
37
+ };
38
+ // update info if needed
39
+ if (!info.selectedType && Array.isArray(schema.type)) {
40
+ info.selectedType =
41
+ schema.type.find((type) => ajv.validate({
42
+ ...schema,
43
+ type,
44
+ }, value)) ?? schema.type[0];
45
+ }
46
+ if (info.oneOf === -1 && schema.oneOf) {
47
+ info.oneOf = schema.oneOf.findIndex((item) => {
48
+ return ajv.validate(item, value);
49
+ });
50
+ if (info.oneOf === -1)
51
+ info.oneOf = 0;
52
+ }
53
+ fieldInfoMap.set(keyName, info);
54
+ return {
55
+ info,
56
+ updateInfo: useEffectEvent((value) => {
57
+ const prev = fieldInfoMap.get(keyName);
58
+ if (!prev)
59
+ return;
60
+ const updated = {
61
+ ...prev,
62
+ ...value,
63
+ };
64
+ if (updated.oneOf === prev.oneOf &&
65
+ updated.selectedType === prev.selectedType)
66
+ return;
67
+ fieldInfoMap.set(keyName, updated);
68
+ form.setValue(fieldName, getDefaultValue(schema.oneOf && updated.oneOf !== -1
69
+ ? schema.oneOf[updated.oneOf]
70
+ : {
71
+ ...schema,
72
+ type: value.selectedType ?? schema.type,
73
+ }));
74
+ trigger((prev) => prev + 1);
75
+ }),
76
+ };
77
+ }
78
+ /**
79
+ * Resolve `$ref` in the schema, **not recursive**.
80
+ */
81
+ export function useResolvedSchema(schema) {
82
+ const { references } = useContext(SchemaContext);
83
+ return useMemo(() => {
84
+ if (typeof schema === 'boolean')
85
+ return anyFields;
86
+ if (schema.$ref)
87
+ return fallbackAny(references[schema.$ref]);
88
+ return schema;
89
+ }, [references, schema]);
90
+ }
91
+ export function fallbackAny(schema) {
92
+ return typeof schema === 'boolean' ? anyFields : schema;
93
+ }
@@ -1,5 +1,4 @@
1
1
  import type { MethodInformation, RenderContext } from '../../types.js';
2
- import type { NoReference } from '../../utils/schema.js';
3
2
  import type { RequestData } from '../../requests/_shared.js';
4
- export declare function getRequestData(path: string, method: NoReference<MethodInformation>, sampleKey: string | null, { schema: { document } }: RenderContext): RequestData;
3
+ export declare function getRequestData(path: string, method: MethodInformation, sampleKey: string | null, { schema: { document } }: RenderContext): RequestData;
5
4
  //# sourceMappingURL=get-request-data.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-request-data.d.ts","sourceRoot":"","sources":["../../../src/render/operation/get-request-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAKlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,CAAC,iBAAiB,CAAC,EACtC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,GACtC,WAAW,CAqEb"}
1
+ {"version":3,"file":"get-request-data.d.ts","sourceRoot":"","sources":["../../../src/render/operation/get-request-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAKhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,GACtC,WAAW,CAwEb"}
@@ -1,5 +1,5 @@
1
- import { sample } from 'openapi-sampler';
2
1
  import { getPreferredType } from '../../utils/schema.js';
2
+ import { sample } from 'openapi-sampler';
3
3
  import { getSecurities, getSecurityPrefix } from '../../utils/get-security.js';
4
4
  export function getRequestData(path, method, sampleKey, { schema: { document } }) {
5
5
  const result = {
@@ -58,7 +58,7 @@ export function getRequestData(path, method, sampleKey, { schema: { document } }
58
58
  result.body = bodyOfType.example;
59
59
  }
60
60
  else {
61
- result.body = generateBody(method.method, bodyOfType?.schema ?? {});
61
+ result.body = generateBody(method.method, (bodyOfType?.schema ?? {}));
62
62
  }
63
63
  }
64
64
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAEV,iBAAiB,EAEjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAejB,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,oBAAoB,CAAC;AAK3E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EACH,MAAM,GACN,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,MAAM,GAAG,SAAS,CAAC,GACxD,KAAK,CAAC;CACX;AASD,wBAAgB,SAAS,CAAC,EACxB,IAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,YAAgB,GACjB,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,YAAY,CAgLf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/operation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAEV,iBAAiB,EAEjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAmBjB,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,oBAAoB,CAAC;AAK3E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EACH,MAAM,GACN,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,MAAM,GAAG,SAAS,CAAC,GACxD,KAAK,CAAC;CACX;AASD,wBAAgB,SAAS,CAAC,EACxB,IAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,OAAO,EACP,YAAgB,GACjB,EAAE;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IAEnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,YAAY,CAoLf"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Fragment } from 'react';
3
- import { getPreferredType } from '../../utils/schema.js';
3
+ import { getPreferredType, } from '../../utils/schema.js';
4
4
  import { getSecurities, getSecurityPrefix } from '../../utils/get-security.js';
5
5
  import { idToTitle } from '../../utils/id-to-title.js';
6
6
  import { Markdown } from '../markdown.js';
@@ -12,8 +12,8 @@ import { APIExample, APIExampleProvider, getAPIExamples, } from '../../render/op
12
12
  import { MethodLabel } from '../../ui/components/method-label.js';
13
13
  import { supportedMediaTypes } from '../../requests/_shared.js';
14
14
  import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
15
- import { CodeBlock } from '../../render/codeblock.js';
16
15
  import { getTypescriptSchema } from '../../utils/get-typescript-schema.js';
16
+ import { CopyResponseTypeScript } from '../../ui/client.js';
17
17
  const ParamTypes = {
18
18
  path: 'Path Parameters',
19
19
  query: 'Query Parameters',
@@ -37,7 +37,7 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
37
37
  if (!type ||
38
38
  !supportedMediaTypes.includes(String(type)))
39
39
  throw new Error(`No supported media type for body content: ${path}, received: ${type}`);
40
- bodyNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Request Body', ctx), _jsxs("div", { className: "mb-8 flex flex-row items-center justify-between gap-2", children: [_jsx("code", { children: type }), _jsx("span", { children: body.required ? 'Required' : 'Optional' })] }), body.description ? _jsx(Markdown, { text: body.description }) : null, _jsx(Schema, { name: "body", schema: body.content[type].schema ?? {}, required: body.required, ctx: {
40
+ bodyNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Request Body', ctx), _jsxs("div", { className: "mb-4 p-3 bg-fd-card rounded-xl border flex flex-row items-center justify-between gap-2", children: [_jsx("code", { children: type }), _jsx("span", { className: "text-xs", children: body.required ? 'Required' : 'Optional' })] }), body.description ? _jsx(Markdown, { text: body.description }) : null, _jsx(Schema, { name: "body", schema: (body.content[type].schema ?? {}), required: body.required, ctx: {
41
41
  readOnly: method.method === 'GET',
42
42
  writeOnly: method.method !== 'GET',
43
43
  render: ctx,
@@ -92,11 +92,11 @@ async function ResponseTab({ status, operation, ctx, }) {
92
92
  else if (generateTypeScriptSchema === undefined && responseOfType?.schema) {
93
93
  ts = await getTypescriptSchema(responseOfType?.schema, schema.dereferenceMap);
94
94
  }
95
- return (_jsxs(Tab, { value: status, children: [_jsx(Markdown, { text: description }), responseOfType?.schema && (_jsx(Schema, { name: "response", schema: responseOfType.schema, required: true, ctx: {
95
+ return (_jsxs(Tab, { value: status, children: [_jsx(Markdown, { text: description }), ts && _jsx(CopyResponseTypeScript, { code: ts }), responseOfType?.schema && (_jsx(Schema, { name: "response", schema: responseOfType.schema, required: true, ctx: {
96
96
  render: ctx,
97
97
  writeOnly: false,
98
98
  readOnly: true,
99
- } })), ts && _jsx(CodeBlock, { lang: "ts", code: ts, ctx: ctx, className: "mt-4" })] }));
99
+ } }))] }));
100
100
  }
101
101
  function WebhookCallback({ callback, ctx, headingLevel, }) {
102
102
  return Object.entries(callback).map(([path, pathItem]) => {
@@ -1,16 +1,16 @@
1
1
  import { type ReactNode } from 'react';
2
- import { NoReference, type ParsedSchema } from '../utils/schema.js';
2
+ import type { ResolvedSchema } from '../utils/schema.js';
3
3
  import type { RenderContext } from '../types.js';
4
4
  interface Context {
5
5
  readOnly: boolean;
6
6
  writeOnly: boolean;
7
- stack?: ParsedSchema[];
7
+ stack?: ResolvedSchema[];
8
8
  render: RenderContext;
9
9
  }
10
10
  export declare function Schema({ name, schema, required, parseObject, ctx, }: {
11
11
  name: string;
12
12
  required?: boolean;
13
- schema: NoReference<ParsedSchema>;
13
+ schema: ResolvedSchema;
14
14
  /**
15
15
  * Render the full object
16
16
  *
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAc,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAgB7C,UAAU,OAAO;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IAEvB,MAAM,EAAE,aAAa,CAAC;CACvB;AAUD,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,WAAkB,EAClB,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IAElC;;;;SAIK;IACL,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,SAAS,CAmKZ"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAiB7C,UAAU,OAAO;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IAEzB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,WAAkB,EAClB,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IAEvB;;;;SAIK;IACL,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,SAAS,CA+MZ"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { isNullable } from '../utils/schema.js';
3
2
  import { combineSchema } from '../utils/combine-schema.js';
4
3
  import { Markdown } from './markdown.js';
4
+ import { schemaToString } from '../utils/schema-to-string.js';
5
5
  const keys = {
6
6
  default: 'Default',
7
7
  minimum: 'Minimum',
@@ -11,48 +11,55 @@ const keys = {
11
11
  pattern: 'Pattern',
12
12
  format: 'Format',
13
13
  };
14
- function isObject(schema) {
15
- return (schema.type === 'object' ||
16
- schema.properties !== undefined ||
17
- schema.additionalProperties !== undefined);
18
- }
19
14
  export function Schema({ name, schema, required = false, parseObject = true, ctx, }) {
15
+ const { render: { renderer }, stack = [], } = ctx;
16
+ if (schema === true) {
17
+ return _jsx(renderer.Property, { name: name, type: "any" });
18
+ }
19
+ else if (schema === false) {
20
+ return _jsx(renderer.Property, { name: name, type: "never" });
21
+ }
20
22
  if ((schema.readOnly === true && !ctx.readOnly) ||
21
23
  (schema.writeOnly === true && !ctx.writeOnly))
22
24
  return null;
23
- const { render: { renderer }, stack = [], } = ctx;
24
- // object type
25
- if (isObject(schema) &&
26
- parseObject &&
27
- (schema.additionalProperties || schema.properties)) {
28
- let body = null;
29
- let footer = null;
30
- const { additionalProperties, properties } = schema;
31
- if (additionalProperties === true) {
32
- footer = _jsx(renderer.Property, { name: "[key: string]", type: "any" });
33
- }
34
- else if (additionalProperties) {
35
- footer = (_jsx(Schema, { name: "[key: string]", schema: additionalProperties, parseObject: false, ctx: {
36
- ...ctx,
37
- stack: [schema, ...stack],
38
- } }));
39
- }
40
- if (properties) {
41
- body = Object.entries(properties).map(([key, value]) => {
42
- return (_jsx(Schema, { name: key, schema: value, parseObject: false, required: schema.required?.includes(key) ?? false, ctx: {
43
- ...ctx,
44
- stack: [schema, ...stack],
45
- } }, key));
46
- });
47
- }
48
- return (_jsxs("div", { className: "flex flex-col gap-4", children: [body, footer] }));
25
+ if (Array.isArray(schema.type) && schema.type.length === 1) {
26
+ return (_jsx(Schema, { name: name, required: required, parseObject: parseObject, schema: {
27
+ ...schema,
28
+ type: schema.type[0],
29
+ }, ctx: {
30
+ ...ctx,
31
+ stack: [schema, ...stack],
32
+ } }));
49
33
  }
50
- if (schema.allOf && parseObject) {
51
- return (_jsx(Schema, { name: name, schema: combineSchema(schema.allOf), ctx: {
34
+ if (schema.allOf || schema.anyOf) {
35
+ return (_jsx(Schema, { name: name, parseObject: parseObject, required: required, schema: combineSchema([
36
+ ...(schema.allOf ?? []),
37
+ ...(schema.anyOf ?? []),
38
+ ]), ctx: {
52
39
  ...ctx,
53
40
  stack: [schema, ...stack],
54
41
  } }));
55
42
  }
43
+ // object type
44
+ if (schema.type === 'object' && parseObject) {
45
+ const { additionalProperties, patternProperties, properties } = schema;
46
+ return (_jsxs("div", { className: "flex flex-col gap-4", children: [properties &&
47
+ Object.entries(properties).map(([key, value]) => {
48
+ return (_jsx(Schema, { name: key, schema: value, parseObject: false, required: schema.required?.includes(key) ?? false, ctx: {
49
+ ...ctx,
50
+ stack: [schema, ...stack],
51
+ } }, key));
52
+ }), patternProperties &&
53
+ Object.entries(patternProperties).map(([key, value]) => {
54
+ return (_jsx(Schema, { name: key, schema: value, parseObject: false, ctx: {
55
+ ...ctx,
56
+ stack: [schema, ...stack],
57
+ } }, key));
58
+ }), additionalProperties && (_jsx(Schema, { name: "[key: string]", schema: additionalProperties, parseObject: false, ctx: {
59
+ ...ctx,
60
+ stack: [schema, ...stack],
61
+ } }))] }));
62
+ }
56
63
  let footer;
57
64
  const fields = [];
58
65
  for (const [key, value] of Object.entries(keys)) {
@@ -69,84 +76,47 @@ export function Schema({ name, schema, required = false, parseObject = true, ctx
69
76
  value: schema.enum.map((value) => JSON.stringify(value)).join(' | '),
70
77
  });
71
78
  }
72
- if (isObject(schema) && !parseObject && !stack.includes(schema)) {
79
+ if (schema.type === 'object' && !parseObject && !stack.includes(schema)) {
73
80
  footer = (_jsx(renderer.ObjectCollapsible, { name: "Show Attributes", children: _jsx(Schema, { name: name, schema: schema, ctx: {
74
81
  ...ctx,
75
82
  stack: [schema, ...stack],
76
83
  } }) }));
77
84
  }
78
85
  else {
79
- const mentionedObjectTypes = [
80
- ...(schema.anyOf ?? schema.oneOf ?? []),
81
- ...(schema.not ? [schema.not] : []),
82
- ...(schema.type === 'array' && schema.items ? [schema.items] : []),
83
- ].filter((s) => isComplexType(s) && !stack.includes(s));
84
- footer = mentionedObjectTypes.map((s, idx) => {
85
- return (_jsx(renderer.ObjectCollapsible, { name: s.title ??
86
- (mentionedObjectTypes.length === 1
87
- ? 'Show Attributes'
88
- : `Object ${idx + 1}`), children: _jsx(Schema, { name: "element", schema: s, ctx: {
89
- ...ctx,
90
- stack: [schema, ...stack],
91
- } }) }, idx));
92
- });
86
+ let mentionedObjectTypes = [];
87
+ if (Array.isArray(schema.type)) {
88
+ mentionedObjectTypes.push(...schema.type.map((type) => ({
89
+ ...schema,
90
+ type,
91
+ })));
92
+ }
93
+ if (schema.oneOf)
94
+ mentionedObjectTypes.push(...schema.oneOf);
95
+ if (schema.not)
96
+ mentionedObjectTypes.push(schema.not);
97
+ if (schema.type === 'array' && schema.items)
98
+ mentionedObjectTypes.push(schema.items);
99
+ mentionedObjectTypes = mentionedObjectTypes.filter((s) => isComplexType(s) && !stack.includes(s));
100
+ footer = (_jsx("div", { className: "flex flex-col gap-2", children: mentionedObjectTypes.map((s, idx) => {
101
+ let title = typeof s === 'object' ? s.title : null;
102
+ title ?? (title = mentionedObjectTypes.length === 1
103
+ ? 'Show Attributes'
104
+ : `Object ${idx + 1}`);
105
+ return (_jsx(renderer.ObjectCollapsible, { name: title, children: _jsx(Schema, { name: "element", schema: s, ctx: {
106
+ ...ctx,
107
+ stack: [schema, ...stack],
108
+ } }) }, idx));
109
+ }) }));
93
110
  }
94
- return (_jsxs(renderer.Property, { name: name, type: getSchemaType(schema, ctx), required: required, deprecated: schema.deprecated, children: [schema.description ? _jsx(Markdown, { text: schema.description }) : null, fields.length > 0 ? (_jsx("div", { className: "flex flex-col gap-2", children: fields.map((field) => (_jsxs("span", { children: [field.key, ": ", _jsx("code", { children: field.value })] }, field.key))) })) : null, footer] }));
111
+ return (_jsxs(renderer.Property, { name: name, type: schemaToString(schema), required: required, deprecated: schema.deprecated, children: [schema.description ? _jsx(Markdown, { text: schema.description }) : null, fields.length > 0 ? (_jsx("div", { className: "flex flex-col gap-2", children: fields.map((field) => (_jsxs("span", { children: [field.key, ": ", _jsx("code", { children: field.value })] }, field.key))) })) : null, footer] }));
95
112
  }
96
113
  /**
97
114
  * Check if the schema needs another collapsible to explain
98
115
  */
99
116
  function isComplexType(schema) {
117
+ if (typeof schema === 'boolean')
118
+ return false;
100
119
  if (schema.anyOf ?? schema.oneOf ?? schema.allOf)
101
120
  return true;
102
- return isObject(schema) || schema.type === 'array';
103
- }
104
- function getSchemaType(schema, ctx, isRoot = true) {
105
- if (isNullable(schema) && isRoot) {
106
- const type = getSchemaType(schema, ctx, false);
107
- // null if schema only contains `nullable`
108
- return type === 'unknown' ? 'null' : `${type} | null`;
109
- }
110
- if (schema.title)
111
- return schema.title;
112
- if (schema.type === 'array')
113
- return `array<${schema.items ? getSchemaType(schema.items, ctx) : 'unknown'}>`;
114
- if (schema.oneOf)
115
- return schema.oneOf
116
- .map((one) => getSchemaType(one, ctx, false))
117
- .filter((v) => v !== 'unknown')
118
- .join(' | ');
119
- if (schema.allOf) {
120
- return schema.allOf
121
- .map((one) => getSchemaType(one, ctx, false))
122
- .filter((v) => v !== 'unknown')
123
- .join(' & ');
124
- }
125
- if (schema.not)
126
- return `not ${getSchemaType(schema.not, ctx, false)}`;
127
- if (schema.anyOf) {
128
- const properties = schema.anyOf
129
- .map((one) => getSchemaType(one, ctx, false))
130
- .filter((v) => v !== 'unknown');
131
- if (properties.length > 1) {
132
- return `Any properties in ${properties.join(',')}`;
133
- }
134
- else if (properties.length === 1) {
135
- return properties[0];
136
- }
137
- // otherwise unknown
138
- }
139
- if (schema.type === 'string' && schema.format === 'binary')
140
- return 'file';
141
- if (schema.type && Array.isArray(schema.type)) {
142
- const nonNullTypes = schema.type.filter((v) => v !== 'null');
143
- if (nonNullTypes.length > 0)
144
- return nonNullTypes.join(' | ');
145
- }
146
- else if (schema.type && schema.type !== 'null') {
147
- return schema.type;
148
- }
149
- if (isObject(schema))
150
- return 'object';
151
- return 'unknown';
121
+ return schema.type === 'object' || schema.type === 'array';
152
122
  }
@@ -1,2 +1,5 @@
1
1
  export { ClientLazy as APIPlayground } from '../playground/client.lazy.js';
2
+ export declare function CopyResponseTypeScript({ code }: {
3
+ code: string;
4
+ }): import("react/jsx-runtime").JSX.Element;
2
5
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ui/client.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ui/client.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,wBAAgB,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,2CAgChE"}
package/dist/ui/client.js CHANGED
@@ -1,2 +1,17 @@
1
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';
4
+ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
5
+ import { cn } from 'fumadocs-ui/utils/cn';
6
+ import { Check, Copy } from '../icons.js';
2
7
  export { ClientLazy as APIPlayground } from '../playground/client.lazy.js';
8
+ export function CopyResponseTypeScript({ code }) {
9
+ const [isChecked, onCopy] = useCopyButton(() => {
10
+ void navigator.clipboard.writeText(code);
11
+ });
12
+ return (_jsxs("div", { className: "flex items-start justify-between gap-2 bg-fd-card border rounded-xl p-3 not-prose mb-4 last:mb-0", children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium text-fd-foreground mb-2", children: "TypeScript Definitions" }), _jsx("p", { className: "text-xs", children: "Use the response body type in TypeScript." })] }), _jsxs("button", { onClick: onCopy, className: cn(buttonVariants({
13
+ color: 'secondary',
14
+ className: 'p-2 gap-2',
15
+ size: 'sm',
16
+ })), children: [isChecked ? (_jsx(Check, { className: "size-3.5" })) : (_jsx(Copy, { className: "size-3.5" })), "Copy"] })] }));
17
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/ui/components/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAI1D,QAAA,MAAM,MAAM,uCAAuB,CAAC;AAEpC,QAAA,MAAM,aAAa,8GAA0B,CAAC;AAE9C,QAAA,MAAM,YAAY,6CAAyB,CAAC;AAE5C,QAAA,MAAM,WAAW,4GAAwB,CAAC;AAE1C,QAAA,MAAM,aAAa,8JAYjB,CAAC;AAGH,QAAA,MAAM,aAAa,8JAqBjB,CAAC;AAGH,QAAA,MAAM,YAAY;8BAGf,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;;CAQtC,CAAC;AAGF,QAAA,MAAM,YAAY;8BAGf,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;;CAQtC,CAAC;AAGF,QAAA,MAAM,WAAW,oKAYf,CAAC;AAGH,QAAA,MAAM,iBAAiB,8KASrB,CAAC;AAGH,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,CAAC"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../src/ui/components/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAK1D,QAAA,MAAM,MAAM,uCAAuB,CAAC;AAEpC,QAAA,MAAM,aAAa,8GAA0B,CAAC;AAE9C,QAAA,MAAM,YAAY,6CAAyB,CAAC;AAE5C,QAAA,MAAM,WAAW,4GAAwB,CAAC;AAE1C,QAAA,MAAM,aAAa,8JAYjB,CAAC;AAGH,QAAA,MAAM,aAAa,8JA0BjB,CAAC;AAGH,QAAA,MAAM,YAAY;8BAGf,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;;CAKtC,CAAC;AAGF,QAAA,MAAM,YAAY;8BAGf,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;;CAQtC,CAAC;AAGF,QAAA,MAAM,WAAW,oKAYf,CAAC;AAGH,QAAA,MAAM,iBAAiB,8KASrB,CAAC;AAGH,OAAO,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,CAAC"}
@@ -4,15 +4,16 @@ import * as React from 'react';
4
4
  import * as DialogPrimitive from '@radix-ui/react-dialog';
5
5
  import { X } from '../../icons.js';
6
6
  import { cn } from 'fumadocs-ui/utils/cn';
7
+ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
7
8
  const Dialog = DialogPrimitive.Root;
8
9
  const DialogTrigger = DialogPrimitive.Trigger;
9
10
  const DialogPortal = DialogPrimitive.Portal;
10
11
  const DialogClose = DialogPrimitive.Close;
11
- const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn('fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out', className), ...props })));
12
+ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn('fixed inset-0 z-50 bg-black/30 backdrop-blur-sm data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out', className), ...props })));
12
13
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
13
- const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn('fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-fd-popover p-6 shadow-lg duration-200 data-[state=open]:animate-fd-dialog-in data-[state=closed]:animate-fd-dialog-out sm:rounded-lg', className), ...props, children: [children, _jsxs(DialogPrimitive.Close, { className: "absolute end-4 top-4 rounded-sm opacity-70 ring-offset-fd-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-fd-accent data-[state=open]:text-fd-muted-foreground", children: [_jsx(X, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "Close" })] })] })] })));
14
+ const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn('fixed left-1/2 top-1/2 z-50 flex flex-col gap-4 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 border bg-fd-popover p-4 shadow-lg rounded-xl duration-200 data-[state=open]:animate-fd-dialog-in data-[state=closed]:animate-fd-dialog-out focus-visible:outline-none', className), ...props, children: [children, _jsx(DialogPrimitive.Close, { "aria-label": "Close", className: cn(buttonVariants({ size: 'icon-sm', color: 'ghost' }), 'absolute end-2 top-2 text-fd-muted-foreground/70'), children: _jsx(X, {}) })] })] })));
14
15
  DialogContent.displayName = DialogPrimitive.Content.displayName;
15
- const DialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn('flex flex-col space-y-1.5 text-center sm:text-start', className), ...props }));
16
+ const DialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn('flex flex-col gap-1.5 text-center sm:text-start', className), ...props }));
16
17
  DialogHeader.displayName = 'DialogHeader';
17
18
  const DialogFooter = ({ className, ...props }) => (_jsx("div", { className: cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2', className), ...props }));
18
19
  DialogFooter.displayName = 'DialogFooter';
@@ -6,7 +6,7 @@ import { cn } from 'fumadocs-ui/utils/cn';
6
6
  const Select = SelectPrimitive.Root;
7
7
  const SelectGroup = SelectPrimitive.Group;
8
8
  const SelectValue = SelectPrimitive.Value;
9
- const SelectTrigger = forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn('flex min-h-10 items-center w-full rounded-md border px-3 py-2 text-start text-[13px] text-fd-secondary-foreground bg-fd-secondary hover:bg-fd-accent focus:outline-none focus:ring focus:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDown, { className: "ms-auto size-4 text-fd-muted-foreground" }) })] })));
9
+ const SelectTrigger = forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn('flex min-h-10 items-center w-full rounded-md border px-3 py-2 text-start text-[13px] text-fd-secondary-foreground bg-fd-secondary hover:bg-fd-accent focus:outline-none focus:ring focus:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDown, { className: "ms-auto size-3.5 text-fd-muted-foreground" }) })] })));
10
10
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
11
11
  const SelectScrollUpButton = forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollUpButton, { ref: ref, className: cn('flex items-center justify-center py-1', className), ...props, children: _jsx(ChevronUp, { className: "size-4" }) })));
12
12
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
package/dist/ui/index.js CHANGED
@@ -13,7 +13,7 @@ export function APIInfo({ className, ...props }) {
13
13
  }
14
14
  export function API({ children, ...props }) {
15
15
  return (_jsx("div", { ...props, className: cn('flex flex-col gap-x-6 gap-y-4 xl:flex-row xl:items-start', props.className), style: {
16
- '--fd-api-info-top': 'calc(var(--fd-nav-height) + var(--fd-banner-height) + var(--fd-tocnav-height, 0px))',
16
+ '--fd-api-info-top': 'calc(12px + var(--fd-nav-height) + var(--fd-banner-height) + var(--fd-tocnav-height, 0px))',
17
17
  ...props.style,
18
18
  }, children: children }));
19
19
  }
@@ -1,8 +1,3 @@
1
- import { type SelectedServer } from '../ui/contexts/api.js';
2
- import type { HTMLAttributes } from 'react';
3
- export default function ServerSelect({ server, onServerChanged, onVariablesChanged, ...props }: HTMLAttributes<HTMLDivElement> & {
4
- server: SelectedServer | null;
5
- onServerChanged: (value: string) => void;
6
- onVariablesChanged: (value: Record<string, string>) => void;
7
- }): import("react/jsx-runtime").JSX.Element | null;
1
+ import { type HTMLAttributes } from 'react';
2
+ export default function ServerSelect(props: HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element | undefined;
8
3
  //# sourceMappingURL=server-select.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-select.d.ts","sourceRoot":"","sources":["../../src/ui/server-select.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,mBAAmB,CAAC;AASvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,MAAM,EACN,eAAe,EACf,kBAAkB,EAClB,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;CAC7D,kDA4EA"}
1
+ {"version":3,"file":"server-select.d.ts","sourceRoot":"","sources":["../../src/ui/server-select.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,cAAc,EAAuB,MAAM,OAAO,CAAC;AAejE,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,uDAqDzE"}
@@ -1,26 +1,59 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useApiContext } from '../ui/contexts/api.js';
3
+ import { useApiContext, useServerSelectContext, } from '../ui/contexts/api.js';
4
4
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/components/select.js';
5
5
  import { Input, labelVariants } from '../ui/components/input.js';
6
+ import { useEffect, useState } from 'react';
6
7
  import { cn } from 'fumadocs-ui/utils/cn';
7
- export default function ServerSelect({ server, onServerChanged, onVariablesChanged, ...props }) {
8
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from '../ui/components/dialog.js';
9
+ import { getUrl } from '../utils/server-url.js';
10
+ import { FormProvider, useController, useForm } from 'react-hook-form';
11
+ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
12
+ export default function ServerSelect(props) {
8
13
  const { servers } = useApiContext();
9
- if (servers.length <= 1)
10
- return null;
11
- const schema = server
12
- ? servers.find((item) => item.url === server.url)
13
- : null;
14
- return (_jsxs("div", { ...props, className: cn('flex flex-col gap-4', props.className), children: [_jsxs(Select, { value: server?.url, onValueChange: onServerChanged, children: [_jsx(SelectTrigger, { className: "break-all", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: servers.map((item) => (_jsxs(SelectItem, { value: item.url, children: [item.url, _jsx("p", { className: "text-start text-fd-muted-foreground", children: item.description })] }, item.url))) })] }), Object.entries(schema?.variables ?? {}).map(([key, variable]) => {
15
- if (!server)
16
- return;
17
- const id = `fd_server_select_${key}`;
18
- return (_jsxs("fieldset", { className: "flex flex-col gap-1", children: [_jsx("label", { className: cn(labelVariants()), htmlFor: id, children: key }), _jsx("p", { className: "text-xs text-fd-muted-foreground empty:hidden", children: variable.description }), variable.enum ? (_jsxs(Select, { value: server.variables[key], onValueChange: (v) => onVariablesChanged({
19
- ...server?.variables,
20
- [key]: v,
21
- }), children: [_jsx(SelectTrigger, { id: id, children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: variable.enum.map((value) => (_jsx(SelectItem, { value: value, children: value }, value))) })] })) : (_jsx(Input, { id: id, value: server.variables[key], onChange: (e) => onVariablesChanged({
22
- ...server?.variables,
23
- [key]: e.target.value,
24
- }) }))] }, key));
25
- })] }));
14
+ const { server, setServer } = useServerSelectContext();
15
+ const [open, setOpen] = useState(false);
16
+ const [isMounted, setIsMounted] = useState(false);
17
+ useEffect(() => {
18
+ setIsMounted(true);
19
+ }, []);
20
+ if (servers.length <= 0)
21
+ return;
22
+ return (_jsxs(Dialog, { open: open, onOpenChange: setOpen, children: [_jsx(DialogTrigger, { className: "text-xs p-3 py-2 bg-fd-muted text-fd-muted-foreground transition-colors truncate hover:bg-fd-accent hover:text-fd-accent-foreground focus-visible:outline-none", children: isMounted
23
+ ? server
24
+ ? getUrl(server.url, server.variables)
25
+ : window.location.origin
26
+ : 'loading...' }), _jsxs(DialogContent, { ...props, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Server URL" }), _jsx(DialogDescription, { children: "The base URL of your API endpoint." })] }), _jsxs(Select, { value: server?.url, onValueChange: setServer, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: servers.map((item) => (_jsxs(SelectItem, { value: item.url, children: [item.url, _jsx("p", { className: "text-start text-fd-muted-foreground", children: item.description })] }, item.url))) })] }), server && (_jsx(ServerSelectContent, { server: server, onClose: () => setOpen(false) }, server.url))] })] }));
27
+ }
28
+ function ServerSelectContent({ server, onClose, }) {
29
+ const { servers } = useApiContext();
30
+ const { setServerVariables } = useServerSelectContext();
31
+ const schema = servers.find((item) => item.url === server.url);
32
+ const form = useForm({
33
+ defaultValues: server.variables,
34
+ });
35
+ const onSubmit = form.handleSubmit((data) => {
36
+ setServerVariables(data);
37
+ onClose();
38
+ });
39
+ if (!schema?.variables)
40
+ return;
41
+ return (_jsx(FormProvider, { ...form, children: _jsxs("form", { className: "flex flex-col gap-4", onSubmit: (e) => {
42
+ void onSubmit(e);
43
+ e.stopPropagation();
44
+ }, children: [Object.entries(schema.variables).map(([key, variable]) => {
45
+ return (_jsxs("fieldset", { className: "flex flex-col gap-1", children: [_jsx("label", { className: cn(labelVariants()), htmlFor: key, children: key }), _jsx("p", { className: "text-xs text-fd-muted-foreground empty:hidden", children: variable.description }), _jsx(Field, { fieldName: key, variable: variable })] }, key));
46
+ }), _jsx("button", { type: "submit", className: cn(buttonVariants({
47
+ color: 'primary',
48
+ className: 'mt-2',
49
+ })), children: "Save" })] }) }));
50
+ }
51
+ function Field({ fieldName, variable, }) {
52
+ const { field } = useController({
53
+ name: fieldName,
54
+ });
55
+ if (variable.enum) {
56
+ return (_jsxs(Select, { value: field.value, onValueChange: field.onChange, children: [_jsx(SelectTrigger, { id: fieldName, ref: field.ref, children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: variable.enum.map((value) => (_jsx(SelectItem, { value: value, children: value }, value))) })] }));
57
+ }
58
+ return _jsx(Input, { id: fieldName, ...field });
26
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"combine-schema.d.ts","sourceRoot":"","sources":["../../src/utils/combine-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAoDlE"}
1
+ {"version":3,"file":"combine-schema.d.ts","sourceRoot":"","sources":["../../src/utils/combine-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CA+DlE"}