fumadocs-openapi 4.4.2 → 5.0.1

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.
@@ -0,0 +1,93 @@
1
+ 'use client';
2
+ import { useContext, createContext, useState, useEffect } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import { Check, Copy } from 'lucide-react';
5
+ import { cn, useCopyButton, buttonVariants } from 'fumadocs-ui/components/api';
6
+ import dynamic from 'next/dynamic';
7
+
8
+ const ApiContext = /*#__PURE__*/ createContext({
9
+ baseUrl: undefined,
10
+ setBaseUrl: ()=>undefined,
11
+ highlighter: null
12
+ });
13
+ function useApiContext() {
14
+ return useContext(ApiContext);
15
+ }
16
+ async function initHighlighter() {
17
+ const { createHighlighterCore } = await import('shiki/core');
18
+ const getWasm = await import('shiki/wasm');
19
+ return createHighlighterCore({
20
+ themes: [
21
+ import('shiki/themes/github-light.mjs'),
22
+ import('shiki/themes/github-dark.mjs')
23
+ ],
24
+ langs: [
25
+ import('shiki/langs/json.mjs')
26
+ ],
27
+ loadWasm: getWasm
28
+ });
29
+ }
30
+ function ApiProvider({ defaultBaseUrl, children }) {
31
+ const [highlighter, setHighlighter] = useState(null);
32
+ const [baseUrl, setBaseUrl] = useState(defaultBaseUrl);
33
+ useEffect(()=>{
34
+ setBaseUrl((prev)=>localStorage.getItem('apiBaseUrl') ?? prev);
35
+ void initHighlighter().then((res)=>{
36
+ setHighlighter(res);
37
+ });
38
+ }, []);
39
+ useEffect(()=>{
40
+ if (baseUrl) localStorage.setItem('apiBaseUrl', baseUrl);
41
+ }, [
42
+ baseUrl
43
+ ]);
44
+ return /*#__PURE__*/ jsx(ApiContext.Provider, {
45
+ value: {
46
+ baseUrl,
47
+ setBaseUrl,
48
+ highlighter
49
+ },
50
+ children: children
51
+ });
52
+ }
53
+
54
+ const SchemaContext = /*#__PURE__*/ createContext(undefined);
55
+ function useSchemaContext() {
56
+ const ctx = useContext(SchemaContext);
57
+ if (!ctx) throw new Error('Missing provider');
58
+ return ctx;
59
+ }
60
+
61
+ const APIPlayground = dynamic(()=>import('./playground-client-Cn3a3hra.js').then((mod)=>mod.APIPlayground));
62
+ function Root({ children, baseUrl, className, ...props }) {
63
+ return /*#__PURE__*/ jsx("div", {
64
+ className: cn('flex flex-col gap-24 text-sm text-fd-muted-foreground', className),
65
+ ...props,
66
+ children: /*#__PURE__*/ jsx(ApiProvider, {
67
+ defaultBaseUrl: baseUrl,
68
+ children: children
69
+ })
70
+ });
71
+ }
72
+ function CopyRouteButton({ className, route, ...props }) {
73
+ const { baseUrl } = useApiContext();
74
+ const [checked, onCopy] = useCopyButton(()=>{
75
+ void navigator.clipboard.writeText(`${baseUrl ?? ''}${route}`);
76
+ });
77
+ return /*#__PURE__*/ jsx("button", {
78
+ type: "button",
79
+ className: cn(buttonVariants({
80
+ color: 'ghost',
81
+ className
82
+ })),
83
+ onClick: onCopy,
84
+ ...props,
85
+ children: checked ? /*#__PURE__*/ jsx(Check, {
86
+ className: "size-3"
87
+ }) : /*#__PURE__*/ jsx(Copy, {
88
+ className: "size-3"
89
+ })
90
+ });
91
+ }
92
+
93
+ export { APIPlayground as A, CopyRouteButton as C, Root as R, SchemaContext as S, useApiContext as a, useSchemaContext as u };
@@ -1,8 +1,78 @@
1
1
  import * as react from 'react';
2
- import { ReactElement, HTMLAttributes, ReactNode, MutableRefObject } from 'react';
2
+ import { ReactNode, ReactElement, MutableRefObject, HTMLAttributes } from 'react';
3
3
  import { FieldPath, ControllerRenderProps, ControllerFieldState, UseFormStateReturn } from 'react-hook-form';
4
- import { R as RequestSchema, a as ReferenceSchema, A as APIPlaygroundProps, P as PrimitiveRequestField } from '../playground-vSsfCaVw.js';
5
- import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
4
+
5
+ interface BaseRequestField {
6
+ name: string;
7
+ description?: string;
8
+ }
9
+ interface BaseSchema {
10
+ description?: string;
11
+ isRequired: boolean;
12
+ }
13
+ type PrimitiveRequestField = BaseRequestField & PrimitiveSchema;
14
+ interface PrimitiveSchema extends BaseSchema {
15
+ type: 'boolean' | 'string' | 'number';
16
+ defaultValue: string;
17
+ }
18
+ interface ReferenceSchema extends BaseSchema {
19
+ type: 'ref';
20
+ schema: string;
21
+ }
22
+ interface ArraySchema extends BaseSchema {
23
+ type: 'array';
24
+ /**
25
+ * Reference to item schema or the schema
26
+ */
27
+ items: string | RequestSchema;
28
+ }
29
+ interface FileSchema extends BaseSchema {
30
+ type: 'file';
31
+ }
32
+ interface ObjectSchema extends BaseSchema {
33
+ type: 'object';
34
+ properties: Record<string, ReferenceSchema>;
35
+ /**
36
+ * Reference to schema, or true if it's `any`
37
+ */
38
+ additionalProperties?: boolean | string;
39
+ }
40
+ interface SwitcherSchema extends BaseSchema {
41
+ type: 'switcher';
42
+ items: Record<string, ReferenceSchema | RequestSchema>;
43
+ }
44
+ interface NullSchema extends BaseSchema {
45
+ type: 'null';
46
+ }
47
+ type RequestSchema = PrimitiveSchema | ArraySchema | ObjectSchema | SwitcherSchema | NullSchema | FileSchema;
48
+ interface APIPlaygroundProps {
49
+ route: string;
50
+ method: string;
51
+ bodyType: 'json' | 'form-data';
52
+ authorization?: PrimitiveRequestField;
53
+ path?: PrimitiveRequestField[];
54
+ query?: PrimitiveRequestField[];
55
+ header?: PrimitiveRequestField[];
56
+ body?: RequestSchema;
57
+ schemas: Record<string, RequestSchema>;
58
+ }
59
+
60
+ interface APIInfoProps {
61
+ method: string;
62
+ route: string;
63
+ children: ReactNode;
64
+ }
65
+ interface PropertyProps {
66
+ name: string;
67
+ type: string;
68
+ required?: boolean;
69
+ deprecated?: boolean;
70
+ children?: ReactNode;
71
+ }
72
+ interface RootProps {
73
+ baseUrl?: string;
74
+ children: ReactNode;
75
+ }
6
76
 
7
77
  interface FormValues {
8
78
  authorization: string;
@@ -23,40 +93,6 @@ interface CustomField<TName extends FieldPath<FormValues>, Info> {
23
93
  }) => ReactElement;
24
94
  }
25
95
 
26
- interface RootProps extends HTMLAttributes<HTMLDivElement> {
27
- baseUrl?: string;
28
- }
29
- declare function Root({ children, baseUrl, className, ...props }: RootProps): React.ReactElement;
30
- declare function API({ className, children, ...props }: HTMLAttributes<HTMLDivElement>): React.ReactElement;
31
- interface APIInfoProps extends HTMLAttributes<HTMLDivElement> {
32
- route: string;
33
- method?: string;
34
- badgeClassName?: string;
35
- }
36
- declare function APIInfo({ children, className, route, badgeClassName, method, ...props }: APIInfoProps): React.ReactElement;
37
- interface PropertyProps {
38
- name: string;
39
- type: string;
40
- required: boolean;
41
- deprecated: boolean;
42
- children: ReactNode;
43
- }
44
- declare function Property({ name, type, required, deprecated, children, }: PropertyProps): React.ReactElement;
45
- declare function APIExample({ children, className, ...props }: HTMLAttributes<HTMLDivElement>): React.ReactElement;
46
- declare function ResponseTypes(props: {
47
- children: ReactNode;
48
- }): React.ReactElement;
49
- declare function ExampleResponse(props: {
50
- children: ReactNode;
51
- }): React.ReactElement;
52
- declare function TypeScriptResponse(props: {
53
- children: ReactNode;
54
- }): React.ReactElement;
55
- declare function ObjectCollapsible(props: {
56
- name: string;
57
- children: ReactNode;
58
- }): React.ReactElement;
59
-
60
96
  interface SchemaContextType {
61
97
  references: Record<string, RequestSchema>;
62
98
  dynamic: MutableRefObject<Map<string, DynamicField>>;
@@ -78,10 +114,18 @@ declare const APIPlayground: react.ComponentType<APIPlaygroundProps & {
78
114
  header?: CustomField<`header.${string}`, PrimitiveRequestField>;
79
115
  body?: CustomField<"body", RequestSchema>;
80
116
  };
81
- } & react.HTMLAttributes<HTMLFormElement>>;
82
- declare const Responses: typeof Tabs;
83
- declare const Response: typeof Tab;
84
- declare const Requests: typeof Tabs;
85
- declare const Request: typeof Tab;
117
+ } & HTMLAttributes<HTMLFormElement>>;
118
+ declare function Root({ children, baseUrl, className, ...props }: RootProps & HTMLAttributes<HTMLDivElement>): React.ReactElement;
119
+
120
+ declare function APIInfo({ children, className, route, badgeClassname, method, ...props }: APIInfoProps & HTMLAttributes<HTMLDivElement> & {
121
+ badgeClassname?: string;
122
+ }): React.ReactElement;
123
+ declare function API({ className, children, ...props }: HTMLAttributes<HTMLDivElement>): React.ReactElement;
124
+ declare function Property({ name, type, required, deprecated, children, }: PropertyProps): React.ReactElement;
125
+ declare function APIExample({ children, className, ...props }: HTMLAttributes<HTMLDivElement>): React.ReactElement;
126
+ declare function ObjectCollapsible(props: {
127
+ name: string;
128
+ children: ReactNode;
129
+ }): React.ReactElement;
86
130
 
87
- export { API, APIExample, APIInfo, type APIInfoProps, APIPlayground, ExampleResponse, ObjectCollapsible, Property, Request, Requests, Response, ResponseTypes, Responses, Root, type RootProps, TypeScriptResponse, useSchemaContext };
131
+ export { API, APIExample, APIInfo, APIPlayground, ObjectCollapsible, Property, Root, useSchemaContext };
package/dist/ui/index.js CHANGED
@@ -1,201 +1,142 @@
1
- "use client";
2
- import {
3
- ApiProvider,
4
- useApiContext,
5
- useSchemaContext
6
- } from "../chunk-N4P4W4VJ.js";
7
- import {
8
- badgeVariants,
9
- getBadgeColor
10
- } from "../chunk-UG2WFM5D.js";
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';
5
+ import { cva } from 'class-variance-authority';
6
+ import { C as CopyRouteButton } from './client-client-CMzXLiVt.js';
7
+ export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-CMzXLiVt.js';
11
8
 
12
- // src/ui/index.ts
13
- import { Tab, Tabs } from "fumadocs-ui/components/tabs";
14
- import dynamic from "next/dynamic";
15
-
16
- // src/ui/components.tsx
17
- import {
18
- Fragment
19
- } from "react";
20
- import { Check, Copy } from "lucide-react";
21
- import { Accordion, Accordions } from "fumadocs-ui/components/accordion";
22
- import { cn, useCopyButton, buttonVariants } from "fumadocs-ui/components/api";
23
- import { jsx, jsxs } from "react/jsx-runtime";
24
- function Root({
25
- children,
26
- baseUrl,
27
- className,
28
- ...props
29
- }) {
30
- return /* @__PURE__ */ jsx(
31
- "div",
32
- {
33
- className: cn(
34
- "flex flex-col gap-24 text-sm text-fd-muted-foreground",
35
- className
36
- ),
37
- ...props,
38
- children: /* @__PURE__ */ jsx(ApiProvider, { defaultBaseUrl: baseUrl, children })
9
+ const badgeVariants = cva('rounded border px-1.5 py-1 text-xs font-medium leading-[12px]', {
10
+ variants: {
11
+ color: {
12
+ green: 'border-green-400/50 bg-green-400/20 text-green-600 dark:text-green-400',
13
+ yellow: 'border-yellow-400/50 bg-yellow-400/20 text-yellow-600 dark:text-yellow-400',
14
+ red: 'border-red-400/50 bg-red-400/20 text-red-600 dark:text-red-400',
15
+ blue: 'border-blue-400/50 bg-blue-400/20 text-blue-600 dark:text-blue-400',
16
+ orange: 'border-orange-400/50 bg-orange-400/20 text-orange-600 dark:text-orange-400'
17
+ }
39
18
  }
40
- );
41
- }
42
- function API({
43
- className,
44
- children,
45
- ...props
46
- }) {
47
- return /* @__PURE__ */ jsx(
48
- "div",
49
- {
50
- className: cn(
51
- "flex flex-col gap-x-6 gap-y-2 xl:flex-row xl:items-start",
52
- className
53
- ),
54
- ...props,
55
- children
19
+ });
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';
56
32
  }
57
- );
58
33
  }
34
+
59
35
  function Route({ route }) {
60
- const segments = route.split("/").filter((part) => part.length > 0);
61
- return /* @__PURE__ */ jsx("div", { className: "flex flex-row flex-wrap items-center gap-1 text-sm", children: segments.map((part, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
62
- /* @__PURE__ */ jsx("span", { className: "text-fd-muted-foreground", children: "/" }),
63
- part.startsWith("{") && part.endsWith("}") ? /* @__PURE__ */ jsx("code", { className: "text-fd-primary", children: part }) : /* @__PURE__ */ jsx("span", { className: "text-fd-foreground", children: part })
64
- ] }, index)) });
36
+ const segments = route.split('/').filter((part)=>part.length > 0);
37
+ return /*#__PURE__*/ jsx("div", {
38
+ className: "flex flex-row flex-wrap items-center gap-1 text-sm",
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: "text-fd-primary",
47
+ children: part
48
+ }) : /*#__PURE__*/ jsx("span", {
49
+ className: "text-fd-foreground",
50
+ children: part
51
+ })
52
+ ]
53
+ }, index))
54
+ });
65
55
  }
66
- function APIInfo({
67
- children,
68
- className,
69
- route,
70
- badgeClassName,
71
- method = "GET",
72
- ...props
73
- }) {
74
- return /* @__PURE__ */ jsxs("div", { className: cn("min-w-0 flex-1", className), ...props, children: [
75
- /* @__PURE__ */ jsxs(
76
- "div",
77
- {
78
- className: cn(
79
- "sticky top-24 z-[2] mb-4 flex flex-row items-center gap-2 rounded-lg border bg-fd-card p-3 md:top-10"
80
- ),
56
+ function APIInfo({ children, className, route, badgeClassname, method = 'GET', ...props }) {
57
+ return /*#__PURE__*/ jsxs("div", {
58
+ className: cn('min-w-0 flex-1', className),
59
+ ...props,
81
60
  children: [
82
- /* @__PURE__ */ jsx(
83
- "span",
84
- {
85
- className: cn(
86
- badgeVariants({ color: getBadgeColor(method) }),
87
- badgeClassName
88
- ),
89
- children: method
90
- }
91
- ),
92
- /* @__PURE__ */ jsx(Route, { route }),
93
- /* @__PURE__ */ jsx(CopyRouteButton, { className: "ms-auto size-6 p-1", route })
61
+ /*#__PURE__*/ jsxs("div", {
62
+ className: cn('sticky top-24 z-[2] mb-4 flex flex-row items-center gap-2 rounded-lg border bg-fd-card p-3 md:top-10'),
63
+ children: [
64
+ /*#__PURE__*/ jsx("span", {
65
+ className: cn(badgeVariants({
66
+ color: getBadgeColor(method)
67
+ }), badgeClassname),
68
+ children: method
69
+ }),
70
+ /*#__PURE__*/ jsx(Route, {
71
+ route: route
72
+ }),
73
+ /*#__PURE__*/ jsx(CopyRouteButton, {
74
+ className: "ms-auto size-6 p-1",
75
+ route: route
76
+ })
77
+ ]
78
+ }),
79
+ /*#__PURE__*/ jsx("div", {
80
+ className: "prose-no-margin",
81
+ children: children
82
+ })
94
83
  ]
95
- }
96
- ),
97
- /* @__PURE__ */ jsx("div", { className: "prose-no-margin", children })
98
- ] });
84
+ });
99
85
  }
100
- function Property({
101
- name,
102
- type,
103
- required,
104
- deprecated,
105
- children
106
- }) {
107
- return /* @__PURE__ */ jsxs("div", { className: "mb-4 flex flex-col rounded-lg border bg-fd-card p-3 prose-no-margin", children: [
108
- /* @__PURE__ */ jsxs("h4", { className: "inline-flex items-center gap-4", children: [
109
- /* @__PURE__ */ jsx("code", { children: name }),
110
- required ? /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ color: "red" })), children: "Required" }) : null,
111
- deprecated ? /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ color: "yellow" })), children: "Deprecated" }) : null,
112
- /* @__PURE__ */ jsx("span", { className: "ms-auto font-mono text-[13px] text-fd-muted-foreground", children: type })
113
- ] }),
114
- children
115
- ] });
86
+ function API({ className, children, ...props }) {
87
+ return /*#__PURE__*/ jsx("div", {
88
+ className: cn('flex flex-col gap-x-6 gap-y-2 xl:flex-row xl:items-start', className),
89
+ ...props,
90
+ children: children
91
+ });
116
92
  }
117
- function APIExample({
118
- children,
119
- className,
120
- ...props
121
- }) {
122
- return /* @__PURE__ */ jsx(
123
- "div",
124
- {
125
- className: cn("sticky top-10 prose-no-margin xl:w-[400px]", className),
126
- ...props,
127
- children
128
- }
129
- );
130
- }
131
- function ResponseTypes(props) {
132
- return /* @__PURE__ */ jsx(
133
- Accordions,
134
- {
135
- type: "single",
136
- className: "!-m-4 border-none pt-2",
137
- defaultValue: "Response",
138
- children: props.children
139
- }
140
- );
141
- }
142
- function ExampleResponse(props) {
143
- return /* @__PURE__ */ jsx(Accordion, { title: "Response", children: props.children });
93
+ function Property({ name, type, required, deprecated, children }) {
94
+ return /*#__PURE__*/ jsxs("div", {
95
+ className: "mb-4 flex flex-col rounded-lg border bg-fd-card p-3 prose-no-margin",
96
+ children: [
97
+ /*#__PURE__*/ jsxs("h4", {
98
+ className: "inline-flex items-center gap-4",
99
+ children: [
100
+ /*#__PURE__*/ jsx("code", {
101
+ children: name
102
+ }),
103
+ required ? /*#__PURE__*/ jsx("div", {
104
+ className: cn(badgeVariants({
105
+ color: 'red'
106
+ })),
107
+ children: "Required"
108
+ }) : null,
109
+ deprecated ? /*#__PURE__*/ jsx("div", {
110
+ className: cn(badgeVariants({
111
+ color: 'yellow'
112
+ })),
113
+ children: "Deprecated"
114
+ }) : null,
115
+ /*#__PURE__*/ jsx("span", {
116
+ className: "ms-auto font-mono text-[13px] text-fd-muted-foreground",
117
+ children: type
118
+ })
119
+ ]
120
+ }),
121
+ children
122
+ ]
123
+ });
144
124
  }
145
- function TypeScriptResponse(props) {
146
- return /* @__PURE__ */ jsx(Accordion, { title: "Typescript", children: props.children });
125
+ function APIExample({ children, className, ...props }) {
126
+ return /*#__PURE__*/ jsx("div", {
127
+ className: cn('sticky top-10 prose-no-margin xl:w-[400px]', className),
128
+ ...props,
129
+ children: children
130
+ });
147
131
  }
148
132
  function ObjectCollapsible(props) {
149
- return /* @__PURE__ */ jsx(Accordions, { type: "single", children: /* @__PURE__ */ jsx(Accordion, { title: props.name, children: props.children }) });
150
- }
151
- function CopyRouteButton({
152
- className,
153
- route,
154
- ...props
155
- }) {
156
- const { baseUrl } = useApiContext();
157
- const [checked, onCopy] = useCopyButton(() => {
158
- void navigator.clipboard.writeText(`${baseUrl ?? ""}${route}`);
159
- });
160
- return /* @__PURE__ */ jsx(
161
- "button",
162
- {
163
- type: "button",
164
- className: cn(
165
- buttonVariants({
166
- color: "ghost",
167
- className
133
+ return /*#__PURE__*/ jsx(Accordions, {
134
+ type: "single",
135
+ children: /*#__PURE__*/ jsx(Accordion, {
136
+ title: props.name,
137
+ children: props.children
168
138
  })
169
- ),
170
- onClick: onCopy,
171
- ...props,
172
- children: checked ? /* @__PURE__ */ jsx(Check, { className: "size-3" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3" })
173
- }
174
- );
139
+ });
175
140
  }
176
141
 
177
- // src/ui/index.ts
178
- var APIPlayground = dynamic(
179
- () => import("../playground-GIGTWHCL.js").then((mod) => mod.APIPlayground)
180
- );
181
- var Responses = Tabs;
182
- var Response = Tab;
183
- var Requests = Tabs;
184
- var Request = Tab;
185
- export {
186
- API,
187
- APIExample,
188
- APIInfo,
189
- APIPlayground,
190
- ExampleResponse,
191
- ObjectCollapsible,
192
- Property,
193
- Request,
194
- Requests,
195
- Response,
196
- ResponseTypes,
197
- Responses,
198
- Root,
199
- TypeScriptResponse,
200
- useSchemaContext
201
- };
142
+ export { API, APIExample, APIInfo, ObjectCollapsible, Property };