fumadocs-openapi 9.0.4 → 9.0.5

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 (39) hide show
  1. package/dist/playground/auth/oauth-dialog.d.ts +4 -2
  2. package/dist/playground/auth/oauth-dialog.d.ts.map +1 -1
  3. package/dist/playground/auth/oauth-dialog.js +113 -26
  4. package/dist/playground/client.d.ts.map +1 -1
  5. package/dist/playground/client.js +101 -63
  6. package/dist/playground/index.js +26 -15
  7. package/dist/playground/inputs.d.ts +8 -2
  8. package/dist/playground/inputs.d.ts.map +1 -1
  9. package/dist/playground/inputs.js +32 -31
  10. package/dist/render/heading.d.ts +1 -1
  11. package/dist/render/heading.d.ts.map +1 -1
  12. package/dist/render/heading.js +3 -3
  13. package/dist/render/markdown.d.ts +2 -2
  14. package/dist/render/markdown.d.ts.map +1 -1
  15. package/dist/render/markdown.js +4 -2
  16. package/dist/render/operation/index.d.ts.map +1 -1
  17. package/dist/render/operation/index.js +68 -58
  18. package/dist/render/renderer.d.ts.map +1 -1
  19. package/dist/render/renderer.js +3 -3
  20. package/dist/render/schema.d.ts.map +1 -1
  21. package/dist/render/schema.js +7 -8
  22. package/dist/ui/components/accordion.d.ts +8 -0
  23. package/dist/ui/components/accordion.d.ts.map +1 -0
  24. package/dist/ui/components/accordion.js +20 -0
  25. package/dist/ui/components/input.js +1 -1
  26. package/dist/ui/components/select.js +1 -1
  27. package/dist/ui/index.d.ts.map +1 -1
  28. package/dist/ui/index.js +4 -2
  29. package/dist/ui/select-tabs.d.ts +13 -0
  30. package/dist/ui/select-tabs.d.ts.map +1 -0
  31. package/dist/ui/select-tabs.js +20 -0
  32. package/dist/ui/server-select.d.ts.map +1 -1
  33. package/dist/ui/server-select.js +22 -15
  34. package/dist/utils/schema-to-string.d.ts.map +1 -1
  35. package/dist/utils/schema-to-string.js +10 -1
  36. package/dist/utils/schema.d.ts +0 -1
  37. package/dist/utils/schema.d.ts.map +1 -1
  38. package/dist/utils/schema.js +0 -10
  39. package/package.json +10 -9
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useMemo, useState, } from 'react';
4
- import { Plus, Trash2 } from '../icons.js';
4
+ import { ChevronDown, Plus, Trash2 } from '../icons.js';
5
5
  import { Controller, useController, useFieldArray, useFormContext, } from 'react-hook-form';
6
6
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/components/select.js';
7
7
  import { Input, labelVariants } from '../ui/components/input.js';
@@ -11,10 +11,13 @@ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
11
11
  import { combineSchema } from '../utils/combine-schema.js';
12
12
  import { schemaToString } from '../utils/schema-to-string.js';
13
13
  import { anyFields, useFieldInfo, useResolvedSchema, } from '../playground/schema.js';
14
- function FieldHeader({ name, required = false, ...props }) {
15
- return (_jsxs("label", { ...props, className: cn('w-full inline-flex items-center gap-1', props.className), children: [_jsxs("span", { className: cn(labelVariants(), 'me-auto'), children: [name, required ? _jsx("span", { className: "text-red-400/80 mx-1", children: "*" }) : null] }), props.children] }));
14
+ function FieldLabel(props) {
15
+ return (_jsx("label", { ...props, className: cn('w-full inline-flex items-center gap-0.5', props.className), children: props.children }));
16
16
  }
17
- function FieldHeaderCode(props) {
17
+ function FieldLabelName({ required = false, ...props }) {
18
+ return (_jsxs("span", { ...props, className: cn(labelVariants(), 'font-mono me-auto', props.className), children: [props.children, required && _jsx("span", { className: "text-red-400/80 mx-1", children: "*" })] }));
19
+ }
20
+ function FieldLabelType(props) {
18
21
  return (_jsx("code", { ...props, className: cn('text-xs text-fd-muted-foreground', props.className), children: props.children }));
19
22
  }
20
23
  export function ObjectInput({ field: _field, fieldName, ...props }) {
@@ -22,7 +25,7 @@ export function ObjectInput({ field: _field, fieldName, ...props }) {
22
25
  const field = useMemo(() => combineSchema([resolved]), [resolved]);
23
26
  if (typeof field === 'boolean')
24
27
  return;
25
- return (_jsxs("div", { ...props, className: cn('flex flex-col gap-6', props.className), children: [Object.entries(field.properties ?? {}).map(([key, child]) => (_jsx(FieldSet, { name: key, field: child, fieldName: `${fieldName}.${key}`, isRequired: field.required?.includes(key) }, key))), (field.additionalProperties || field.patternProperties) && (_jsx(DynamicProperties, { fieldName: fieldName, filterKey: (v) => !field.properties || !Object.keys(field.properties).includes(v), getType: (key) => {
28
+ return (_jsxs("div", { ...props, className: cn('grid grid-cols-1 gap-4 @md:grid-cols-2', props.className), children: [Object.entries(field.properties ?? {}).map(([key, child]) => (_jsx(FieldSet, { name: key, field: child, fieldName: `${fieldName}.${key}`, isRequired: field.required?.includes(key) }, key))), (field.additionalProperties || field.patternProperties) && (_jsx(DynamicProperties, { fieldName: fieldName, filterKey: (v) => !field.properties || !Object.keys(field.properties).includes(v), getType: (key) => {
26
29
  for (const pattern in field.patternProperties) {
27
30
  if (key.match(RegExp(pattern))) {
28
31
  return field.patternProperties[pattern];
@@ -73,9 +76,8 @@ function DynamicProperties({ fieldName, filterKey = () => true, getType = () =>
73
76
  return (_jsxs(_Fragment, { children: [properties.map((item) => {
74
77
  const type = getType(item);
75
78
  return (_jsx(FieldSet, { name: item, field: type, fieldName: `${fieldName}.${item}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
76
- color: 'ghost',
77
- size: 'icon-sm',
78
- className: 'p-1',
79
+ color: 'outline',
80
+ size: 'icon-xs',
79
81
  })), onClick: () => {
80
82
  setProperties((p) => p.filter((prop) => prop !== item));
81
83
  control.unregister(`${fieldName}.${item}`);
@@ -87,14 +89,18 @@ function DynamicProperties({ fieldName, filterKey = () => true, getType = () =>
87
89
  }
88
90
  } }), _jsx("button", { type: "button", className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4'), onClick: onAppend, children: "New" })] })] }));
89
91
  }
90
- function FieldInput({ field, fieldName, isRequired, ...props }) {
92
+ export function FieldInput({ field, fieldName, isRequired, ...props }) {
91
93
  const { control, register } = useFormContext();
92
94
  if (field.type === 'string' && field.format === 'binary') {
93
- return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value: _, onChange, ...restField } }) => (_jsx("input", { id: fieldName, type: "file", multiple: false, onChange: (e) => {
94
- if (!e.target.files)
95
- return;
96
- onChange(e.target.files.item(0));
97
- }, ...props, className: cn('border rounded-lg bg-fd-background text-fd-muted-foreground p-2 font-medium text-sm', props.className), ...restField })) }));
95
+ return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value, onChange, ...restField } }) => (_jsxs("div", { ...props, children: [_jsx("label", { htmlFor: fieldName, className: cn(buttonVariants({
96
+ color: 'secondary',
97
+ size: 'sm',
98
+ className: 'w-full',
99
+ })), children: value ? value.name : 'Upload' }), _jsx("input", { id: fieldName, type: "file", multiple: false, onChange: (e) => {
100
+ if (!e.target.files)
101
+ return;
102
+ onChange(e.target.files.item(0));
103
+ }, hidden: true, ...restField })] })) }));
98
104
  }
99
105
  if (field.type === 'boolean') {
100
106
  return (_jsx(Controller, { control: control, name: fieldName, render: ({ field: { value, onChange, ...restField } }) => (_jsxs(Select, { value: String(value), onValueChange: (value) => onChange(value === 'null' ? null : value === 'true'), disabled: restField.disabled, children: [_jsx(SelectTrigger, { id: fieldName, className: props.className, ...restField, children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "true", children: "True" }), _jsx(SelectItem, { value: "false", children: "False" }), !isRequired && _jsx(SelectItem, { value: "null", children: "Null" })] })] })) }));
@@ -105,21 +111,12 @@ function FieldInput({ field, fieldName, isRequired, ...props }) {
105
111
  valueAsNumber: field.type === 'number' || field.type === 'integer',
106
112
  }), ...props }));
107
113
  }
108
- export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired, depth = 0, slotType, ...props }) {
114
+ export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired, depth = 0, slotType, collapsible = true, ...props }) {
109
115
  const field = useResolvedSchema(_field);
110
- const [show, setShow] = useState(false);
116
+ const [show, setShow] = useState(!collapsible);
111
117
  const { info, updateInfo } = useFieldInfo(fieldName, field, depth);
112
118
  if (_field === false)
113
119
  return null;
114
- const recursive = typeof _field !== 'boolean' &&
115
- _field.$ref &&
116
- (field.oneOf || field.type === 'object' || field.allOf || field.anyOf);
117
- if (recursive && !show) {
118
- return (_jsxs(FieldHeader, { ...props, name: name, required: isRequired, children: [slotType ?? _jsx(FieldHeaderCode, { children: schemaToString(field) }), toolbar, _jsx("button", { type: "button", className: cn(buttonVariants({
119
- size: 'sm',
120
- color: 'secondary',
121
- })), onClick: () => setShow(true), children: "Open" })] }));
122
- }
123
120
  if (field.oneOf) {
124
121
  const showSelect = field.oneOf.length > 1;
125
122
  return (_jsx(FieldSet, { ...props, name: name, fieldName: fieldName, isRequired: isRequired, field: field.oneOf[info.oneOf], depth: depth + 1, slotType: showSelect ? false : slotType, toolbar: _jsxs(_Fragment, { children: [showSelect && (_jsx("select", { className: "text-xs font-mono", value: info.oneOf, onChange: (e) => {
@@ -139,13 +136,18 @@ export function FieldSet({ field: _field, fieldName, toolbar, name, isRequired,
139
136
  });
140
137
  }, children: field.type.map((item) => (_jsx("option", { value: item, children: item }, item))) })), toolbar] }) }));
141
138
  }
139
+ const showBn = collapsible && (_jsx("button", { type: "button", onClick: () => setShow((prev) => !prev), className: cn(buttonVariants({
140
+ size: 'icon-xs',
141
+ color: 'ghost',
142
+ className: 'text-fd-muted-foreground -ms-1',
143
+ })), children: _jsx(ChevronDown, { className: cn(show && 'rotate-180') }) }));
142
144
  if (field.type === 'object' || field.anyOf || field.allOf) {
143
- return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, children: [slotType ?? (_jsx(FieldHeaderCode, { children: schemaToString(field) })), toolbar] }), _jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) })] }));
145
+ return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5 col-span-full @container', props.className), children: [_jsxs(FieldLabel, { htmlFor: fieldName, children: [showBn, _jsx(FieldLabelName, { required: isRequired, children: name }), slotType ?? _jsx(FieldLabelType, { children: schemaToString(field) }), toolbar] }), show && (_jsx(ObjectInput, { field: field, fieldName: fieldName, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm', props.className) }))] }));
144
146
  }
145
147
  if (field.type === 'array') {
146
- return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, children: [slotType ?? (_jsx(FieldHeaderCode, { children: schemaToString(field) })), toolbar] }), _jsx(ArrayInput, { fieldName: fieldName, items: field.items ?? anyFields, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-3 shadow-sm', props.className) })] }));
148
+ return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5 col-span-full', props.className), children: [_jsxs(FieldLabel, { htmlFor: fieldName, children: [showBn, _jsx(FieldLabelName, { required: isRequired, children: name }), slotType ?? _jsx(FieldLabelType, { children: schemaToString(field) }), toolbar] }), show && (_jsx(ArrayInput, { fieldName: fieldName, items: field.items ?? anyFields, ...props, className: cn('rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm', props.className) }))] }));
147
149
  }
148
- return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldHeader, { htmlFor: fieldName, name: name, required: isRequired, children: [slotType ?? _jsx(FieldHeaderCode, { children: schemaToString(field) }), toolbar] }), _jsx(FieldInput, { field: field, fieldName: fieldName, isRequired: isRequired })] }));
150
+ return (_jsxs("fieldset", { ...props, className: cn('flex flex-col gap-1.5', props.className), children: [_jsxs(FieldLabel, { htmlFor: fieldName, children: [_jsx(FieldLabelName, { required: isRequired, children: name }), slotType ?? _jsx(FieldLabelType, { children: schemaToString(field) }), toolbar] }), _jsx(FieldInput, { field: field, fieldName: fieldName, isRequired: isRequired })] }));
149
151
  }
150
152
  function ArrayInput({ fieldName, items, ...props }) {
151
153
  const name = fieldName.split('.').at(-1) ?? '';
@@ -153,9 +155,8 @@ function ArrayInput({ fieldName, items, ...props }) {
153
155
  name: fieldName,
154
156
  });
155
157
  return (_jsxs("div", { ...props, className: cn('flex flex-col gap-2', props.className), children: [fields.map((item, index) => (_jsx(FieldSet, { name: _jsxs("span", { className: "text-fd-muted-foreground", children: [name, "[", index, "]"] }), field: items, fieldName: `${fieldName}.${index}`, toolbar: _jsx("button", { type: "button", "aria-label": "Remove Item", className: cn(buttonVariants({
156
- color: 'ghost',
157
- size: 'icon-sm',
158
- className: 'p-1',
158
+ color: 'outline',
159
+ size: 'icon-xs',
159
160
  })), onClick: () => remove(index), children: _jsx(Trash2, {}) }) }, item.id))), _jsxs("button", { type: "button", className: cn(buttonVariants({
160
161
  color: 'secondary',
161
162
  className: 'gap-1.5 py-2',
@@ -1,4 +1,4 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { RenderContext } from '../types.js';
3
- export declare function heading(depth: number, child: string, ctx: RenderContext): ReactNode;
3
+ export declare function heading(depth: number, text: string, ctx: RenderContext, children?: ReactNode): ReactNode;
4
4
  //# sourceMappingURL=heading.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../src/render/heading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,aAAa,GACjB,SAAS,CAQX"}
1
+ {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../src/render/heading.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,aAAa,EAClB,QAAQ,GAAE,SAAgB,GACzB,SAAS,CAQX"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Heading } from 'fumadocs-ui/components/heading';
3
- export function heading(depth, child, ctx) {
4
- const id = ctx.slugger.slug(child);
5
- return (_jsx(Heading, { id: id, as: `h${depth.toString()}`, children: child.trim() }, id));
3
+ export function heading(depth, text, ctx, children = text) {
4
+ const id = ctx.slugger.slug(text);
5
+ return (_jsx(Heading, { id: id, as: `h${depth.toString()}`, children: children }, id));
6
6
  }
@@ -1,5 +1,5 @@
1
1
  import { type ReactElement } from 'react';
2
- export declare function Markdown({ text, }: {
2
+ export declare function Markdown({ text }: {
3
3
  text: string;
4
- }): Promise<ReactElement>;
4
+ }): Promise<ReactElement<unknown, string | import("react").JSXElementConstructor<any>>>;
5
5
  //# sourceMappingURL=markdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/render/markdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAkC1C,wBAAsB,QAAQ,CAAC,EAC7B,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,YAAY,CAAC,CAIxB"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/render/markdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAkC1C,wBAAsB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,uFAMxD"}
@@ -23,7 +23,9 @@ function rehypeReact() {
23
23
  });
24
24
  };
25
25
  }
26
- export async function Markdown({ text, }) {
27
- const out = await processor.process(text);
26
+ export async function Markdown({ text }) {
27
+ const out = await processor.process({
28
+ value: text,
29
+ });
28
30
  return out.result;
29
31
  }
@@ -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;AAkBjB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAW1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK,CAAC;CAC3C;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,CA6Kf"}
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,EACjB,aAAa,EAEd,MAAM,SAAS,CAAC;AAcjB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAY1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK,CAAC;CAC3C;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,CAgNf"}
@@ -1,6 +1,5 @@
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';
4
3
  import { idToTitle } from '../../utils/id-to-title.js';
5
4
  import { Markdown } from '../markdown.js';
6
5
  import { heading } from '../heading.js';
@@ -8,10 +7,11 @@ import { Schema } from '../schema.js';
8
7
  import { createMethod } from '../../server/create-method.js';
9
8
  import { methodKeys } from '../../build-routes.js';
10
9
  import { APIExample, APIExampleProvider, getAPIExamples, } from '../../render/operation/api-example.js';
11
- import { Badge, MethodLabel } from '../../ui/components/method-label.js';
12
- import { Tab, Tabs, TabsContent, TabsList, TabsTrigger, } from 'fumadocs-ui/components/tabs';
10
+ import { MethodLabel } from '../../ui/components/method-label.js';
13
11
  import { getTypescriptSchema } from '../../utils/get-typescript-schema.js';
14
12
  import { CopyResponseTypeScript } from '../../ui/client.js';
13
+ import { SelectTab, SelectTabs, SelectTabTrigger } from '../../ui/select-tabs.js';
14
+ import { AccordionContent, AccordionHeader, AccordionItem, Accordions, AccordionTrigger, } from '../../ui/components/accordion.js';
15
15
  const ParamTypes = {
16
16
  path: 'Path Parameters',
17
17
  query: 'Query Parameters',
@@ -22,6 +22,7 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
22
22
  const body = method.requestBody;
23
23
  let headNode = null;
24
24
  let bodyNode = null;
25
+ let authNode = null;
25
26
  let responseNode = null;
26
27
  let callbacksNode = null;
27
28
  if (hasHead) {
@@ -30,34 +31,48 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
30
31
  headNode = (_jsxs(_Fragment, { children: [heading(headingLevel, title, ctx), method.description ? _jsx(Markdown, { text: method.description }) : null] }));
31
32
  headingLevel++;
32
33
  }
33
- if (body) {
34
- const type = getPreferredType(body.content);
35
- if (!type || !(type in ctx.mediaAdapters))
36
- throw new Error(`No supported media type for body content: ${path}, received: ${type}`);
37
- bodyNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Request Body', ctx), _jsxs("div", { className: "flex justify-between items-center gap-2 mb-4", children: [_jsx("code", { children: type }), body.required ? (_jsx(Badge, { color: "red", className: "text-xs", children: "Required" })) : (_jsx(Badge, { color: "yellow", className: "text-xs", children: "Optional" }))] }), body.description ? _jsx(Markdown, { text: body.description }) : null, _jsx(Schema, { name: "body", as: "body", schema: (body.content[type].schema ?? {}), required: body.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx })] }));
34
+ const contentTypes = body ? Object.entries(body.content) : null;
35
+ if (body && contentTypes && contentTypes.length > 0) {
36
+ bodyNode = (_jsxs(SelectTabs, { defaultValue: contentTypes[0][0], children: [_jsxs("div", { className: "flex gap-2 items-end justify-between", children: [heading(headingLevel, 'Request Body', ctx), _jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]), className: "mb-4" })] }), body.description && _jsx(Markdown, { text: body.description }), contentTypes.map(([type, content]) => {
37
+ if (!(type in ctx.mediaAdapters)) {
38
+ throw new Error(`Media type ${type} is not supported (in ${path})`);
39
+ }
40
+ return (_jsx(SelectTab, { value: type, children: _jsx(Schema, { name: "body", as: "body", schema: (content.schema ?? {}), required: body.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }) }, type));
41
+ })] }));
38
42
  }
39
43
  if (method.responses && ctx.showResponseSchema !== false) {
40
44
  const statuses = Object.keys(method.responses);
41
- responseNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Response Body', ctx), _jsx(Tabs, { items: statuses, groupId: "fumadocs_openapi_responses", children: statuses.map((status) => (_jsx(ResponseTab, { status: status, operation: method, ctx: ctx }, status))) })] }));
45
+ responseNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Response Body', ctx), _jsx(Accordions, { type: "multiple", children: statuses.map((status) => (_jsx(AccordionItem, { value: status, children: _jsx(ResponseAccordion, { status: status, operation: method, ctx: ctx }) }, status))) })] }));
42
46
  }
43
47
  const parameterNode = Object.entries(ParamTypes).map(([type, title]) => {
44
48
  const params = method.parameters?.filter((param) => param.in === type);
45
49
  if (!params || params.length === 0)
46
50
  return;
47
- return (_jsxs(Fragment, { children: [heading(headingLevel, title, ctx), _jsx("div", { className: "flex flex-col gap-4", children: params.map((param) => (_jsx(Schema, { name: param.name, schema: {
51
+ return (_jsxs(Fragment, { children: [heading(headingLevel, title, ctx), _jsx("div", { className: "flex flex-col", children: params.map((param) => (_jsx(Schema, { name: param.name, schema: {
48
52
  ...param.schema,
49
53
  description: param.description ?? param.schema?.description,
50
54
  deprecated: (param.deprecated ?? false) ||
51
55
  (param.schema?.deprecated ?? false),
52
56
  }, required: param.required, readOnly: method.method === 'GET', writeOnly: method.method !== 'GET', ctx: ctx }, param.name))) })] }, type));
53
57
  });
54
- if (method.callbacks) {
55
- callbacksNode = (_jsxs(_Fragment, { children: [heading(headingLevel, 'Webhooks', ctx), Object.entries(method.callbacks).map(([name, callback]) => (_jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }, name)))] }));
56
- }
57
- const security = (method.security ??
58
+ const securities = (method.security ??
58
59
  ctx.schema.document.security ??
59
60
  []).filter((v) => Object.keys(v).length > 0);
60
- const info = (_jsxs(ctx.renderer.APIInfo, { head: headNode, method: method.method, route: path, children: [type === 'operation' ? (ctx.disablePlayground ? (_jsxs("div", { className: "flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose", children: [_jsx(MethodLabel, { className: "text-xs", children: method.method }), _jsx("code", { className: "flex-1 overflow-auto text-nowrap text-[13px] text-fd-muted-foreground", children: path })] })) : (_jsx(ctx.renderer.APIPlayground, { path: path, method: method, ctx: ctx }))) : null, security.length > 0 ? (_jsxs(_Fragment, { children: [heading(headingLevel, 'Authorization', ctx), _jsx(AuthSection, { requirements: security, ctx: ctx })] })) : null, bodyNode, parameterNode, responseNode, callbacksNode] }));
61
+ if (type === 'operation' && securities.length > 0) {
62
+ const securitySchemes = ctx.schema.document.components?.securitySchemes;
63
+ const names = securities.map((security) => Object.keys(security).join(' & '));
64
+ authNode = (_jsxs(SelectTabs, { defaultValue: names[0], children: [_jsxs("div", { className: "flex items-end justify-between gap-2", children: [heading(headingLevel, 'Authorization', ctx), _jsx(SelectTabTrigger, { items: names, className: "mb-4" })] }), securities.map((security, i) => (_jsx(SelectTab, { value: names[i], children: Object.entries(security).map(([key, scopes]) => {
65
+ const scheme = securitySchemes?.[key];
66
+ if (!scheme)
67
+ return;
68
+ return (_jsx(AuthScheme, { scheme: scheme, scopes: scopes, ctx: ctx }, key));
69
+ }) }, i)))] }));
70
+ }
71
+ if (method.callbacks) {
72
+ const callbacks = Object.entries(method.callbacks);
73
+ callbacksNode = (_jsxs(SelectTabs, { defaultValue: callbacks[0][0], children: [_jsxs("div", { className: "flex justify-between gap-2 items-end", children: [heading(headingLevel, 'Callbacks', ctx), _jsx(SelectTabTrigger, { items: callbacks.map((v) => v[0]), className: "mb-4" })] }), callbacks.map(([name, callback]) => (_jsx(SelectTab, { value: name, children: _jsx(WebhookCallback, { callback: callback, ctx: ctx, headingLevel: headingLevel }) }, name)))] }));
74
+ }
75
+ const info = (_jsxs(ctx.renderer.APIInfo, { head: headNode, method: method.method, route: path, children: [type === 'operation' ? (ctx.disablePlayground ? (_jsxs("div", { className: "flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose", children: [_jsx(MethodLabel, { className: "text-xs", children: method.method }), _jsx("code", { className: "flex-1 overflow-auto text-nowrap text-[13px] text-fd-muted-foreground", children: path })] })) : (_jsx(ctx.renderer.APIPlayground, { path: path, method: method, ctx: ctx }))) : null, authNode, parameterNode, bodyNode, responseNode, callbacksNode] }));
61
76
  if (type === 'operation') {
62
77
  const examples = getAPIExamples(path, method, ctx);
63
78
  return (_jsx(ctx.renderer.API, { children: _jsxs(APIExampleProvider, { route: path, examples: examples, method: method, children: [info, _jsx(APIExample, { examples: examples, method: method, ctx: ctx })] }) }));
@@ -66,52 +81,47 @@ export function Operation({ type = 'operation', path, method, ctx, hasHead, head
66
81
  return info;
67
82
  }
68
83
  }
69
- async function ResponseTab({ status, operation, ctx, }) {
84
+ async function ResponseAccordion({ status, operation, ctx, }) {
70
85
  const response = operation.responses[status];
71
- const { generateTypeScriptSchema, schema } = ctx;
72
- const mediaType = response.content
73
- ? getPreferredType(response.content)
86
+ const { generateTypeScriptSchema, schema: { dereferenceMap }, } = ctx;
87
+ const contentTypes = response.content
88
+ ? Object.entries(response.content)
74
89
  : null;
75
- const responseOfType = mediaType ? response.content?.[mediaType] : null;
76
- const description = responseOfType?.schema?.description ?? response.description ?? '';
77
- let ts;
78
- if (generateTypeScriptSchema) {
79
- ts = await generateTypeScriptSchema(operation, status);
80
- }
81
- else if (generateTypeScriptSchema === undefined && responseOfType?.schema) {
82
- ts = await getTypescriptSchema(responseOfType?.schema, schema.dereferenceMap);
83
- }
84
- return (_jsxs(Tab, { value: status, children: [_jsx(Markdown, { text: description }), ts && _jsx(CopyResponseTypeScript, { code: ts }), responseOfType?.schema && (_jsx(Schema, { name: "response", schema: responseOfType.schema, as: "body", readOnly: true, ctx: ctx }))] }));
90
+ return (_jsxs(SelectTabs, { defaultValue: contentTypes?.[0][0], children: [_jsxs(AccordionHeader, { children: [_jsx(AccordionTrigger, { className: "font-mono", children: status }), contentTypes && (_jsx(SelectTabTrigger, { items: contentTypes.map((v) => v[0]) }))] }), _jsxs(AccordionContent, { children: [response.description && (_jsx("div", { className: "prose-no-margin", children: _jsx(Markdown, { text: response.description }) })), contentTypes?.map(async ([type, resType]) => {
91
+ const schema = resType.schema;
92
+ let ts;
93
+ if (generateTypeScriptSchema) {
94
+ ts = await generateTypeScriptSchema(operation, status);
95
+ }
96
+ else if (generateTypeScriptSchema === undefined && schema) {
97
+ ts = await getTypescriptSchema(schema, dereferenceMap);
98
+ }
99
+ return (_jsxs(SelectTab, { value: type, className: "mt-2", children: [ts && _jsx(CopyResponseTypeScript, { code: ts }), schema && (_jsx("div", { className: "border px-3 rounded-lg my-2 overflow-auto max-h-[400px]", children: _jsx(Schema, { name: "response", schema: schema, as: "body", readOnly: true, ctx: ctx }) }))] }, type));
100
+ })] })] }));
85
101
  }
86
102
  function WebhookCallback({ callback, ctx, headingLevel, }) {
87
- return Object.entries(callback).map(([path, pathItem]) => {
88
- const pathNodes = methodKeys.map((method) => {
89
- const operation = pathItem[method];
90
- if (!operation)
91
- return null;
92
- return (_jsx(Operation, { type: "webhook", hasHead: true, path: path, headingLevel: headingLevel + 1, method: createMethod(method, pathItem, operation), ctx: ctx }, method));
93
- });
94
- return _jsx(Fragment, { children: pathNodes }, path);
95
- });
103
+ const pathItems = Object.entries(callback);
104
+ return (_jsx(Accordions, { type: "single", collapsible: true, children: pathItems.map(([path, pathItem]) => {
105
+ const pathNodes = methodKeys.map((method) => {
106
+ const operation = pathItem[method];
107
+ if (!operation)
108
+ return null;
109
+ return (_jsx("div", { className: "border p-3 my-2 prose-no-margin rounded-lg", children: _jsx(Operation, { type: "webhook", path: path, headingLevel: headingLevel + 1, method: createMethod(method, pathItem, operation), ctx: ctx }) }, method));
110
+ });
111
+ return (_jsxs(AccordionItem, { value: path, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { className: "font-mono", children: path }) }), _jsx(AccordionContent, { children: pathNodes })] }, path));
112
+ }) }));
96
113
  }
97
- function AuthSection({ ctx: { schema: { document }, renderer, }, requirements, }) {
98
- return (_jsxs(Tabs, { defaultValue: "0", children: [_jsx(TabsList, { children: requirements.map((securities, i) => (_jsx(TabsTrigger, { value: i.toString(), children: Object.keys(securities).join(' & ') }, i))) }), requirements.map((securities, i) => {
99
- return (_jsx(TabsContent, { value: i.toString(), className: "flex flex-col gap-4", children: Object.entries(securities).map(([key, scopes]) => {
100
- const schema = document.components?.securitySchemes?.[key];
101
- if (!schema)
102
- return;
103
- const scopeElement = scopes.length > 0 ? (_jsxs("p", { children: ["Scope: ", _jsx("code", { children: scopes.join(', ') })] })) : null;
104
- if (schema.type === 'http' || schema.type === 'oauth2') {
105
- return (_jsxs(renderer.Property, { name: "Authorization", type: schema.type === 'http' && schema.scheme === 'basic'
106
- ? `Basic <token>`
107
- : 'Bearer <token>', required: true, children: [schema.description && (_jsx(Markdown, { text: schema.description })), _jsxs("p", { children: ["In: ", _jsx("code", { children: "header" })] }), scopeElement] }, key));
108
- }
109
- if (schema.type === 'apiKey') {
110
- return (_jsxs(renderer.Property, { name: schema.name, type: "<token>", children: [schema.description && (_jsx(Markdown, { text: schema.description })), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in }), scopeElement] })] }, key));
111
- }
112
- if (schema.type === 'openIdConnect') {
113
- return (_jsxs(renderer.Property, { name: "OpenID Connect", type: "<token>", required: true, children: [schema.description && (_jsx(Markdown, { text: schema.description })), scopeElement] }, key));
114
- }
115
- }) }, i));
116
- })] }));
114
+ function AuthScheme({ scheme: schema, scopes, ctx: { renderer }, }) {
115
+ const scopeElement = scopes.length > 0 ? (_jsxs("p", { children: ["Scope: ", _jsx("code", { children: scopes.join(', ') })] })) : null;
116
+ if (schema.type === 'http' || schema.type === 'oauth2') {
117
+ return (_jsxs(renderer.Property, { name: "Authorization", type: schema.type === 'http' && schema.scheme === 'basic'
118
+ ? `Basic <token>`
119
+ : 'Bearer <token>', required: true, children: [schema.description && _jsx(Markdown, { text: schema.description }), _jsxs("p", { children: ["In: ", _jsx("code", { children: "header" })] }), scopeElement] }));
120
+ }
121
+ if (schema.type === 'apiKey') {
122
+ return (_jsxs(renderer.Property, { name: schema.name, type: "<token>", children: [schema.description && _jsx(Markdown, { text: schema.description }), _jsxs("p", { children: ["In: ", _jsx("code", { children: schema.in }), scopeElement] })] }));
123
+ }
124
+ if (schema.type === 'openIdConnect') {
125
+ return (_jsxs(renderer.Property, { name: "OpenID Connect", type: "<token>", required: true, children: [schema.description && _jsx(Markdown, { text: schema.description }), scopeElement] }));
126
+ }
117
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAWtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGtE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,SAAS,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,GAAG,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAEnD,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACzC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,mBAAmB,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD,QAAQ,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC7E,YAAY,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAE/C;;OAEG;IACH,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IACzD,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,IAAI,QAAQ,CAqCxC"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAiBtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGtE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,SAAS,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/B,GAAG,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAEnD,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACzC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,mBAAmB,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjD,QAAQ,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC7E,YAAY,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAE/C;;OAEG;IACH,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IACzD,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,aAAa,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,IAAI,QAAQ,CA4CxC"}
@@ -1,6 +1,6 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
3
- import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
3
+ import { AccordionContent, AccordionHeader, AccordionItem, Accordions, AccordionTrigger, } from '../ui/components/accordion.js';
4
4
  import { API, APIExample, APIInfo, ObjectCollapsible, Property, Root, } from '../ui/index.js';
5
5
  import { APIPlayground } from '../playground/index.js';
6
6
  import { CodeExampleSelector } from '../ui/lazy.js';
@@ -12,8 +12,8 @@ export function createRenders() {
12
12
  APIExample,
13
13
  Responses: (props) => (_jsx(Tabs, { ...props, groupId: "fumadocs_openapi_responses" })),
14
14
  Response: Tab,
15
- ResponseTypes: (props) => (_jsx(Accordions, { type: "single", className: "!-m-4 border-none pt-2", defaultValue: props.defaultValue, children: props.children })),
16
- ResponseType: (props) => (_jsx(Accordion, { title: props.label, children: props.children })),
15
+ ResponseTypes: (props) => (_jsx(Accordions, { type: "single", className: "pt-2", defaultValue: props.defaultValue, children: props.children })),
16
+ ResponseType: (props) => (_jsxs(AccordionItem, { value: props.label, children: [_jsx(AccordionHeader, { children: _jsx(AccordionTrigger, { children: props.label }) }), _jsx(AccordionContent, { className: "prose-no-margin", children: props.children })] })),
17
17
  Property,
18
18
  ObjectCollapsible,
19
19
  Requests: (props) => (_jsx(Tabs, { groupId: "fumadocs_openapi_requests", ...props })),
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAwB7C,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,QAAgB,EAChB,SAAiB,EACjB,EAAe,EACf,GAAG,EAAE,EAAE,QAAQ,EAAE,GAClB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,aAAa,CAAC;CACpB,GAAG,SAAS,CAoSZ"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/render/schema.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAwB7C,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,QAAgB,EAChB,SAAiB,EACjB,EAAe,EACf,GAAG,EAAE,EAAE,QAAQ,EAAE,GAClB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,EAAE,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAEzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,aAAa,CAAC;CACpB,GAAG,SAAS,CAiSZ"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Fragment } from 'react';
3
3
  import { combineSchema } from '../utils/combine-schema.js';
4
4
  import { Markdown } from './markdown.js';
@@ -85,7 +85,7 @@ export function Schema({ name, schema, required = false, readOnly = false, write
85
85
  }
86
86
  if (fields.length === 0)
87
87
  return;
88
- return (_jsx("div", { className: "flex flex-col border divide-y divide-fd-border bg-fd-muted rounded-lg not-prose", children: fields.map((field) => (_jsxs("div", { className: "flex items-center text-[13px] px-3 py-2.5 justify-between gap-2", children: [_jsx("span", { className: "font-medium", children: field.key }), _jsx("code", { className: "texxt-xs text-fd-muted-foreground", children: field.value })] }, field.key))) }));
88
+ return (_jsx("div", { className: "flex flex-wrap gap-2 not-prose", children: fields.map((field) => (_jsxs("div", { className: "bg-fd-secondary text-fd-secondary-foreground border rounded-lg text-xs p-1.5 shadow-md", children: [_jsx("span", { className: "font-medium me-2", children: field.key }), _jsx("code", { className: "text-fd-muted-foreground", children: field.value })] }, field.key))) }));
89
89
  }
90
90
  function primitiveBody(schema, ctx, collapsible, nested) {
91
91
  if (schema.type === 'object') {
@@ -99,7 +99,7 @@ export function Schema({ name, schema, required = false, readOnly = false, write
99
99
  };
100
100
  if (props.length === 0 && patternProps.length === 0)
101
101
  return _jsx("p", { children: "Empty Object" });
102
- const children = (_jsxs("div", { className: "flex flex-col gap-4", children: [props.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, {
102
+ const children = (_jsxs(_Fragment, { children: [props.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, {
103
103
  required: schema.required?.includes(key) ?? false,
104
104
  nested,
105
105
  }) }, key))), patternProps.map(([key, value]) => (_jsx(Fragment, { children: property(key, value, next, { nested }) }, key))), schema.additionalProperties &&
@@ -114,11 +114,10 @@ export function Schema({ name, schema, required = false, readOnly = false, write
114
114
  const items = schema.items;
115
115
  if (!items || !isComplexType(items) || ctx.stack.has(items))
116
116
  return;
117
- const children = (_jsxs("div", { className: "flex flex-col gap-4", children: [items.description && _jsx(Markdown, { text: items.description }), propertyBody(items, (child, ctx) => primitiveBody(child, ctx, false, true), {
118
- ...ctx,
119
- stack: ctx.stack.next(schema),
120
- })] }));
121
- return (_jsx(renderer.ObjectCollapsible, { name: "Array Item", children: children }));
117
+ return (_jsxs(_Fragment, { children: [items.description && (_jsx(Markdown, { text: 'Item: ' + items.description })), _jsx(renderer.ObjectCollapsible, { name: "Array Item", children: propertyBody(items, (child, ctx) => primitiveBody(child, ctx, false, true), {
118
+ ...ctx,
119
+ stack: ctx.stack.next(schema),
120
+ }) })] }));
122
121
  }
123
122
  }
124
123
  function property(key, schema, ctx, props) {
@@ -0,0 +1,8 @@
1
+ import * as Primitive from '@radix-ui/react-accordion';
2
+ import type { ComponentProps } from 'react';
3
+ export declare function Accordions(props: ComponentProps<typeof Primitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ export declare function AccordionItem(props: ComponentProps<typeof Primitive.Item>): import("react/jsx-runtime").JSX.Element;
5
+ export declare function AccordionContent(props: ComponentProps<typeof Primitive.Content>): import("react/jsx-runtime").JSX.Element;
6
+ export declare function AccordionHeader(props: ComponentProps<typeof Primitive.Header>): import("react/jsx-runtime").JSX.Element;
7
+ export declare function AccordionTrigger(props: ComponentProps<typeof Primitive.Trigger>): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../src/ui/components/accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,2BAA2B,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,2CAUtE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC,2CAMzE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,OAAO,CAAC,2CAahD;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,2CAa/C;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,OAAO,CAAC,2CAchD"}
@@ -0,0 +1,20 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as Primitive from '@radix-ui/react-accordion';
4
+ import { ChevronRight } from '../../icons.js';
5
+ import { cn } from 'fumadocs-ui/utils/cn';
6
+ export function Accordions(props) {
7
+ return (_jsx(Primitive.Root, { ...props, className: cn('divide-y divide-fd-border overflow-hidden', props.className) }));
8
+ }
9
+ export function AccordionItem(props) {
10
+ return (_jsx(Primitive.Item, { ...props, className: cn('scroll-m-20', props.className), children: props.children }));
11
+ }
12
+ export function AccordionContent(props) {
13
+ return (_jsx(Primitive.Content, { ...props, className: cn('overflow-hidden px-1 data-[state=closed]:animate-fd-accordion-up data-[state=open]:animate-fd-accordion-down', props.className), children: props.children }));
14
+ }
15
+ export function AccordionHeader(props) {
16
+ return (_jsx(Primitive.Header, { ...props, className: cn('not-prose flex py-2 text-fd-foreground font-medium', props.className), children: props.children }));
17
+ }
18
+ export function AccordionTrigger(props) {
19
+ return (_jsxs(Primitive.Trigger, { ...props, className: cn('flex flex-1 items-center gap-1 text-start group/accordion focus-visible:outline-none', props.className), children: [_jsx(ChevronRight, { className: "size-3.5 text-fd-muted-foreground shrink-0 transition-transform group-data-[state=open]/accordion:rotate-90" }), props.children] }));
20
+ }
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import * as React from 'react';
3
3
  import { cn } from 'fumadocs-ui/utils/cn';
4
4
  import { cva } from 'class-variance-authority';
5
- export const labelVariants = cva('text-xs font-medium text-fd-foreground/80 peer-disabled:cursor-not-allowed peer-disabled:opacity-70');
5
+ export const labelVariants = cva('text-xs font-medium text-fd-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70');
6
6
  const Input = React.forwardRef(({ className, type, ...props }, ref) => {
7
7
  return (_jsx("input", { type: type, className: cn('flex h-9 w-full rounded-md border bg-fd-secondary px-2 py-1.5 text-[13px] text-fd-secondary-foreground transition-colors placeholder:text-fd-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50', className), ref: ref, ...props }));
8
8
  });
@@ -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-3.5 text-fd-muted-foreground" }) })] })));
9
+ const SelectTrigger = forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn('flex items-center w-full rounded-md border p-2 gap-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;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAYlE,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,GAAG,cAAc,CAAC,cAAc,CAAC,2CAmB5C;AAED,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,2CAMhC;AAED,wBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,2CAmBzE;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,MAAM,EACN,GAAG,KAAK,EACT,EAAE,aAAa,2CAyBf;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,2CAY/D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAmBA;AAED,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAYlE,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,GAAG,cAAc,CAAC,cAAc,CAAC,2CAmB5C;AAED,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,2CAMhC;AAED,wBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC,2CAmBzE;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,MAAM,EACN,GAAG,KAAK,EACT,EAAE,aAAa,2CA+Bf;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,2CAY/D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAiBA;AAED,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/ui/index.js CHANGED
@@ -18,12 +18,14 @@ export function API({ children, ...props }) {
18
18
  }, children: children }));
19
19
  }
20
20
  export function Property({ name, type, required, deprecated, nested, ...props }) {
21
- return (_jsxs("div", { className: cn('flex flex-col gap-3 text-sm', !nested && 'p-3 border rounded-xl bg-fd-card'), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3 not-prose", children: [_jsxs("span", { className: "px-1 py-0.5 border rounded-md border-fd-primary/10 bg-fd-primary/10 font-mono text-xs text-fd-primary sm:text-[13px]", children: [name, required === false && '?'] }), _jsx("span", { className: "text-xs me-auto font-mono text-fd-muted-foreground", children: type }), deprecated && (_jsx(Badge, { color: "yellow", className: "text-xs", children: "Deprecated" }))] }), _jsx("div", { className: "prose-no-margin empty:hidden", children: props.children })] }));
21
+ return (_jsxs("div", { className: cn('text-sm border-t', nested
22
+ ? 'p-3 border-x bg-fd-card last:rounded-b-xl first:rounded-tr-xl last:border-b'
23
+ : 'py-4 first:border-t-0'), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2 not-prose", children: [_jsxs("span", { className: "font-medium font-mono text-fd-primary", children: [name, required === false && (_jsx("span", { className: "text-fd-muted-foreground", children: "?" }))] }), _jsx("span", { className: "me-auto text-xs font-mono text-fd-muted-foreground", children: type }), deprecated && (_jsx(Badge, { color: "yellow", className: "text-xs", children: "Deprecated" }))] }), _jsx("div", { className: "prose-no-margin pt-2.5 empty:hidden", children: props.children })] }));
22
24
  }
23
25
  export function APIExample(props) {
24
26
  return (_jsx("div", { ...props, className: cn('prose-no-margin md:sticky md:top-(--fd-api-info-top) xl:w-[400px]', props.className), children: props.children }));
25
27
  }
26
28
  export function ObjectCollapsible(props) {
27
- return (_jsxs(Collapsible, { ...props, children: [_jsxs(CollapsibleTrigger, { className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'group px-3 py-2 data-[state=open]:rounded-b-none data-[state=open]:border-b-0'), children: [props.name, _jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })] }), _jsx(CollapsibleContent, { className: "-me-3", children: _jsx("div", { className: "border-s border-y rounded-b-lg p-3", children: props.children }) })] }));
29
+ return (_jsxs(Collapsible, { ...props, children: [_jsxs(CollapsibleTrigger, { className: cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'group px-3 py-2 data-[state=open]:rounded-b-none'), children: [props.name, _jsx(ChevronDown, { className: "size-4 text-fd-muted-foreground group-data-[state=open]:rotate-180" })] }), _jsx(CollapsibleContent, { className: "-mt-px *:bg-fd-card", children: props.children })] }));
28
30
  }
29
31
  export { APIPage } from '../render/api-page.js';
@@ -0,0 +1,13 @@
1
+ import { type ComponentProps, type ReactNode } from 'react';
2
+ import { SelectTrigger } from '../ui/components/select.js';
3
+ export declare function SelectTabs({ defaultValue, children, }: {
4
+ defaultValue?: string;
5
+ children: ReactNode;
6
+ }): import("react/jsx-runtime").JSX.Element;
7
+ export declare function SelectTab({ value, ...props }: ComponentProps<'div'> & {
8
+ value: string;
9
+ }): import("react/jsx-runtime").JSX.Element | undefined;
10
+ export declare function SelectTabTrigger({ items, ...props }: ComponentProps<typeof SelectTrigger> & {
11
+ items: string[];
12
+ }): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=select-tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-tabs.d.ts","sourceRoot":"","sources":["../../src/ui/select-tabs.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AACf,OAAO,EAIL,aAAa,EAEd,MAAM,wBAAwB,CAAC;AAQhC,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,QAAQ,GACT,EAAE;IACD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAQA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;CACf,uDAKA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,aAAa,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,2CAoB5D"}