fumadocs-openapi 5.11.7 → 5.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,6 +46,12 @@ interface CodeSample {
46
46
  source: string | ((endpoint: EndpointSample) => string | undefined) | false;
47
47
  }
48
48
 
49
+ type ProcessedDocument = {
50
+ document: NoReference<Document>;
51
+ dereferenceMap: DereferenceMap;
52
+ downloaded: Document;
53
+ };
54
+
49
55
  type Document = OpenAPIV3_1.Document;
50
56
  type ReferenceObject = OpenAPIV3_1.ReferenceObject;
51
57
  type ServerObject = NoReference<OpenAPIV3_1.ServerObject>;
@@ -55,19 +61,22 @@ type Awaitable<T> = T | Promise<T>;
55
61
  */
56
62
  type DereferenceMap = Map<unknown, string>;
57
63
  interface RenderContext {
64
+ /**
65
+ * Use Scalar for API Playground
66
+ */
67
+ useScalar: boolean;
58
68
  /**
59
69
  * The url of proxy to avoid CORS issues
60
70
  */
61
71
  proxyUrl?: string;
62
72
  renderer: Renderer;
63
- /**
64
- * dereferenced schema
65
- */
66
- document: NoReference<Document>;
67
73
  baseUrl: string;
68
74
  servers: ServerObject[];
69
75
  slugger: Slugger;
70
- dereferenceMap: DereferenceMap;
76
+ /**
77
+ * dereferenced schema
78
+ */
79
+ schema: ProcessedDocument;
71
80
  /**
72
81
  * Generate TypeScript definitions from response schema.
73
82
  *
@@ -267,13 +276,16 @@ declare const APIPlayground: react.ComponentType<APIPlaygroundProps & {
267
276
  }>;
268
277
  }>;
269
278
  } & HTMLAttributes<HTMLFormElement>>;
279
+ declare const ScalarPlayground: react.ComponentType<{
280
+ spec: object;
281
+ path: string;
282
+ method: string;
283
+ }>;
270
284
  declare function Root({ children, baseUrl, className, shikiOptions, servers, ...props }: RootProps & {
271
285
  shikiOptions: RenderContext['shikiOptions'];
272
286
  } & HTMLAttributes<HTMLDivElement>): ReactNode;
273
287
 
274
- declare function APIInfo({ className, route, badgeClassname, method, head, ...props }: APIInfoProps & HTMLAttributes<HTMLDivElement> & {
275
- badgeClassname?: string;
276
- }): react_jsx_runtime.JSX.Element;
288
+ declare function APIInfo({ className, ...props }: HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
277
289
  declare function API({ children, ...props }: HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
278
290
  declare function Property({ name, type, required, deprecated, children, }: PropertyProps): react_jsx_runtime.JSX.Element;
279
291
  declare function APIExample(props: HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
@@ -282,4 +294,4 @@ declare function ObjectCollapsible(props: {
282
294
  children: ReactNode;
283
295
  }): react_jsx_runtime.JSX.Element;
284
296
 
285
- export { API, APIExample, APIInfo, APIPlayground, ObjectCollapsible, Property, Root, useSchemaContext };
297
+ export { API, APIExample, APIInfo, APIPlayground, ObjectCollapsible, Property, Root, ScalarPlayground, useSchemaContext };
package/dist/ui/index.js CHANGED
@@ -1,10 +1,9 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { cn } from 'fumadocs-ui/components/api';
3
- import { Fragment } from 'react';
4
- import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { cn, buttonVariants } from 'fumadocs-ui/components/api';
5
3
  import { cva } from 'class-variance-authority';
6
- import { h as CopyRouteButton, i as ServerSelect } from './client-client-B06fJG48.js';
7
- export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-B06fJG48.js';
4
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent } from 'fumadocs-ui/components/ui/collapsible';
5
+ import { C as ChevronDown } from './client-client-Die8irpf.js';
6
+ export { A as APIPlayground, R as Root, h as ScalarPlayground, u as useSchemaContext } from './client-client-Die8irpf.js';
8
7
 
9
8
  const badgeVariants = cva('rounded-xl border px-1.5 py-1 text-xs font-medium leading-[12px]', {
10
9
  variants: {
@@ -17,77 +16,12 @@ const badgeVariants = cva('rounded-xl border px-1.5 py-1 text-xs font-medium lea
17
16
  }
18
17
  }
19
18
  });
20
- function getBadgeColor(method) {
21
- switch(method){
22
- case 'PUT':
23
- return 'yellow';
24
- case 'PATCH':
25
- return 'orange';
26
- case 'POST':
27
- return 'blue';
28
- case 'DELETE':
29
- return 'red';
30
- default:
31
- return 'green';
32
- }
33
- }
34
19
 
35
- function Route({ route }) {
36
- const segments = route.split('/').filter((part)=>part.length > 0);
20
+ function APIInfo({ className, ...props }) {
37
21
  return /*#__PURE__*/ jsx("div", {
38
- className: "not-prose flex flex-row items-center gap-0.5 overflow-auto text-nowrap text-xs",
39
- children: segments.map((part, index)=>/*#__PURE__*/ jsxs(Fragment, {
40
- children: [
41
- /*#__PURE__*/ jsx("span", {
42
- className: "text-fd-muted-foreground",
43
- children: "/"
44
- }),
45
- part.startsWith('{') && part.endsWith('}') ? /*#__PURE__*/ jsx("code", {
46
- className: "bg-fd-primary/10 text-fd-primary",
47
- children: part
48
- }) : /*#__PURE__*/ jsx("code", {
49
- className: "text-fd-foreground",
50
- children: part
51
- })
52
- ]
53
- }, index))
54
- });
55
- }
56
- function APIInfo({ className, route, badgeClassname, method = 'GET', head, ...props }) {
57
- return /*#__PURE__*/ jsxs("div", {
58
22
  className: cn('min-w-0 flex-1', className),
59
23
  ...props,
60
- children: [
61
- head,
62
- /*#__PURE__*/ jsxs("div", {
63
- className: "not-prose mb-4 rounded-lg border bg-fd-card p-3 text-fd-card-foreground shadow-lg",
64
- children: [
65
- /*#__PURE__*/ jsxs("div", {
66
- className: "-mx-1 flex flex-row items-center gap-1.5",
67
- children: [
68
- /*#__PURE__*/ jsx("span", {
69
- className: cn(badgeVariants({
70
- color: getBadgeColor(method)
71
- }), badgeClassname),
72
- children: method
73
- }),
74
- /*#__PURE__*/ jsx(Route, {
75
- route: route
76
- }),
77
- /*#__PURE__*/ jsx(CopyRouteButton, {
78
- className: "ms-auto size-6 p-1.5",
79
- route: route
80
- })
81
- ]
82
- }),
83
- /*#__PURE__*/ jsx(ServerSelect, {})
84
- ]
85
- }),
86
- /*#__PURE__*/ jsx("div", {
87
- className: "prose-no-margin",
88
- children: props.children
89
- })
90
- ]
24
+ children: props.children
91
25
  });
92
26
  }
93
27
  function API({ children, ...props }) {
@@ -103,9 +37,9 @@ function API({ children, ...props }) {
103
37
  }
104
38
  function Property({ name, type, required, deprecated, children }) {
105
39
  return /*#__PURE__*/ jsxs("div", {
106
- className: "mb-4 rounded-lg border bg-fd-card p-3 prose-no-margin",
40
+ className: "rounded-xl border bg-fd-card p-3 prose-no-margin",
107
41
  children: [
108
- /*#__PURE__*/ jsxs("h4", {
42
+ /*#__PURE__*/ jsxs("div", {
109
43
  className: "flex flex-row flex-wrap items-center gap-4",
110
44
  children: [
111
45
  /*#__PURE__*/ jsx("code", {
@@ -124,7 +58,7 @@ function Property({ name, type, required, deprecated, children }) {
124
58
  children: "Deprecated"
125
59
  }) : null,
126
60
  /*#__PURE__*/ jsx("span", {
127
- className: "ms-auto font-mono text-[13px] text-fd-muted-foreground",
61
+ className: "ms-auto text-xs font-mono text-fd-muted-foreground",
128
62
  children: type
129
63
  })
130
64
  ]
@@ -141,12 +75,29 @@ function APIExample(props) {
141
75
  });
142
76
  }
143
77
  function ObjectCollapsible(props) {
144
- return /*#__PURE__*/ jsx(Accordions, {
145
- type: "single",
146
- children: /*#__PURE__*/ jsx(Accordion, {
147
- title: props.name,
148
- children: props.children
149
- })
78
+ return /*#__PURE__*/ jsxs(Collapsible, {
79
+ ...props,
80
+ children: [
81
+ /*#__PURE__*/ jsxs(CollapsibleTrigger, {
82
+ className: cn(buttonVariants({
83
+ color: 'outline',
84
+ size: 'sm'
85
+ }), 'group rounded-full px-2 py-1.5 text-fd-muted-foreground'),
86
+ children: [
87
+ props.name,
88
+ /*#__PURE__*/ jsx(ChevronDown, {
89
+ className: "size-4 group-data-[state=open]:rotate-180"
90
+ })
91
+ ]
92
+ }),
93
+ /*#__PURE__*/ jsx(CollapsibleContent, {
94
+ className: "-mx-2",
95
+ children: /*#__PURE__*/ jsx("div", {
96
+ className: "flex flex-col gap-2 p-2",
97
+ children: props.children
98
+ })
99
+ })
100
+ ]
150
101
  });
151
102
  }
152
103
 
@@ -0,0 +1,86 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { e as useApiContext, f as useServerSelectContext } from './client-client-Die8irpf.js';
4
+ import { S as Select, a as SelectTrigger, b as SelectValue, c as SelectContent, d as SelectItem, l as labelVariants, I as Input } from './index-client-XPLtFTfD.js';
5
+ import { cn } from 'fumadocs-ui/components/api';
6
+
7
+ function ServerSelect(props) {
8
+ const { servers } = useApiContext();
9
+ const { server, setServer, setServerVariables } = useServerSelectContext();
10
+ if (servers.length <= 1) return null;
11
+ const schema = server ? servers.find((item)=>item.url === server.url) : undefined;
12
+ return /*#__PURE__*/ jsxs("div", {
13
+ ...props,
14
+ className: cn('flex flex-col gap-4', props.className),
15
+ children: [
16
+ /*#__PURE__*/ jsxs(Select, {
17
+ value: server?.url,
18
+ onValueChange: setServer,
19
+ children: [
20
+ /*#__PURE__*/ jsx(SelectTrigger, {
21
+ className: "h-auto break-all",
22
+ children: /*#__PURE__*/ jsx(SelectValue, {})
23
+ }),
24
+ /*#__PURE__*/ jsx(SelectContent, {
25
+ children: servers.map((item)=>/*#__PURE__*/ jsxs(SelectItem, {
26
+ value: item.url,
27
+ children: [
28
+ item.url,
29
+ /*#__PURE__*/ jsx("p", {
30
+ className: "text-start text-fd-muted-foreground",
31
+ children: item.description
32
+ })
33
+ ]
34
+ }, item.url))
35
+ })
36
+ ]
37
+ }),
38
+ Object.entries(schema?.variables ?? {}).map(([key, variable])=>{
39
+ if (!server) return;
40
+ const id = `fd_server_select_${key}`;
41
+ return /*#__PURE__*/ jsxs("fieldset", {
42
+ className: "flex flex-col gap-1",
43
+ children: [
44
+ /*#__PURE__*/ jsx("label", {
45
+ className: cn(labelVariants()),
46
+ htmlFor: id,
47
+ children: key
48
+ }),
49
+ /*#__PURE__*/ jsx("p", {
50
+ className: "text-xs text-fd-muted-foreground empty:hidden",
51
+ children: variable.description
52
+ }),
53
+ variable.enum ? /*#__PURE__*/ jsxs(Select, {
54
+ value: server.variables[key],
55
+ onValueChange: (v)=>setServerVariables({
56
+ ...server?.variables,
57
+ [key]: v
58
+ }),
59
+ children: [
60
+ /*#__PURE__*/ jsx(SelectTrigger, {
61
+ id: id,
62
+ children: /*#__PURE__*/ jsx(SelectValue, {})
63
+ }),
64
+ /*#__PURE__*/ jsx(SelectContent, {
65
+ children: variable.enum.map((value)=>/*#__PURE__*/ jsx(SelectItem, {
66
+ value: value,
67
+ children: value
68
+ }, value))
69
+ })
70
+ ]
71
+ }) : /*#__PURE__*/ jsx(Input, {
72
+ id: id,
73
+ value: server.variables[key],
74
+ onChange: (e)=>setServerVariables({
75
+ ...server?.variables,
76
+ [key]: e.target.value
77
+ })
78
+ })
79
+ ]
80
+ }, key);
81
+ })
82
+ ]
83
+ });
84
+ }
85
+
86
+ export { ServerSelect as S };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "5.11.7",
3
+ "version": "5.12.0",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -32,7 +32,7 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@fumari/json-schema-to-typescript": "^1.1.2",
35
- "@radix-ui/react-select": "^2.1.4",
35
+ "@radix-ui/react-select": "^2.1.5",
36
36
  "@radix-ui/react-slot": "^1.1.1",
37
37
  "@scalar/openapi-parser": "0.10.4",
38
38
  "ajv-draft-04": "^1.0.0",
@@ -41,32 +41,41 @@
41
41
  "github-slugger": "^2.0.0",
42
42
  "hast-util-to-jsx-runtime": "^2.3.2",
43
43
  "js-yaml": "^4.1.0",
44
+ "next-themes": "^0.4.4",
44
45
  "openapi-sampler": "^1.6.1",
45
46
  "react-hook-form": "^7.54.2",
46
47
  "remark": "^15.0.1",
47
48
  "remark-rehype": "^11.1.1",
48
- "shiki": "^2.0.3",
49
+ "shiki": "^2.1.0",
49
50
  "xml-js": "^1.6.11",
50
- "fumadocs-core": "14.7.6",
51
- "fumadocs-ui": "14.7.6"
51
+ "fumadocs-core": "15.0.0",
52
+ "fumadocs-ui": "15.0.0"
52
53
  },
53
54
  "devDependencies": {
55
+ "@scalar/api-client-react": "^1.1.17",
54
56
  "@types/js-yaml": "^4.0.9",
55
- "@types/node": "22.10.7",
57
+ "@types/node": "22.10.9",
56
58
  "@types/openapi-sampler": "^1.0.3",
57
59
  "@types/react": "^19.0.7",
58
60
  "bunchee": "^6.3.2",
59
61
  "lucide-react": "^0.473.0",
60
- "next": "15.1.5",
62
+ "next": "15.1.6",
61
63
  "openapi-types": "^12.1.3",
64
+ "tailwindcss": "^4.0.0",
62
65
  "eslint-config-custom": "0.0.0",
63
66
  "tsconfig": "0.0.0"
64
67
  },
65
68
  "peerDependencies": {
69
+ "@scalar/api-client-react": "*",
66
70
  "next": "14.x.x || 15.x.x",
67
71
  "react": "18.x.x || 19.x.x",
68
72
  "react-dom": "18.x.x || 19.x.x"
69
73
  },
74
+ "peerDependenciesMeta": {
75
+ "@scalar/api-client-react": {
76
+ "optional": true
77
+ }
78
+ },
70
79
  "publishConfig": {
71
80
  "access": "public"
72
81
  },
@@ -1,101 +0,0 @@
1
- 'use client';
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { e as useApiContext, f as useServerSelectContext, C as ChevronDown } from './client-client-B06fJG48.js';
4
- import { Collapsible, CollapsibleTrigger, CollapsibleContent } from 'fumadocs-ui/components/ui/collapsible';
5
- import { S as Select, a as SelectTrigger, b as SelectValue, c as SelectContent, d as SelectItem, I as Input } from './index-client-DPqAL2w9.js';
6
-
7
- function ServerSelect() {
8
- const { servers } = useApiContext();
9
- const { server, setServer, setServerVariables } = useServerSelectContext();
10
- if (servers.length <= 1) return null;
11
- const schema = server ? servers.find((item)=>item.url === server.url) : undefined;
12
- return /*#__PURE__*/ jsxs(Collapsible, {
13
- className: "-m-2 mt-2",
14
- children: [
15
- /*#__PURE__*/ jsxs(CollapsibleTrigger, {
16
- className: "flex w-full flex-row items-center justify-between p-2 text-xs font-medium text-fd-muted-foreground",
17
- children: [
18
- "Configure Server",
19
- /*#__PURE__*/ jsx(ChevronDown, {
20
- className: "size-4"
21
- })
22
- ]
23
- }),
24
- /*#__PURE__*/ jsx(CollapsibleContent, {
25
- children: /*#__PURE__*/ jsxs("div", {
26
- className: "flex flex-col gap-4 p-2",
27
- children: [
28
- /*#__PURE__*/ jsxs(Select, {
29
- value: server?.url,
30
- onValueChange: setServer,
31
- children: [
32
- /*#__PURE__*/ jsx(SelectTrigger, {
33
- className: "h-auto break-all",
34
- children: /*#__PURE__*/ jsx(SelectValue, {})
35
- }),
36
- /*#__PURE__*/ jsx(SelectContent, {
37
- children: servers.map((item)=>/*#__PURE__*/ jsxs(SelectItem, {
38
- value: item.url,
39
- children: [
40
- item.url,
41
- /*#__PURE__*/ jsx("p", {
42
- className: "text-start text-xs text-fd-muted-foreground",
43
- children: item.description
44
- })
45
- ]
46
- }, item.url))
47
- })
48
- ]
49
- }),
50
- Object.entries(schema?.variables ?? {}).map(([key, variable])=>{
51
- if (!server) return;
52
- const id = `fd_server_select_${key}`;
53
- return /*#__PURE__*/ jsxs("fieldset", {
54
- className: "flex flex-col gap-1",
55
- children: [
56
- /*#__PURE__*/ jsx("label", {
57
- className: "font-mono text-xs text-fd-foreground",
58
- htmlFor: id,
59
- children: key
60
- }),
61
- /*#__PURE__*/ jsx("p", {
62
- className: "text-xs text-fd-muted-foreground empty:hidden",
63
- children: variable.description
64
- }),
65
- variable.enum ? /*#__PURE__*/ jsxs(Select, {
66
- value: server.variables[key],
67
- onValueChange: (v)=>setServerVariables({
68
- ...server?.variables,
69
- [key]: v
70
- }),
71
- children: [
72
- /*#__PURE__*/ jsx(SelectTrigger, {
73
- id: id,
74
- children: /*#__PURE__*/ jsx(SelectValue, {})
75
- }),
76
- /*#__PURE__*/ jsx(SelectContent, {
77
- children: variable.enum.map((value)=>/*#__PURE__*/ jsx(SelectItem, {
78
- value: value,
79
- children: value
80
- }, value))
81
- })
82
- ]
83
- }) : /*#__PURE__*/ jsx(Input, {
84
- id: id,
85
- value: server.variables[key],
86
- onChange: (e)=>setServerVariables({
87
- ...server?.variables,
88
- [key]: e.target.value
89
- })
90
- })
91
- ]
92
- }, key);
93
- })
94
- ]
95
- })
96
- })
97
- ]
98
- });
99
- }
100
-
101
- export { ServerSelect as default };