fumadocs-openapi 10.3.18 → 10.4.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.
- package/css/generated/shared.css +64 -15
- package/dist/i18n.d.ts +100 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +113 -0
- package/dist/i18n.js.map +1 -0
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +35 -23
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/components/inputs.js +16 -12
- package/dist/playground/components/inputs.js.map +1 -1
- package/dist/playground/components/oauth-dialog.js +45 -44
- package/dist/playground/components/oauth-dialog.js.map +1 -1
- package/dist/playground/components/server-select.js +7 -4
- package/dist/playground/components/server-select.js.map +1 -1
- package/dist/playground/status-info.js +18 -11
- package/dist/playground/status-info.js.map +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/base.d.ts +7 -6
- package/dist/ui/base.d.ts.map +1 -1
- package/dist/ui/base.js +13 -7
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/client/i18n.js +19 -0
- package/dist/ui/client/i18n.js.map +1 -0
- package/dist/ui/components/codeblock.d.ts +15 -0
- package/dist/ui/components/codeblock.d.ts.map +1 -0
- package/dist/ui/components/codeblock.js +27 -0
- package/dist/ui/components/codeblock.js.map +1 -0
- package/dist/ui/components/dialog.js +17 -13
- package/dist/ui/components/dialog.js.map +1 -1
- package/dist/ui/full.client.js +6 -7
- package/dist/ui/full.client.js.map +1 -1
- package/dist/ui/full.d.ts.map +1 -1
- package/dist/ui/full.js +8 -4
- package/dist/ui/full.js.map +1 -1
- package/dist/ui/operation/client.js +7 -8
- package/dist/ui/operation/client.js.map +1 -1
- package/dist/ui/operation/index.js +42 -19
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/request-tabs.d.ts.map +1 -1
- package/dist/ui/operation/request-tabs.js +9 -8
- package/dist/ui/operation/request-tabs.js.map +1 -1
- package/dist/ui/operation/response-tabs.d.ts +1 -1
- package/dist/ui/operation/response-tabs.d.ts.map +1 -1
- package/dist/ui/operation/response-tabs.js +13 -12
- package/dist/ui/operation/response-tabs.js.map +1 -1
- package/dist/ui/operation/usage-tabs/client.js +4 -5
- package/dist/ui/operation/usage-tabs/client.js.map +1 -1
- package/dist/ui/schema/client.d.ts.map +1 -1
- package/dist/ui/schema/client.js +32 -21
- package/dist/ui/schema/client.js.map +1 -1
- package/dist/ui/schema/index.d.ts +1 -1
- package/dist/ui/schema/index.d.ts.map +1 -1
- package/dist/ui/schema/index.js +11 -10
- package/dist/ui/schema/index.js.map +1 -1
- package/dist/utils/process-document.d.ts +1 -1
- package/dist/utils/process-document.js +19 -15
- package/dist/utils/process-document.js.map +1 -1
- package/package.json +19 -12
|
@@ -10,13 +10,14 @@ import { encodeRequestData } from "../requests/media/encode.js";
|
|
|
10
10
|
import { SchemaProvider, useResolvedSchema } from "./schema.js";
|
|
11
11
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/components/select.js";
|
|
12
12
|
import { labelVariants } from "../ui/components/input.js";
|
|
13
|
+
import { useTranslations } from "../ui/client/i18n.js";
|
|
13
14
|
import ServerSelect from "./components/server-select.js";
|
|
15
|
+
import { ClientCodeBlock } from "../ui/components/codeblock.js";
|
|
14
16
|
import { useExampleRequests } from "../ui/operation/usage-tabs/client.js";
|
|
15
17
|
import { FieldInput, FieldSet, JsonInput, ObjectInput } from "./components/inputs.js";
|
|
16
18
|
import { Fragment, lazy, useEffect, useMemo, useRef, useState } from "react";
|
|
17
19
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
18
20
|
import { ChevronDown, LoaderCircle } from "lucide-react";
|
|
19
|
-
import { DynamicCodeBlock } from "fumadocs-ui/components/dynamic-codeblock.core";
|
|
20
21
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "fumadocs-ui/components/ui/collapsible";
|
|
21
22
|
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
|
22
23
|
import { StfProvider, useDataEngine, useFieldValue, useListener, useStf } from "@fumari/stf";
|
|
@@ -25,6 +26,7 @@ import { objectGet, objectSet, stringifyFieldKey } from "@fumari/stf/lib/utils";
|
|
|
25
26
|
const OauthDialog = lazy(() => import("./components/oauth-dialog.js").then((mod) => ({ default: mod.OauthDialog })));
|
|
26
27
|
const OauthDialogTrigger = lazy(() => import("./components/oauth-dialog.js").then((mod) => ({ default: mod.OauthDialogTrigger })));
|
|
27
28
|
function PlaygroundClient({ route, method = "GET", securities, parameters = [], body, references, proxyUrl, writeOnly, readOnly, ...rest }) {
|
|
29
|
+
const t = useTranslations();
|
|
28
30
|
const { example: exampleId, examples, setExampleData } = useExampleRequests();
|
|
29
31
|
const storageKeys = useStorageKey();
|
|
30
32
|
const { mediaAdapters, client: { playground: { components: { ResultDisplay = DefaultResultDisplay } = {}, requestTimeout = 10, transformAuthInputs } = {} } } = useApiContext();
|
|
@@ -115,7 +117,7 @@ function PlaygroundClient({ route, method = "GET", securities, parameters = [],
|
|
|
115
117
|
size: "sm"
|
|
116
118
|
}), "w-14 py-1.5"),
|
|
117
119
|
disabled: testQuery.isLoading,
|
|
118
|
-
children: testQuery.isLoading ? /* @__PURE__ */ jsx(LoaderCircle, { className: "size-4 animate-spin" }) :
|
|
120
|
+
children: testQuery.isLoading ? /* @__PURE__ */ jsx(LoaderCircle, { className: "size-4 animate-spin" }) : t.send
|
|
119
121
|
})
|
|
120
122
|
]
|
|
121
123
|
}),
|
|
@@ -142,7 +144,7 @@ function SecurityTabs({ securities, setSecurityId, securityId, children }) {
|
|
|
142
144
|
const [open, setOpen] = useState(false);
|
|
143
145
|
const engine = useDataEngine();
|
|
144
146
|
const result = /* @__PURE__ */ jsxs(CollapsiblePanel, {
|
|
145
|
-
title:
|
|
147
|
+
title: useTranslations().authorization,
|
|
146
148
|
children: [/* @__PURE__ */ jsxs(Select, {
|
|
147
149
|
value: securityId.toString(),
|
|
148
150
|
onValueChange: (v) => setSecurityId(Number(v)),
|
|
@@ -185,16 +187,17 @@ const ParamTypes = [
|
|
|
185
187
|
];
|
|
186
188
|
function FormBody({ parameters = [], body }) {
|
|
187
189
|
const { renderParameterField, renderBodyField } = useApiContext().client.playground ?? {};
|
|
190
|
+
const t = useTranslations();
|
|
188
191
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [useMemo(() => {
|
|
189
192
|
return ParamTypes.map((type) => {
|
|
190
193
|
const items = parameters.filter((v) => v.in === type);
|
|
191
194
|
if (items.length === 0) return;
|
|
192
195
|
return /* @__PURE__ */ jsx(CollapsiblePanel, {
|
|
193
196
|
title: {
|
|
194
|
-
header:
|
|
195
|
-
cookie:
|
|
196
|
-
query:
|
|
197
|
-
path:
|
|
197
|
+
header: t.header,
|
|
198
|
+
cookie: t.cookies,
|
|
199
|
+
query: t.query,
|
|
200
|
+
path: t.path
|
|
198
201
|
}[type],
|
|
199
202
|
children: items.map((field) => {
|
|
200
203
|
const fieldName = [type, field.name];
|
|
@@ -210,14 +213,19 @@ function FormBody({ parameters = [], body }) {
|
|
|
210
213
|
})
|
|
211
214
|
}, type);
|
|
212
215
|
});
|
|
213
|
-
}, [
|
|
214
|
-
|
|
216
|
+
}, [
|
|
217
|
+
parameters,
|
|
218
|
+
renderParameterField,
|
|
219
|
+
t
|
|
220
|
+
]), body && /* @__PURE__ */ jsx(CollapsiblePanel, {
|
|
221
|
+
title: t.body,
|
|
215
222
|
children: renderBodyField ? renderBodyField("body", body) : /* @__PURE__ */ jsx(BodyInput, { field: body.schema })
|
|
216
223
|
})] });
|
|
217
224
|
}
|
|
218
225
|
function BodyInput({ field: _field }) {
|
|
219
226
|
const field = useResolvedSchema(_field);
|
|
220
227
|
const [isJson, setIsJson] = useState(false);
|
|
228
|
+
const t = useTranslations();
|
|
221
229
|
if (field.format === "binary") return /* @__PURE__ */ jsx(FieldSet, {
|
|
222
230
|
field,
|
|
223
231
|
fieldName: ["body"],
|
|
@@ -231,7 +239,7 @@ function BodyInput({ field: _field }) {
|
|
|
231
239
|
})),
|
|
232
240
|
onClick: () => setIsJson(false),
|
|
233
241
|
type: "button",
|
|
234
|
-
children:
|
|
242
|
+
children: t.closeJsonEditor
|
|
235
243
|
}), /* @__PURE__ */ jsx(JsonInput, { fieldName: ["body"] })] });
|
|
236
244
|
return /* @__PURE__ */ jsx(FieldSet, {
|
|
237
245
|
field,
|
|
@@ -246,12 +254,13 @@ function BodyInput({ field: _field }) {
|
|
|
246
254
|
className: "p-2"
|
|
247
255
|
})),
|
|
248
256
|
onClick: () => setIsJson(true),
|
|
249
|
-
children:
|
|
257
|
+
children: t.openJsonEditor
|
|
250
258
|
})
|
|
251
259
|
});
|
|
252
260
|
}
|
|
253
261
|
function useAuthInputs(securities, transform) {
|
|
254
262
|
const storageKeys = useStorageKey();
|
|
263
|
+
const t = useTranslations();
|
|
255
264
|
const inputs = useMemo(() => {
|
|
256
265
|
const result = [];
|
|
257
266
|
if (!securities) return result;
|
|
@@ -291,7 +300,7 @@ function useAuthInputs(securities, transform) {
|
|
|
291
300
|
children: [/* @__PURE__ */ jsx("label", {
|
|
292
301
|
htmlFor: stringifyFieldKey(fieldName),
|
|
293
302
|
className: cn(labelVariants()),
|
|
294
|
-
children:
|
|
303
|
+
children: t.accessToken
|
|
295
304
|
}), /* @__PURE__ */ jsxs("div", {
|
|
296
305
|
className: "flex gap-2",
|
|
297
306
|
children: [/* @__PURE__ */ jsx(FieldInput, {
|
|
@@ -305,7 +314,7 @@ function useAuthInputs(securities, transform) {
|
|
|
305
314
|
size: "sm",
|
|
306
315
|
color: "secondary"
|
|
307
316
|
})),
|
|
308
|
-
children:
|
|
317
|
+
children: t.authorize
|
|
309
318
|
})]
|
|
310
319
|
})]
|
|
311
320
|
})
|
|
@@ -317,7 +326,7 @@ function useAuthInputs(securities, transform) {
|
|
|
317
326
|
original: security,
|
|
318
327
|
defaultValue: "Bearer ",
|
|
319
328
|
children: /* @__PURE__ */ jsx(FieldSet, {
|
|
320
|
-
name:
|
|
329
|
+
name: `${t.authorization} (${t.header})`,
|
|
321
330
|
fieldName,
|
|
322
331
|
isRequired: true,
|
|
323
332
|
field: { type: "string" }
|
|
@@ -343,18 +352,22 @@ function useAuthInputs(securities, transform) {
|
|
|
343
352
|
defaultValue: "",
|
|
344
353
|
original: security,
|
|
345
354
|
children: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(FieldSet, {
|
|
346
|
-
name:
|
|
355
|
+
name: `${t.authorization} (${t.header})`,
|
|
347
356
|
isRequired: true,
|
|
348
357
|
fieldName,
|
|
349
358
|
field: { type: "string" }
|
|
350
359
|
}), /* @__PURE__ */ jsx("p", {
|
|
351
360
|
className: "text-fd-muted-foreground text-xs",
|
|
352
|
-
children:
|
|
361
|
+
children: t.openIdUnsupported
|
|
353
362
|
})] })
|
|
354
363
|
});
|
|
355
364
|
}
|
|
356
365
|
return transform ? transform(result) : result;
|
|
357
|
-
}, [
|
|
366
|
+
}, [
|
|
367
|
+
securities,
|
|
368
|
+
transform,
|
|
369
|
+
t
|
|
370
|
+
]);
|
|
358
371
|
const mapInputs = (values) => {
|
|
359
372
|
const cloned = structuredClone(values);
|
|
360
373
|
for (const item of inputs) {
|
|
@@ -403,8 +416,8 @@ function Route({ route, ...props }) {
|
|
|
403
416
|
});
|
|
404
417
|
}
|
|
405
418
|
function DefaultResultDisplay({ data, reset }) {
|
|
406
|
-
const
|
|
407
|
-
const
|
|
419
|
+
const t = useTranslations();
|
|
420
|
+
const statusInfo = useMemo(() => getStatusInfo(data.status, t), [data.status, t]);
|
|
408
421
|
return /* @__PURE__ */ jsxs("div", {
|
|
409
422
|
className: "flex flex-col gap-3 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground",
|
|
410
423
|
children: [
|
|
@@ -420,17 +433,16 @@ function DefaultResultDisplay({ data, reset }) {
|
|
|
420
433
|
variant: "outline"
|
|
421
434
|
})),
|
|
422
435
|
onClick: () => reset(),
|
|
423
|
-
children:
|
|
436
|
+
children: t.close
|
|
424
437
|
})]
|
|
425
438
|
}),
|
|
426
439
|
/* @__PURE__ */ jsx("p", {
|
|
427
440
|
className: "text-sm text-fd-muted-foreground",
|
|
428
441
|
children: data.status
|
|
429
442
|
}),
|
|
430
|
-
data.data !== void 0 && /* @__PURE__ */ jsx(
|
|
443
|
+
data.data !== void 0 && /* @__PURE__ */ jsx(ClientCodeBlock, {
|
|
431
444
|
lang: typeof data.data === "string" && data.data.length > 5e4 ? "text" : data.type,
|
|
432
|
-
code: typeof data.data === "string" ? data.data : JSON.stringify(data.data, null, 2)
|
|
433
|
-
options: shikiOptions
|
|
445
|
+
code: typeof data.data === "string" ? data.data : JSON.stringify(data.data, null, 2)
|
|
434
446
|
})
|
|
435
447
|
]
|
|
436
448
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../../src/playground/client.tsx"],"sourcesContent":["'use client';\nimport {\n type FC,\n Fragment,\n lazy,\n type ReactNode,\n useEffect,\n useMemo,\n useState,\n type ComponentProps,\n useRef,\n} from 'react';\nimport { useApiContext, useServerContext } from '@/ui/contexts/api';\nimport type { FetchResult } from '@/playground/fetcher';\nimport type { SecurityEntry } from '@/playground/index';\nimport { getStatusInfo } from './status-info';\nimport { joinURL, resolveRequestData, resolveServerUrl, withBase } from '@/utils/url';\nimport { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';\nimport { MethodLabel } from '@/ui/components/method-label';\nimport { useQuery } from '@/utils/use-query';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from 'fumadocs-ui/components/ui/collapsible';\nimport { ChevronDown, LoaderCircle } from 'lucide-react';\nimport { encodeRequestData } from '@/requests/media/encode';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { cn } from '@/utils/cn';\nimport { SchemaProvider, SchemaScope, useResolvedSchema } from '@/playground/schema';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { labelVariants } from '@/ui/components/input';\nimport type { ParsedSchema } from '@/utils/schema';\nimport ServerSelect from './components/server-select';\nimport { useStorageKey } from '@/ui/client/storage-key';\nimport { useExampleRequests } from '@/ui/operation/usage-tabs/client';\nimport {\n FieldKey,\n Stf,\n StfProvider,\n useDataEngine,\n useFieldValue,\n useListener,\n useStf,\n} from '@fumari/stf';\nimport { objectGet, objectSet, stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { FieldInput, FieldSet, JsonInput, ObjectInput } from './components/inputs';\nimport type { ParameterObject } from '@/types';\n\nexport interface FormValues extends Record<string, unknown> {\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n header: Record<string, unknown>;\n cookie: Record<string, unknown>;\n body: unknown;\n}\n\nexport interface PlaygroundClientProps extends ComponentProps<'form'>, SchemaScope {\n route: string;\n method: string;\n parameters?: ParameterObject[];\n securities: SecurityEntry[][];\n body?: {\n schema: ParsedSchema;\n mediaType: string;\n };\n /**\n * Resolver for $ref schemas you've passed\n */\n references: Record<string, ParsedSchema>;\n proxyUrl?: string;\n}\n\nexport interface PlaygroundClientOptions {\n /**\n * transform fields for auth-specific parameters (e.g. header)\n */\n transformAuthInputs?: (fields: AuthField[]) => AuthField[];\n\n /**\n * Request timeout in seconds (default: 10s)\n */\n requestTimeout?: number;\n\n components?: Partial<{\n ResultDisplay: FC<{ data: FetchResult }>;\n }>;\n\n /**\n * render the paremeter inputs of API endpoint.\n *\n * for updating values, use:\n * - the `Custom.useController()` from `fumadocs-openapi/playground/client`.\n *\n * Recommended types packages: `json-schema-typed`, `openapi-types`.\n */\n renderParameterField?: (fieldName: FieldKey, param: ParameterObject) => ReactNode;\n\n /**\n * render the input for API endpoint body.\n *\n * @see renderParameterField for customisation tips\n */\n renderBodyField?: (\n fieldName: 'body',\n info: {\n schema: ParsedSchema;\n mediaType: string;\n },\n ) => ReactNode;\n}\n\nconst OauthDialog = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialog,\n })),\n);\nconst OauthDialogTrigger = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialogTrigger,\n })),\n);\n\nexport default function PlaygroundClient({\n route,\n method = 'GET',\n securities,\n parameters = [],\n body,\n references,\n proxyUrl,\n writeOnly,\n readOnly,\n ...rest\n}: PlaygroundClientProps) {\n const { example: exampleId, examples, setExampleData } = useExampleRequests();\n const storageKeys = useStorageKey();\n const {\n mediaAdapters,\n client: {\n playground: {\n components: { ResultDisplay = DefaultResultDisplay } = {},\n requestTimeout = 10,\n transformAuthInputs,\n } = {},\n },\n } = useApiContext();\n const { serverRef } = useServerContext();\n const [securityId, setSecurityId] = useState(() => {\n const idx = securities.findIndex((s) => s.every((entry) => !entry.deprecated));\n return idx === -1 ? 0 : idx;\n });\n const { inputs, mapInputs, initAuthValues } = useAuthInputs(\n securities[securityId],\n transformAuthInputs,\n );\n\n const defaultValues: FormValues = useMemo(() => {\n const requestData = examples.find((example) => example.id === exampleId)?.data;\n\n return {\n path: requestData?.path ?? {},\n query: requestData?.query ?? {},\n header: requestData?.header ?? {},\n body: requestData?.body ?? {},\n cookie: requestData?.cookie ?? {},\n };\n }, [examples, exampleId]);\n\n const stf = useStf({\n // it is fine to modify `defaultValues` in place\n // because we already try to persist the form values via `setExampleData`.\n defaultValues,\n });\n\n const testQuery = useQuery(async (input: FormValues) => {\n const targetServer = serverRef.current;\n const fetcher = await import('./fetcher').then((mod) =>\n mod.createBrowserFetcher(mediaAdapters, requestTimeout),\n );\n const encoded = encodeRequestData(\n { ...mapInputs(input), method, bodyMediaType: body?.mediaType },\n mediaAdapters,\n parameters,\n );\n return fetcher.fetch(\n joinURL(\n withBase(\n targetServer ? resolveServerUrl(targetServer.url, targetServer.variables) : '/',\n window.location.origin,\n ),\n resolveRequestData(route, encoded),\n ),\n {\n proxyUrl,\n ...encoded,\n },\n );\n });\n\n const timerRef = useRef<number | null>(null);\n useListener({\n stf,\n onUpdate() {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n timerRef.current = window.setTimeout(\n () => {\n const values = stf.dataEngine.getData() as FormValues;\n for (const item of inputs) {\n const value = stf.dataEngine.get(item.fieldName);\n\n if (value) {\n localStorage.setItem(storageKeys.AuthField(item), JSON.stringify(value));\n }\n }\n\n const data = {\n ...mapInputs(values),\n method,\n bodyMediaType: body?.mediaType,\n };\n setExampleData(data, encodeRequestData(data, mediaAdapters, parameters));\n },\n timerRef.current ? 400 : 0,\n );\n },\n });\n\n useEffect(() => {\n // same object reference = unchanged\n if (stf.dataEngine.getData() === defaultValues) return;\n\n stf.dataEngine.reset(defaultValues);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues]);\n\n useEffect(() => {\n return initAuthValues(stf);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues, inputs]);\n\n return (\n <StfProvider value={stf}>\n <SchemaProvider references={references} writeOnly={writeOnly} readOnly={readOnly}>\n <form\n {...rest}\n className={cn(\n 'not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground',\n rest.className,\n )}\n onSubmit={(e) => {\n testQuery.start(mapInputs(stf.dataEngine.getData() as FormValues));\n e.preventDefault();\n }}\n >\n <ServerSelect className=\"border-b\" />\n <div className=\"flex flex-row items-center gap-2 text-sm p-3 not-last:pb-0\">\n <MethodLabel>{method}</MethodLabel>\n <Route route={route} className=\"flex-1\" />\n <button\n type=\"submit\"\n className={cn(buttonVariants({ color: 'primary', size: 'sm' }), 'w-14 py-1.5')}\n disabled={testQuery.isLoading}\n >\n {testQuery.isLoading ? <LoaderCircle className=\"size-4 animate-spin\" /> : 'Send'}\n </button>\n </div>\n {testQuery.data ? <ResultDisplay data={testQuery.data} reset={testQuery.reset} /> : null}\n\n {securities.length > 0 && (\n <SecurityTabs\n securities={securities}\n securityId={securityId}\n setSecurityId={setSecurityId}\n >\n {inputs.map((input) => (\n <Fragment key={stringifyFieldKey(input.fieldName)}>{input.children}</Fragment>\n ))}\n </SecurityTabs>\n )}\n <FormBody body={body} parameters={parameters} />\n </form>\n </SchemaProvider>\n </StfProvider>\n );\n}\n\nfunction SecurityTabs({\n securities,\n setSecurityId,\n securityId,\n children,\n}: {\n securities: SecurityEntry[][];\n securityId: number;\n setSecurityId: (value: number) => void;\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n const engine = useDataEngine();\n\n const result = (\n <CollapsiblePanel title=\"Authorization\">\n <Select value={securityId.toString()} onValueChange={(v) => setSecurityId(Number(v))}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {securities.map((security, i) => (\n <SelectItem key={i} value={i.toString()}>\n {security.map((item) => (\n <div key={item.id} className=\"max-w-[600px]\">\n <p\n className={cn(\n 'font-mono font-medium',\n item.deprecated && 'text-fd-muted-foreground line-through',\n )}\n >\n {item.id}\n </p>\n <p className=\"text-fd-muted-foreground whitespace-pre-wrap\">{item.description}</p>\n </div>\n ))}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {children}\n </CollapsiblePanel>\n );\n\n for (let i = 0; i < securities.length; i++) {\n const security = securities[i];\n\n for (const item of security) {\n if (item.type === 'oauth2') {\n return (\n <OauthDialog\n scheme={item}\n scopes={item.scopes}\n open={open}\n setOpen={(v) => {\n setOpen(v);\n if (v) {\n setSecurityId(i);\n }\n }}\n setToken={(token) => engine.update(['header', 'Authorization'], token)}\n >\n {result}\n </OauthDialog>\n );\n }\n }\n }\n\n return result;\n}\n\nconst ParamTypes = ['path', 'header', 'cookie', 'query'] as const;\n\nfunction FormBody({ parameters = [], body }: Pick<PlaygroundClientProps, 'parameters' | 'body'>) {\n const { renderParameterField, renderBodyField } = useApiContext().client.playground ?? {};\n const panels = useMemo(() => {\n return ParamTypes.map((type) => {\n const items = parameters.filter((v) => v.in === type);\n if (items.length === 0) return;\n\n return (\n <CollapsiblePanel\n key={type}\n title={\n {\n header: 'Header',\n cookie: 'Cookies',\n query: 'Query',\n path: 'Path',\n }[type]\n }\n >\n {items.map((field) => {\n const fieldName: FieldKey = [type, field.name!];\n if (renderParameterField) {\n return renderParameterField(fieldName, field);\n }\n\n const contentTypes = field.content && Object.keys(field.content);\n const schema = (\n field.content && contentTypes && contentTypes.length > 0\n ? field.content[contentTypes[0]].schema\n : field.schema\n ) as ParsedSchema;\n\n return (\n <FieldSet\n key={stringifyFieldKey(fieldName)}\n name={field.name}\n fieldName={fieldName}\n field={schema}\n isRequired={field.required}\n />\n );\n })}\n </CollapsiblePanel>\n );\n });\n }, [parameters, renderParameterField]);\n\n return (\n <>\n {panels}\n {body && (\n <CollapsiblePanel title=\"Body\">\n {renderBodyField ? renderBodyField('body', body) : <BodyInput field={body.schema} />}\n </CollapsiblePanel>\n )}\n </>\n );\n}\n\nfunction BodyInput({ field: _field }: { field: ParsedSchema }) {\n const field = useResolvedSchema(_field);\n const [isJson, setIsJson] = useState(false);\n\n if (field.format === 'binary') return <FieldSet field={field} fieldName={['body']} isRequired />;\n\n if (isJson)\n return (\n <>\n <button\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'w-fit font-mono p-2',\n }),\n )}\n onClick={() => setIsJson(false)}\n type=\"button\"\n >\n Close JSON Editor\n </button>\n <JsonInput fieldName={['body']} />\n </>\n );\n\n return (\n <FieldSet\n field={field}\n fieldName={['body']}\n collapsible={false}\n isRequired\n name={\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'p-2',\n }),\n )}\n onClick={() => setIsJson(true)}\n >\n Open JSON Editor\n </button>\n }\n />\n );\n}\n\nexport interface AuthField {\n fieldName: FieldKey;\n defaultValue: unknown;\n\n original?: SecurityEntry;\n children: ReactNode;\n\n mapOutput?: (values: unknown) => unknown;\n}\n\nfunction useAuthInputs(\n securities?: SecurityEntry[],\n transform?: (fields: AuthField[]) => AuthField[],\n) {\n const storageKeys = useStorageKey();\n const inputs = useMemo(() => {\n const result: AuthField[] = [];\n if (!securities) return result;\n\n for (const security of securities) {\n if (security.type === 'http' && security.scheme === 'basic') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: {\n username: '',\n password: '',\n },\n mapOutput(out) {\n if (out && typeof out === 'object') {\n return `Basic ${btoa(`${'username' in out ? out.username : ''}:${'password' in out ? out.password : ''}`)}`;\n }\n\n return out;\n },\n children: (\n <ObjectInput\n field={{\n type: 'object',\n properties: {\n username: {\n type: 'string',\n },\n password: {\n type: 'string',\n },\n },\n required: ['username', 'password'],\n }}\n fieldName={fieldName}\n />\n ),\n });\n } else if (security.type === 'oauth2') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <fieldset className=\"flex flex-col gap-2\">\n <label htmlFor={stringifyFieldKey(fieldName)} className={cn(labelVariants())}>\n Access Token\n </label>\n <div className=\"flex gap-2\">\n <FieldInput\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n className=\"flex-1\"\n />\n\n <OauthDialogTrigger\n type=\"button\"\n className={cn(\n buttonVariants({\n size: 'sm',\n color: 'secondary',\n }),\n )}\n >\n Authorize\n </OauthDialogTrigger>\n </div>\n </fieldset>\n ),\n });\n } else if (security.type === 'http') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <FieldSet\n name=\"Authorization (header)\"\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else if (security.type === 'apiKey') {\n const fieldName: FieldKey = [security.in!, security.name!];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <FieldSet\n fieldName={fieldName}\n name={`${security.name} (${security.in})`}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <>\n <FieldSet\n name=\"Authorization (header)\"\n isRequired\n fieldName={fieldName}\n field={{\n type: 'string',\n }}\n />\n <p className=\"text-fd-muted-foreground text-xs\">\n OpenID Connect is not supported at the moment, you can still set an access token\n here.\n </p>\n </>\n ),\n });\n }\n }\n\n return transform ? transform(result) : result;\n }, [securities, transform]);\n\n const mapInputs = (values: FormValues) => {\n const cloned = structuredClone(values);\n\n for (const item of inputs) {\n if (!item.mapOutput) continue;\n objectSet(cloned, item.fieldName, item.mapOutput(objectGet(cloned, item.fieldName)));\n }\n\n return cloned;\n };\n\n const initAuthValues = (stf: Stf) => {\n const { dataEngine } = stf;\n for (const item of inputs) {\n const stored = localStorage.getItem(storageKeys.AuthField(item));\n\n if (stored) {\n const parsed = JSON.parse(stored);\n if (typeof parsed === typeof item.defaultValue) {\n dataEngine.init(item.fieldName, parsed);\n continue;\n }\n }\n\n dataEngine.init(item.fieldName, item.defaultValue);\n }\n\n // reset\n return () => {\n for (const item of inputs) {\n stf.dataEngine.delete(item.fieldName);\n }\n };\n };\n\n return { inputs, mapInputs, initAuthValues };\n}\n\nfunction Route({ route, ...props }: ComponentProps<'div'> & { route: string }) {\n return (\n <div\n {...props}\n className={cn(\n 'flex flex-row items-center gap-0.5 overflow-auto text-nowrap',\n props.className,\n )}\n >\n {route.split('/').map((part, index) => (\n <Fragment key={index}>\n {index > 0 && <span className=\"text-fd-muted-foreground\">/</span>}\n {part.startsWith('{') && part.endsWith('}') ? (\n <code className=\"bg-fd-primary/10 text-fd-primary\">{part}</code>\n ) : (\n <code className=\"text-fd-foreground\">{part}</code>\n )}\n </Fragment>\n ))}\n </div>\n );\n}\n\nfunction DefaultResultDisplay({ data, reset }: { data: FetchResult; reset: () => void }) {\n const statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);\n const { shikiOptions } = useApiContext();\n\n return (\n <div className=\"flex flex-col gap-3 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground\">\n <div className=\"flex justify-between items-center\">\n <div className=\"inline-flex items-center gap-1.5 text-sm font-medium\">\n <statusInfo.icon className={cn('size-4', statusInfo.color)} />\n {statusInfo.description}\n </div>\n <button\n type=\"button\"\n className={cn(buttonVariants({ size: 'sm', variant: 'outline' }))}\n onClick={() => reset()}\n >\n Close\n </button>\n </div>\n <p className=\"text-sm text-fd-muted-foreground\">{data.status}</p>\n {data.data !== undefined && (\n <DynamicCodeBlock\n lang={typeof data.data === 'string' && data.data.length > 50000 ? 'text' : data.type}\n code={typeof data.data === 'string' ? data.data : JSON.stringify(data.data, null, 2)}\n options={shikiOptions}\n />\n )}\n </div>\n );\n}\n\nfunction CollapsiblePanel({\n title,\n children,\n ...props\n}: Omit<ComponentProps<'div'>, 'title'> & {\n title: ReactNode;\n}) {\n return (\n <Collapsible {...props} className=\"border-b last:border-b-0\">\n <CollapsibleTrigger className=\"group w-full flex items-center gap-2 p-3 text-sm font-medium\">\n {title}\n <ChevronDown className=\"ms-auto size-3.5 text-fd-muted-foreground group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"flex flex-col gap-3 p-3 pt-1\">{children}</div>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n\nexport const Custom = {\n useController(\n fieldName: FieldKey,\n options?: {\n defaultValue?: unknown;\n },\n ) {\n const [value, setValue] = useFieldValue(fieldName, options);\n return {\n value,\n setValue,\n };\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../../src/playground/client.tsx"],"sourcesContent":["'use client';\nimport {\n type FC,\n Fragment,\n lazy,\n type ReactNode,\n useEffect,\n useMemo,\n useState,\n type ComponentProps,\n useRef,\n} from 'react';\nimport { useApiContext, useServerContext } from '@/ui/contexts/api';\nimport type { FetchResult } from '@/playground/fetcher';\nimport type { SecurityEntry } from '@/playground/index';\nimport { getStatusInfo } from './status-info';\nimport { joinURL, resolveRequestData, resolveServerUrl, withBase } from '@/utils/url';\nimport { MethodLabel } from '@/ui/components/method-label';\nimport { useQuery } from '@/utils/use-query';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from 'fumadocs-ui/components/ui/collapsible';\nimport { ChevronDown, LoaderCircle } from 'lucide-react';\nimport { encodeRequestData } from '@/requests/media/encode';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { cn } from '@/utils/cn';\nimport { SchemaProvider, SchemaScope, useResolvedSchema } from '@/playground/schema';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { labelVariants } from '@/ui/components/input';\nimport type { ParsedSchema } from '@/utils/schema';\nimport ServerSelect from './components/server-select';\nimport { useStorageKey } from '@/ui/client/storage-key';\nimport { useExampleRequests } from '@/ui/operation/usage-tabs/client';\nimport {\n FieldKey,\n Stf,\n StfProvider,\n useDataEngine,\n useFieldValue,\n useListener,\n useStf,\n} from '@fumari/stf';\nimport { objectGet, objectSet, stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { FieldInput, FieldSet, JsonInput, ObjectInput } from './components/inputs';\nimport type { ParameterObject } from '@/types';\nimport { ClientCodeBlock } from '@/ui/components/codeblock';\nimport { useTranslations } from '@/ui/client/i18n';\n\nexport interface FormValues extends Record<string, unknown> {\n path: Record<string, unknown>;\n query: Record<string, unknown>;\n header: Record<string, unknown>;\n cookie: Record<string, unknown>;\n body: unknown;\n}\n\nexport interface PlaygroundClientProps extends ComponentProps<'form'>, SchemaScope {\n route: string;\n method: string;\n parameters?: ParameterObject[];\n securities: SecurityEntry[][];\n body?: {\n schema: ParsedSchema;\n mediaType: string;\n };\n /**\n * Resolver for $ref schemas you've passed\n */\n references: Record<string, ParsedSchema>;\n proxyUrl?: string;\n}\n\nexport interface PlaygroundClientOptions {\n /**\n * transform fields for auth-specific parameters (e.g. header)\n */\n transformAuthInputs?: (fields: AuthField[]) => AuthField[];\n\n /**\n * Request timeout in seconds (default: 10s)\n */\n requestTimeout?: number;\n\n components?: Partial<{\n ResultDisplay: FC<{ data: FetchResult }>;\n }>;\n\n /**\n * render the paremeter inputs of API endpoint.\n *\n * for updating values, use:\n * - the `Custom.useController()` from `fumadocs-openapi/playground/client`.\n *\n * Recommended types packages: `json-schema-typed`, `openapi-types`.\n */\n renderParameterField?: (fieldName: FieldKey, param: ParameterObject) => ReactNode;\n\n /**\n * render the input for API endpoint body.\n *\n * @see renderParameterField for customisation tips\n */\n renderBodyField?: (\n fieldName: 'body',\n info: {\n schema: ParsedSchema;\n mediaType: string;\n },\n ) => ReactNode;\n}\n\nconst OauthDialog = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialog,\n })),\n);\nconst OauthDialogTrigger = lazy(() =>\n import('./components/oauth-dialog').then((mod) => ({\n default: mod.OauthDialogTrigger,\n })),\n);\n\nexport default function PlaygroundClient({\n route,\n method = 'GET',\n securities,\n parameters = [],\n body,\n references,\n proxyUrl,\n writeOnly,\n readOnly,\n ...rest\n}: PlaygroundClientProps) {\n const t = useTranslations();\n const { example: exampleId, examples, setExampleData } = useExampleRequests();\n const storageKeys = useStorageKey();\n const {\n mediaAdapters,\n client: {\n playground: {\n components: { ResultDisplay = DefaultResultDisplay } = {},\n requestTimeout = 10,\n transformAuthInputs,\n } = {},\n },\n } = useApiContext();\n const { serverRef } = useServerContext();\n const [securityId, setSecurityId] = useState(() => {\n const idx = securities.findIndex((s) => s.every((entry) => !entry.deprecated));\n return idx === -1 ? 0 : idx;\n });\n const { inputs, mapInputs, initAuthValues } = useAuthInputs(\n securities[securityId],\n transformAuthInputs,\n );\n\n const defaultValues: FormValues = useMemo(() => {\n const requestData = examples.find((example) => example.id === exampleId)?.data;\n\n return {\n path: requestData?.path ?? {},\n query: requestData?.query ?? {},\n header: requestData?.header ?? {},\n body: requestData?.body ?? {},\n cookie: requestData?.cookie ?? {},\n };\n }, [examples, exampleId]);\n\n const stf = useStf({\n // it is fine to modify `defaultValues` in place\n // because we already try to persist the form values via `setExampleData`.\n defaultValues,\n });\n\n const testQuery = useQuery(async (input: FormValues) => {\n const targetServer = serverRef.current;\n const fetcher = await import('./fetcher').then((mod) =>\n mod.createBrowserFetcher(mediaAdapters, requestTimeout),\n );\n const encoded = encodeRequestData(\n { ...mapInputs(input), method, bodyMediaType: body?.mediaType },\n mediaAdapters,\n parameters,\n );\n return fetcher.fetch(\n joinURL(\n withBase(\n targetServer ? resolveServerUrl(targetServer.url, targetServer.variables) : '/',\n window.location.origin,\n ),\n resolveRequestData(route, encoded),\n ),\n {\n proxyUrl,\n ...encoded,\n },\n );\n });\n\n const timerRef = useRef<number | null>(null);\n useListener({\n stf,\n onUpdate() {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n timerRef.current = window.setTimeout(\n () => {\n const values = stf.dataEngine.getData() as FormValues;\n for (const item of inputs) {\n const value = stf.dataEngine.get(item.fieldName);\n\n if (value) {\n localStorage.setItem(storageKeys.AuthField(item), JSON.stringify(value));\n }\n }\n\n const data = {\n ...mapInputs(values),\n method,\n bodyMediaType: body?.mediaType,\n };\n setExampleData(data, encodeRequestData(data, mediaAdapters, parameters));\n },\n timerRef.current ? 400 : 0,\n );\n },\n });\n\n useEffect(() => {\n // same object reference = unchanged\n if (stf.dataEngine.getData() === defaultValues) return;\n\n stf.dataEngine.reset(defaultValues);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues]);\n\n useEffect(() => {\n return initAuthValues(stf);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- ignore other parts\n }, [defaultValues, inputs]);\n\n return (\n <StfProvider value={stf}>\n <SchemaProvider references={references} writeOnly={writeOnly} readOnly={readOnly}>\n <form\n {...rest}\n className={cn(\n 'not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground',\n rest.className,\n )}\n onSubmit={(e) => {\n testQuery.start(mapInputs(stf.dataEngine.getData() as FormValues));\n e.preventDefault();\n }}\n >\n <ServerSelect className=\"border-b\" />\n <div className=\"flex flex-row items-center gap-2 text-sm p-3 not-last:pb-0\">\n <MethodLabel>{method}</MethodLabel>\n <Route route={route} className=\"flex-1\" />\n <button\n type=\"submit\"\n className={cn(buttonVariants({ color: 'primary', size: 'sm' }), 'w-14 py-1.5')}\n disabled={testQuery.isLoading}\n >\n {testQuery.isLoading ? <LoaderCircle className=\"size-4 animate-spin\" /> : t.send}\n </button>\n </div>\n {testQuery.data ? <ResultDisplay data={testQuery.data} reset={testQuery.reset} /> : null}\n\n {securities.length > 0 && (\n <SecurityTabs\n securities={securities}\n securityId={securityId}\n setSecurityId={setSecurityId}\n >\n {inputs.map((input) => (\n <Fragment key={stringifyFieldKey(input.fieldName)}>{input.children}</Fragment>\n ))}\n </SecurityTabs>\n )}\n <FormBody body={body} parameters={parameters} />\n </form>\n </SchemaProvider>\n </StfProvider>\n );\n}\n\nfunction SecurityTabs({\n securities,\n setSecurityId,\n securityId,\n children,\n}: {\n securities: SecurityEntry[][];\n securityId: number;\n setSecurityId: (value: number) => void;\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n const engine = useDataEngine();\n const t = useTranslations();\n\n const result = (\n <CollapsiblePanel title={t.authorization}>\n <Select value={securityId.toString()} onValueChange={(v) => setSecurityId(Number(v))}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {securities.map((security, i) => (\n <SelectItem key={i} value={i.toString()}>\n {security.map((item) => (\n <div key={item.id} className=\"max-w-[600px]\">\n <p\n className={cn(\n 'font-mono font-medium',\n item.deprecated && 'text-fd-muted-foreground line-through',\n )}\n >\n {item.id}\n </p>\n <p className=\"text-fd-muted-foreground whitespace-pre-wrap\">{item.description}</p>\n </div>\n ))}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {children}\n </CollapsiblePanel>\n );\n\n for (let i = 0; i < securities.length; i++) {\n const security = securities[i];\n\n for (const item of security) {\n if (item.type === 'oauth2') {\n return (\n <OauthDialog\n scheme={item}\n scopes={item.scopes}\n open={open}\n setOpen={(v) => {\n setOpen(v);\n if (v) {\n setSecurityId(i);\n }\n }}\n setToken={(token) => engine.update(['header', 'Authorization'], token)}\n >\n {result}\n </OauthDialog>\n );\n }\n }\n }\n\n return result;\n}\n\nconst ParamTypes = ['path', 'header', 'cookie', 'query'] as const;\n\nfunction FormBody({ parameters = [], body }: Pick<PlaygroundClientProps, 'parameters' | 'body'>) {\n const { renderParameterField, renderBodyField } = useApiContext().client.playground ?? {};\n const t = useTranslations();\n const panels = useMemo(() => {\n return ParamTypes.map((type) => {\n const items = parameters.filter((v) => v.in === type);\n if (items.length === 0) return;\n\n return (\n <CollapsiblePanel\n key={type}\n title={\n {\n header: t.header,\n cookie: t.cookies,\n query: t.query,\n path: t.path,\n }[type]\n }\n >\n {items.map((field) => {\n const fieldName: FieldKey = [type, field.name!];\n if (renderParameterField) {\n return renderParameterField(fieldName, field);\n }\n\n const contentTypes = field.content && Object.keys(field.content);\n const schema = (\n field.content && contentTypes && contentTypes.length > 0\n ? field.content[contentTypes[0]].schema\n : field.schema\n ) as ParsedSchema;\n\n return (\n <FieldSet\n key={stringifyFieldKey(fieldName)}\n name={field.name}\n fieldName={fieldName}\n field={schema}\n isRequired={field.required}\n />\n );\n })}\n </CollapsiblePanel>\n );\n });\n }, [parameters, renderParameterField, t]);\n\n return (\n <>\n {panels}\n {body && (\n <CollapsiblePanel title={t.body}>\n {renderBodyField ? renderBodyField('body', body) : <BodyInput field={body.schema} />}\n </CollapsiblePanel>\n )}\n </>\n );\n}\n\nfunction BodyInput({ field: _field }: { field: ParsedSchema }) {\n const field = useResolvedSchema(_field);\n const [isJson, setIsJson] = useState(false);\n const t = useTranslations();\n\n if (field.format === 'binary') return <FieldSet field={field} fieldName={['body']} isRequired />;\n\n if (isJson)\n return (\n <>\n <button\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'w-fit font-mono p-2',\n }),\n )}\n onClick={() => setIsJson(false)}\n type=\"button\"\n >\n {t.closeJsonEditor}\n </button>\n <JsonInput fieldName={['body']} />\n </>\n );\n\n return (\n <FieldSet\n field={field}\n fieldName={['body']}\n collapsible={false}\n isRequired\n name={\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n size: 'sm',\n className: 'p-2',\n }),\n )}\n onClick={() => setIsJson(true)}\n >\n {t.openJsonEditor}\n </button>\n }\n />\n );\n}\n\nexport interface AuthField {\n fieldName: FieldKey;\n defaultValue: unknown;\n\n original?: SecurityEntry;\n children: ReactNode;\n\n mapOutput?: (values: unknown) => unknown;\n}\n\nfunction useAuthInputs(\n securities?: SecurityEntry[],\n transform?: (fields: AuthField[]) => AuthField[],\n) {\n const storageKeys = useStorageKey();\n const t = useTranslations();\n const inputs = useMemo(() => {\n const result: AuthField[] = [];\n if (!securities) return result;\n\n for (const security of securities) {\n if (security.type === 'http' && security.scheme === 'basic') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: {\n username: '',\n password: '',\n },\n mapOutput(out) {\n if (out && typeof out === 'object') {\n return `Basic ${btoa(`${'username' in out ? out.username : ''}:${'password' in out ? out.password : ''}`)}`;\n }\n\n return out;\n },\n children: (\n <ObjectInput\n field={{\n type: 'object',\n properties: {\n username: {\n type: 'string',\n },\n password: {\n type: 'string',\n },\n },\n required: ['username', 'password'],\n }}\n fieldName={fieldName}\n />\n ),\n });\n } else if (security.type === 'oauth2') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <fieldset className=\"flex flex-col gap-2\">\n <label htmlFor={stringifyFieldKey(fieldName)} className={cn(labelVariants())}>\n {t.accessToken}\n </label>\n <div className=\"flex gap-2\">\n <FieldInput\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n className=\"flex-1\"\n />\n\n <OauthDialogTrigger\n type=\"button\"\n className={cn(\n buttonVariants({\n size: 'sm',\n color: 'secondary',\n }),\n )}\n >\n {t.authorize}\n </OauthDialogTrigger>\n </div>\n </fieldset>\n ),\n });\n } else if (security.type === 'http') {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n original: security,\n defaultValue: 'Bearer ',\n children: (\n <FieldSet\n name={`${t.authorization} (${t.header})`}\n fieldName={fieldName}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else if (security.type === 'apiKey') {\n const fieldName: FieldKey = [security.in!, security.name!];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <FieldSet\n fieldName={fieldName}\n name={`${security.name} (${security.in})`}\n isRequired\n field={{\n type: 'string',\n }}\n />\n ),\n });\n } else {\n const fieldName: FieldKey = ['header', 'Authorization'];\n\n result.push({\n fieldName,\n defaultValue: '',\n original: security,\n children: (\n <>\n <FieldSet\n name={`${t.authorization} (${t.header})`}\n isRequired\n fieldName={fieldName}\n field={{\n type: 'string',\n }}\n />\n <p className=\"text-fd-muted-foreground text-xs\">{t.openIdUnsupported}</p>\n </>\n ),\n });\n }\n }\n\n return transform ? transform(result) : result;\n }, [securities, transform, t]);\n\n const mapInputs = (values: FormValues) => {\n const cloned = structuredClone(values);\n\n for (const item of inputs) {\n if (!item.mapOutput) continue;\n objectSet(cloned, item.fieldName, item.mapOutput(objectGet(cloned, item.fieldName)));\n }\n\n return cloned;\n };\n\n const initAuthValues = (stf: Stf) => {\n const { dataEngine } = stf;\n for (const item of inputs) {\n const stored = localStorage.getItem(storageKeys.AuthField(item));\n\n if (stored) {\n const parsed = JSON.parse(stored);\n if (typeof parsed === typeof item.defaultValue) {\n dataEngine.init(item.fieldName, parsed);\n continue;\n }\n }\n\n dataEngine.init(item.fieldName, item.defaultValue);\n }\n\n // reset\n return () => {\n for (const item of inputs) {\n stf.dataEngine.delete(item.fieldName);\n }\n };\n };\n\n return { inputs, mapInputs, initAuthValues };\n}\n\nfunction Route({ route, ...props }: ComponentProps<'div'> & { route: string }) {\n return (\n <div\n {...props}\n className={cn(\n 'flex flex-row items-center gap-0.5 overflow-auto text-nowrap',\n props.className,\n )}\n >\n {route.split('/').map((part, index) => (\n <Fragment key={index}>\n {index > 0 && <span className=\"text-fd-muted-foreground\">/</span>}\n {part.startsWith('{') && part.endsWith('}') ? (\n <code className=\"bg-fd-primary/10 text-fd-primary\">{part}</code>\n ) : (\n <code className=\"text-fd-foreground\">{part}</code>\n )}\n </Fragment>\n ))}\n </div>\n );\n}\n\nfunction DefaultResultDisplay({ data, reset }: { data: FetchResult; reset: () => void }) {\n const t = useTranslations();\n const statusInfo = useMemo(() => getStatusInfo(data.status, t), [data.status, t]);\n\n return (\n <div className=\"flex flex-col gap-3 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground\">\n <div className=\"flex justify-between items-center\">\n <div className=\"inline-flex items-center gap-1.5 text-sm font-medium\">\n <statusInfo.icon className={cn('size-4', statusInfo.color)} />\n {statusInfo.description}\n </div>\n <button\n type=\"button\"\n className={cn(buttonVariants({ size: 'sm', variant: 'outline' }))}\n onClick={() => reset()}\n >\n {t.close}\n </button>\n </div>\n <p className=\"text-sm text-fd-muted-foreground\">{data.status}</p>\n {data.data !== undefined && (\n <ClientCodeBlock\n lang={typeof data.data === 'string' && data.data.length > 50000 ? 'text' : data.type}\n code={typeof data.data === 'string' ? data.data : JSON.stringify(data.data, null, 2)}\n />\n )}\n </div>\n );\n}\n\nfunction CollapsiblePanel({\n title,\n children,\n ...props\n}: Omit<ComponentProps<'div'>, 'title'> & {\n title: ReactNode;\n}) {\n return (\n <Collapsible {...props} className=\"border-b last:border-b-0\">\n <CollapsibleTrigger className=\"group w-full flex items-center gap-2 p-3 text-sm font-medium\">\n {title}\n <ChevronDown className=\"ms-auto size-3.5 text-fd-muted-foreground group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"flex flex-col gap-3 p-3 pt-1\">{children}</div>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n\nexport const Custom = {\n useController(\n fieldName: FieldKey,\n options?: {\n defaultValue?: unknown;\n },\n ) {\n const [value, setValue] = useFieldValue(fieldName, options);\n return {\n value,\n setValue,\n };\n },\n};\n"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { FormatFlags } from "../../utils/schema-to-string.js";
|
|
|
4
4
|
import { anyFields, useFieldInfo, useResolvedSchema, useSchemaScope, useSchemaUtils } from "../schema.js";
|
|
5
5
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/components/select.js";
|
|
6
6
|
import { Input, labelVariants } from "../../ui/components/input.js";
|
|
7
|
+
import { useTranslations } from "../../ui/client/i18n.js";
|
|
7
8
|
import { useState } from "react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
import { ChevronRight, Plus, Trash2, X } from "lucide-react";
|
|
@@ -35,6 +36,7 @@ function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
|
35
36
|
patternProperties
|
|
36
37
|
});
|
|
37
38
|
const hiddenProperties = isLazy ? schemaPropKeys.filter((key) => !_objectKeys.includes(key)) : [];
|
|
39
|
+
const t = useTranslations();
|
|
38
40
|
return /* @__PURE__ */ jsxs("div", {
|
|
39
41
|
...props,
|
|
40
42
|
className: cn("grid grid-cols-1 gap-4 @md:grid-cols-2 *:data-[collapsible=true]:order-last", props.className),
|
|
@@ -44,7 +46,7 @@ function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
|
44
46
|
onValueChange: onAppend,
|
|
45
47
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
46
48
|
className: "col-span-full",
|
|
47
|
-
children: /* @__PURE__ */ jsx(SelectValue, { placeholder:
|
|
49
|
+
children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t.playgroundShowProperty })
|
|
48
50
|
}), /* @__PURE__ */ jsx(SelectContent, { children: hiddenProperties.map((key) => /* @__PURE__ */ jsx(SelectItem, {
|
|
49
51
|
value: key,
|
|
50
52
|
children: key
|
|
@@ -54,7 +56,7 @@ function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
|
54
56
|
let toolbar = null;
|
|
55
57
|
if (child.kind === "pattern" || child.kind === "fallback") toolbar = /* @__PURE__ */ jsx("button", {
|
|
56
58
|
type: "button",
|
|
57
|
-
"aria-label":
|
|
59
|
+
"aria-label": t.playgroundRemoveItem,
|
|
58
60
|
className: cn(buttonVariants({
|
|
59
61
|
color: "outline",
|
|
60
62
|
size: "icon-xs"
|
|
@@ -76,7 +78,7 @@ function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
|
76
78
|
className: "flex gap-2 order-last col-span-full",
|
|
77
79
|
children: [/* @__PURE__ */ jsx(Input, {
|
|
78
80
|
value: nextName,
|
|
79
|
-
placeholder:
|
|
81
|
+
placeholder: t.playgroundPropertyPlaceholder,
|
|
80
82
|
onChange: (e) => setNextName(e.target.value),
|
|
81
83
|
onKeyDown: (e) => {
|
|
82
84
|
if (e.key === "Enter") {
|
|
@@ -95,7 +97,7 @@ function ObjectInput({ field: _field, fieldName, ...props }) {
|
|
|
95
97
|
onAppend(nextName);
|
|
96
98
|
setNextName("");
|
|
97
99
|
},
|
|
98
|
-
children:
|
|
100
|
+
children: t.playgroundNewProperty
|
|
99
101
|
})]
|
|
100
102
|
})
|
|
101
103
|
]
|
|
@@ -128,6 +130,7 @@ function JsonInput({ fieldName }) {
|
|
|
128
130
|
function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
129
131
|
const [value, setValue] = useFieldValue(fieldName);
|
|
130
132
|
const id = stringifyFieldKey(fieldName);
|
|
133
|
+
const t = useTranslations();
|
|
131
134
|
if (field.type === "null") return;
|
|
132
135
|
if (field.type === "string" && field.format === "binary") return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("label", {
|
|
133
136
|
htmlFor: id,
|
|
@@ -137,13 +140,13 @@ function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
|
137
140
|
})),
|
|
138
141
|
children: value instanceof File ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
139
142
|
className: "text-fd-muted-foreground text-xs",
|
|
140
|
-
children:
|
|
143
|
+
children: t.playgroundSelected
|
|
141
144
|
}), /* @__PURE__ */ jsx("span", {
|
|
142
145
|
className: "truncate w-0 flex-1 text-end",
|
|
143
146
|
children: value.name
|
|
144
147
|
})] }) : /* @__PURE__ */ jsx("span", {
|
|
145
148
|
className: "text-fd-muted-foreground",
|
|
146
|
-
children:
|
|
149
|
+
children: t.playgroundInputUpload
|
|
147
150
|
})
|
|
148
151
|
}), /* @__PURE__ */ jsx("input", {
|
|
149
152
|
id,
|
|
@@ -163,13 +166,13 @@ function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
|
163
166
|
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
164
167
|
id,
|
|
165
168
|
...props,
|
|
166
|
-
children: /* @__PURE__ */ jsx(SelectValue, { placeholder:
|
|
169
|
+
children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t.playgroundSelectPlaceholder })
|
|
167
170
|
}), /* @__PURE__ */ jsxs(SelectContent, { children: [field.enum.map((item, i) => /* @__PURE__ */ jsx(SelectItem, {
|
|
168
171
|
value: String(i),
|
|
169
172
|
children: typeof item === "string" ? item : JSON.stringify(item, null, 2)
|
|
170
173
|
}, i)), !isRequired && /* @__PURE__ */ jsx(SelectItem, {
|
|
171
174
|
value: "-1",
|
|
172
|
-
children:
|
|
175
|
+
children: t.playgroundInputUnset
|
|
173
176
|
})] })]
|
|
174
177
|
});
|
|
175
178
|
}
|
|
@@ -191,14 +194,14 @@ function FieldInput({ field, fieldName, isRequired, ...props }) {
|
|
|
191
194
|
}),
|
|
192
195
|
!isRequired && /* @__PURE__ */ jsx(SelectItem, {
|
|
193
196
|
value: "undefined",
|
|
194
|
-
children:
|
|
197
|
+
children: t.playgroundInputUnset
|
|
195
198
|
})
|
|
196
199
|
] })]
|
|
197
200
|
});
|
|
198
201
|
const isNumber = field.type === "integer" || field.type === "number";
|
|
199
202
|
return /* @__PURE__ */ jsx(Input, {
|
|
200
203
|
id,
|
|
201
|
-
placeholder:
|
|
204
|
+
placeholder: t.inputPlaceholder,
|
|
202
205
|
type: isNumber ? "number" : "text",
|
|
203
206
|
step: field.type === "integer" ? 1 : void 0,
|
|
204
207
|
value: String(value ?? ""),
|
|
@@ -372,6 +375,7 @@ function ArrayInput({ fieldName, items: itemSchema, ...props }) {
|
|
|
372
375
|
const name = fieldName.at(-1) ?? "";
|
|
373
376
|
const { generateDefault } = useSchemaUtils();
|
|
374
377
|
const { items, insertItem, removeItem } = useArray(fieldName);
|
|
378
|
+
const t = useTranslations();
|
|
375
379
|
return /* @__PURE__ */ jsxs("div", {
|
|
376
380
|
...props,
|
|
377
381
|
className: cn("flex flex-col gap-2", props.className),
|
|
@@ -390,7 +394,7 @@ function ArrayInput({ fieldName, items: itemSchema, ...props }) {
|
|
|
390
394
|
fieldName: item.field,
|
|
391
395
|
toolbar: /* @__PURE__ */ jsx("button", {
|
|
392
396
|
type: "button",
|
|
393
|
-
"aria-label":
|
|
397
|
+
"aria-label": t.playgroundRemoveItem,
|
|
394
398
|
className: cn(buttonVariants({
|
|
395
399
|
color: "outline",
|
|
396
400
|
size: "icon-xs"
|
|
@@ -408,7 +412,7 @@ function ArrayInput({ fieldName, items: itemSchema, ...props }) {
|
|
|
408
412
|
onClick: () => {
|
|
409
413
|
insertItem(generateDefault(itemSchema));
|
|
410
414
|
},
|
|
411
|
-
children: [/* @__PURE__ */ jsx(Plus, { className: "size-4" }),
|
|
415
|
+
children: [/* @__PURE__ */ jsx(Plus, { className: "size-4" }), t.playgroundNewItem]
|
|
412
416
|
})]
|
|
413
417
|
});
|
|
414
418
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputs.js","names":[],"sources":["../../../src/playground/components/inputs.tsx"],"sourcesContent":["'use client';\nimport { type ComponentProps, type HTMLAttributes, type ReactNode, useState } from 'react';\nimport { ChevronRight, Plus, Trash2, X } from 'lucide-react';\nimport { FieldKey, useArray, useDataEngine, useFieldValue, useObject } from '@fumari/stf';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { Input, labelVariants } from '@/ui/components/input';\nimport { cn } from '@/utils/cn';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { FormatFlags } from '@/utils/schema-to-string';\nimport {\n anyFields,\n useFieldInfo,\n useSchemaUtils,\n useSchemaScope,\n useResolvedSchema,\n} from '@/playground/schema';\nimport type { ParsedSchema } from '@/utils/schema';\nimport { stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { cva } from 'class-variance-authority';\n\nconst fieldLabelVariants = cva('w-full inline-flex items-center gap-0.5');\n\nfunction FieldLabelType(props: ComponentProps<'code'>) {\n return (\n <code {...props} className={cn('text-xs text-fd-muted-foreground', props.className)}>\n {props.children}\n </code>\n );\n}\n\nexport function ObjectInput({\n field: _field,\n fieldName,\n ...props\n}: {\n field: Exclude<ParsedSchema, boolean>;\n fieldName: FieldKey;\n} & ComponentProps<'div'>) {\n const { generateDefault } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const schemaPropKeys = field.properties ? Object.keys(field.properties) : [];\n const {\n patternProperties = {},\n additionalProperties,\n 'x-playground-lazy': isLazy = schemaPropKeys.length > 100,\n } = field;\n const isDynamic = Object.keys(patternProperties).length > 0 || additionalProperties;\n\n const [nextName, setNextName] = useState('');\n const { properties, onAppend, onDelete, _objectKeys } = useObject(fieldName, {\n lazy: isLazy,\n defaultValue: () => generateDefault(field) as object,\n properties: field.properties ?? {},\n fallback: additionalProperties,\n patternProperties: patternProperties,\n });\n\n const hiddenProperties = isLazy ? schemaPropKeys.filter((key) => !_objectKeys.includes(key)) : [];\n\n return (\n <div\n {...props}\n className={cn(\n 'grid grid-cols-1 gap-4 @md:grid-cols-2 *:data-[collapsible=true]:order-last',\n props.className,\n )}\n >\n {isLazy && hiddenProperties.length > 0 && (\n <Select value=\"\" onValueChange={onAppend}>\n <SelectTrigger className=\"col-span-full\">\n <SelectValue placeholder=\"Show Property\" />\n </SelectTrigger>\n <SelectContent>\n {hiddenProperties.map((key) => (\n <SelectItem key={key} value={key}>\n {key}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n\n {properties.map((child) => {\n let toolbar: ReactNode = null;\n if (child.kind === 'pattern' || child.kind === 'fallback') {\n toolbar = (\n <button\n type=\"button\"\n aria-label=\"Remove Item\"\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => {\n onDelete(child.key);\n }}\n >\n <Trash2 />\n </button>\n );\n }\n\n return (\n <FieldSet\n key={child.key}\n name={child.key}\n field={child.info}\n fieldName={child.field}\n isRequired={field.required?.includes(child.key)}\n toolbar={toolbar}\n />\n );\n })}\n {isDynamic && (\n <div className=\"flex gap-2 order-last col-span-full\">\n <Input\n value={nextName}\n placeholder=\"Enter Property Name\"\n onChange={(e) => setNextName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n setNextName('');\n onAppend(nextName);\n e.preventDefault();\n }\n }}\n />\n <button\n type=\"button\"\n className={cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4')}\n onClick={() => {\n onAppend(nextName);\n setNextName('');\n }}\n >\n New\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function JsonInput({ fieldName }: { fieldName: FieldKey }) {\n const engine = useDataEngine();\n const [error, setError] = useState<string | null>(null);\n const [value, setValue] = useState(() => JSON.stringify(engine.init(fieldName, {}), null, 2));\n\n return (\n <div className=\"flex flex-col bg-fd-secondary text-fd-secondary-foreground overflow-hidden border rounded-lg\">\n <textarea\n value={value}\n className=\"p-2 h-[240px] text-sm font-mono resize-none focus-visible:outline-none\"\n onChange={(v) => {\n setValue(v.target.value);\n try {\n engine.update(fieldName, JSON.parse(v.target.value));\n setError(null);\n } catch (e) {\n if (e instanceof Error) setError(e.message);\n }\n }}\n />\n <p className=\"p-2 text-xs font-mono border-t text-red-400 empty:hidden\">{error}</p>\n </div>\n );\n}\n\nexport function FieldInput({\n field,\n fieldName,\n isRequired,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n field: Exclude<ParsedSchema, boolean>;\n isRequired?: boolean;\n fieldName: FieldKey;\n}) {\n const [value, setValue] = useFieldValue(fieldName);\n const id = stringifyFieldKey(fieldName);\n if (field.type === 'null') return;\n\n if (field.type === 'string' && field.format === 'binary') {\n return (\n <>\n <label\n htmlFor={id}\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'w-full h-9 gap-2 truncate',\n }),\n )}\n >\n {value instanceof File ? (\n <>\n <span className=\"text-fd-muted-foreground text-xs\">Selected</span>\n <span className=\"truncate w-0 flex-1 text-end\">{value.name}</span>\n </>\n ) : (\n <span className=\"text-fd-muted-foreground\">Upload</span>\n )}\n </label>\n <input\n id={id}\n type=\"file\"\n multiple={false}\n onChange={(e) => {\n if (!e.target.files || e.target.files.length === 0) return;\n setValue(e.target.files.item(0));\n }}\n hidden\n />\n </>\n );\n }\n\n if (field.enum && field.enum.length > 0) {\n const idx = field.enum.indexOf(value);\n\n return (\n <Select\n value={idx === -1 && isRequired ? '' : String(idx)}\n onValueChange={(v) => setValue(field.enum![Number(v)])}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue placeholder=\"Select\" />\n </SelectTrigger>\n <SelectContent>\n {field.enum.map((item, i) => (\n <SelectItem key={i} value={String(i)}>\n {typeof item === 'string' ? item : JSON.stringify(item, null, 2)}\n </SelectItem>\n ))}\n {!isRequired && <SelectItem value=\"-1\">Unset</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n if (field.type === 'boolean') {\n return (\n <Select\n value={String(value)}\n onValueChange={(value) => setValue(value === 'undefined' ? undefined : value === 'true')}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"true\">True</SelectItem>\n <SelectItem value=\"false\">False</SelectItem>\n {!isRequired && <SelectItem value=\"undefined\">Unset</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n const isNumber = field.type === 'integer' || field.type === 'number';\n return (\n <Input\n id={id}\n placeholder=\"Enter value\"\n type={isNumber ? 'number' : 'text'}\n step={field.type === 'integer' ? 1 : undefined}\n value={String(value ?? '')}\n onChange={(e) => {\n if (isNumber) {\n setValue(Number.isNaN(e.target.valueAsNumber) ? undefined : e.target.valueAsNumber);\n } else if (!isNumber) {\n setValue(e.target.value);\n }\n }}\n />\n );\n}\n\nexport function FieldSet({\n field: _field,\n fieldName,\n toolbar,\n name,\n isRequired,\n depth = 0,\n slotType,\n collapsible = true,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n isRequired?: boolean;\n name?: ReactNode;\n field: ParsedSchema;\n fieldName: FieldKey;\n depth?: number;\n\n slotType?: ReactNode;\n toolbar?: ReactNode;\n collapsible?: boolean;\n}) {\n const { readOnly, writeOnly } = useSchemaScope();\n const { generateDefault, schemaToString } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const [show, setShow] = useState(!collapsible);\n const { info, updateInfo } = useFieldInfo(fieldName, field, depth);\n const id = stringifyFieldKey(fieldName);\n const dataEngine = useDataEngine();\n const [isDefined] = useFieldValue(fieldName, {\n compute(currentValue) {\n return currentValue !== undefined;\n },\n });\n\n if (_field === false) return;\n if (field.readOnly && !readOnly) return;\n if (field.writeOnly && !writeOnly) return;\n\n if (collapsible && !isDefined && show) setShow(false);\n\n function renderLabelTrigger(schema = field) {\n if (!collapsible) return renderLabelName();\n\n return (\n <button\n type=\"button\"\n className={cn(labelVariants(), 'inline-flex items-center gap-1 font-mono me-auto')}\n onClick={() => {\n dataEngine.init(fieldName, generateDefault(schema));\n setShow((prev) => !prev);\n }}\n >\n <ChevronRight className={cn('size-3.5 text-fd-muted-foreground', show && 'rotate-90')} />\n {name}\n {isRequired && <span className=\"text-red-400/80\">*</span>}\n </button>\n );\n }\n\n function renderLabelName() {\n return (\n <span className={cn(labelVariants(), 'font-mono me-auto')}>\n {name}\n {isRequired && <span className=\"text-red-400/80 mx-1\">*</span>}\n </span>\n );\n }\n\n function renderUnsetButton() {\n return (\n <button\n type=\"button\"\n onClick={() => dataEngine.delete(fieldName)}\n className=\"text-fd-muted-foreground hover:text-fd-accent-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n );\n }\n\n if (info.unionField && field[info.unionField] && field[info.unionField]!.length > 0) {\n const union = field[info.unionField]!;\n const showSelect = union.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={union[info.oneOf]}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n collapsible={collapsible}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.oneOf}\n onChange={(e) => {\n updateInfo({\n oneOf: Number(e.target.value),\n });\n }}\n >\n {union.map((item, i) => (\n <option key={i} value={i} className=\"bg-fd-popover text-fd-popover-foreground\">\n {schemaToString(item, FormatFlags.UseAlias)}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (Array.isArray(field.type)) {\n const showSelect = field.type.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={{\n ...field,\n type: info.selectedType,\n }}\n collapsible={collapsible}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.selectedType}\n onChange={(e) => {\n updateInfo({\n selectedType: e.target.value,\n });\n }}\n >\n {field.type.map((item) => (\n <option\n key={item}\n value={item}\n className=\"bg-fd-popover text-fd-popover-foreground\"\n >\n {item}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (field.type === 'object') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full @container', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger(field)}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ObjectInput\n field={field}\n fieldName={fieldName}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n if (field.type === 'array') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ArrayInput\n fieldName={fieldName}\n items={field.items ?? anyFields}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n return (\n <fieldset {...props} className={cn('flex flex-col gap-1.5', props.className)}>\n <label className={fieldLabelVariants()} htmlFor={id}>\n {renderLabelName()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </label>\n <FieldInput field={field} fieldName={fieldName} isRequired={isRequired} />\n </fieldset>\n );\n}\n\nfunction ArrayInput({\n fieldName,\n items: itemSchema,\n ...props\n}: {\n fieldName: FieldKey;\n items: ParsedSchema;\n} & ComponentProps<'div'>) {\n const name = fieldName.at(-1) ?? '';\n const { generateDefault } = useSchemaUtils();\n const { items, insertItem, removeItem } = useArray(fieldName);\n\n return (\n <div {...props} className={cn('flex flex-col gap-2', props.className)}>\n {items.map((item) => (\n <FieldSet\n key={item.index}\n name={\n <span className=\"text-fd-muted-foreground\">\n {name}[{item.index}]\n </span>\n }\n field={itemSchema}\n isRequired\n fieldName={item.field}\n toolbar={\n <button\n type=\"button\"\n aria-label=\"Remove Item\"\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => removeItem(item.index)}\n >\n <Trash2 />\n </button>\n }\n />\n ))}\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'gap-1.5 py-2',\n size: 'sm',\n }),\n )}\n onClick={() => {\n insertItem(generateDefault(itemSchema));\n }}\n >\n <Plus className=\"size-4\" />\n New Item\n </button>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"inputs.js","names":[],"sources":["../../../src/playground/components/inputs.tsx"],"sourcesContent":["'use client';\nimport { type ComponentProps, type HTMLAttributes, type ReactNode, useState } from 'react';\nimport { ChevronRight, Plus, Trash2, X } from 'lucide-react';\nimport { FieldKey, useArray, useDataEngine, useFieldValue, useObject } from '@fumari/stf';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { Input, labelVariants } from '@/ui/components/input';\nimport { cn } from '@/utils/cn';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { FormatFlags } from '@/utils/schema-to-string';\nimport {\n anyFields,\n useFieldInfo,\n useSchemaUtils,\n useSchemaScope,\n useResolvedSchema,\n} from '@/playground/schema';\nimport type { ParsedSchema } from '@/utils/schema';\nimport { stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { cva } from 'class-variance-authority';\nimport { useTranslations } from '@/ui/client/i18n';\n\nconst fieldLabelVariants = cva('w-full inline-flex items-center gap-0.5');\n\nfunction FieldLabelType(props: ComponentProps<'code'>) {\n return (\n <code {...props} className={cn('text-xs text-fd-muted-foreground', props.className)}>\n {props.children}\n </code>\n );\n}\n\nexport function ObjectInput({\n field: _field,\n fieldName,\n ...props\n}: {\n field: Exclude<ParsedSchema, boolean>;\n fieldName: FieldKey;\n} & ComponentProps<'div'>) {\n const { generateDefault } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const schemaPropKeys = field.properties ? Object.keys(field.properties) : [];\n const {\n patternProperties = {},\n additionalProperties,\n 'x-playground-lazy': isLazy = schemaPropKeys.length > 100,\n } = field;\n const isDynamic = Object.keys(patternProperties).length > 0 || additionalProperties;\n\n const [nextName, setNextName] = useState('');\n const { properties, onAppend, onDelete, _objectKeys } = useObject(fieldName, {\n lazy: isLazy,\n defaultValue: () => generateDefault(field) as object,\n properties: field.properties ?? {},\n fallback: additionalProperties,\n patternProperties: patternProperties,\n });\n\n const hiddenProperties = isLazy ? schemaPropKeys.filter((key) => !_objectKeys.includes(key)) : [];\n const t = useTranslations();\n\n return (\n <div\n {...props}\n className={cn(\n 'grid grid-cols-1 gap-4 @md:grid-cols-2 *:data-[collapsible=true]:order-last',\n props.className,\n )}\n >\n {isLazy && hiddenProperties.length > 0 && (\n <Select value=\"\" onValueChange={onAppend}>\n <SelectTrigger className=\"col-span-full\">\n <SelectValue placeholder={t.playgroundShowProperty} />\n </SelectTrigger>\n <SelectContent>\n {hiddenProperties.map((key) => (\n <SelectItem key={key} value={key}>\n {key}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n\n {properties.map((child) => {\n let toolbar: ReactNode = null;\n if (child.kind === 'pattern' || child.kind === 'fallback') {\n toolbar = (\n <button\n type=\"button\"\n aria-label={t.playgroundRemoveItem}\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => {\n onDelete(child.key);\n }}\n >\n <Trash2 />\n </button>\n );\n }\n\n return (\n <FieldSet\n key={child.key}\n name={child.key}\n field={child.info}\n fieldName={child.field}\n isRequired={field.required?.includes(child.key)}\n toolbar={toolbar}\n />\n );\n })}\n {isDynamic && (\n <div className=\"flex gap-2 order-last col-span-full\">\n <Input\n value={nextName}\n placeholder={t.playgroundPropertyPlaceholder}\n onChange={(e) => setNextName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n setNextName('');\n onAppend(nextName);\n e.preventDefault();\n }\n }}\n />\n <button\n type=\"button\"\n className={cn(buttonVariants({ color: 'secondary', size: 'sm' }), 'px-4')}\n onClick={() => {\n onAppend(nextName);\n setNextName('');\n }}\n >\n {t.playgroundNewProperty}\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport function JsonInput({ fieldName }: { fieldName: FieldKey }) {\n const engine = useDataEngine();\n const [error, setError] = useState<string | null>(null);\n const [value, setValue] = useState(() => JSON.stringify(engine.init(fieldName, {}), null, 2));\n\n return (\n <div className=\"flex flex-col bg-fd-secondary text-fd-secondary-foreground overflow-hidden border rounded-lg\">\n <textarea\n value={value}\n className=\"p-2 h-[240px] text-sm font-mono resize-none focus-visible:outline-none\"\n onChange={(v) => {\n setValue(v.target.value);\n try {\n engine.update(fieldName, JSON.parse(v.target.value));\n setError(null);\n } catch (e) {\n if (e instanceof Error) setError(e.message);\n }\n }}\n />\n <p className=\"p-2 text-xs font-mono border-t text-red-400 empty:hidden\">{error}</p>\n </div>\n );\n}\n\nexport function FieldInput({\n field,\n fieldName,\n isRequired,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n field: Exclude<ParsedSchema, boolean>;\n isRequired?: boolean;\n fieldName: FieldKey;\n}) {\n const [value, setValue] = useFieldValue(fieldName);\n const id = stringifyFieldKey(fieldName);\n const t = useTranslations();\n if (field.type === 'null') return;\n\n if (field.type === 'string' && field.format === 'binary') {\n return (\n <>\n <label\n htmlFor={id}\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'w-full h-9 gap-2 truncate',\n }),\n )}\n >\n {value instanceof File ? (\n <>\n <span className=\"text-fd-muted-foreground text-xs\">{t.playgroundSelected}</span>\n <span className=\"truncate w-0 flex-1 text-end\">{value.name}</span>\n </>\n ) : (\n <span className=\"text-fd-muted-foreground\">{t.playgroundInputUpload}</span>\n )}\n </label>\n <input\n id={id}\n type=\"file\"\n multiple={false}\n onChange={(e) => {\n if (!e.target.files || e.target.files.length === 0) return;\n setValue(e.target.files.item(0));\n }}\n hidden\n />\n </>\n );\n }\n\n if (field.enum && field.enum.length > 0) {\n const idx = field.enum.indexOf(value);\n\n return (\n <Select\n value={idx === -1 && isRequired ? '' : String(idx)}\n onValueChange={(v) => setValue(field.enum![Number(v)])}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue placeholder={t.playgroundSelectPlaceholder} />\n </SelectTrigger>\n <SelectContent>\n {field.enum.map((item, i) => (\n <SelectItem key={i} value={String(i)}>\n {typeof item === 'string' ? item : JSON.stringify(item, null, 2)}\n </SelectItem>\n ))}\n {!isRequired && <SelectItem value=\"-1\">{t.playgroundInputUnset}</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n if (field.type === 'boolean') {\n return (\n <Select\n value={String(value)}\n onValueChange={(value) => setValue(value === 'undefined' ? undefined : value === 'true')}\n >\n <SelectTrigger id={id} {...props}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"true\">True</SelectItem>\n <SelectItem value=\"false\">False</SelectItem>\n {!isRequired && <SelectItem value=\"undefined\">{t.playgroundInputUnset}</SelectItem>}\n </SelectContent>\n </Select>\n );\n }\n\n const isNumber = field.type === 'integer' || field.type === 'number';\n return (\n <Input\n id={id}\n placeholder={t.inputPlaceholder}\n type={isNumber ? 'number' : 'text'}\n step={field.type === 'integer' ? 1 : undefined}\n value={String(value ?? '')}\n onChange={(e) => {\n if (isNumber) {\n setValue(Number.isNaN(e.target.valueAsNumber) ? undefined : e.target.valueAsNumber);\n } else if (!isNumber) {\n setValue(e.target.value);\n }\n }}\n />\n );\n}\n\nexport function FieldSet({\n field: _field,\n fieldName,\n toolbar,\n name,\n isRequired,\n depth = 0,\n slotType,\n collapsible = true,\n ...props\n}: HTMLAttributes<HTMLElement> & {\n isRequired?: boolean;\n name?: ReactNode;\n field: ParsedSchema;\n fieldName: FieldKey;\n depth?: number;\n\n slotType?: ReactNode;\n toolbar?: ReactNode;\n collapsible?: boolean;\n}) {\n const { readOnly, writeOnly } = useSchemaScope();\n const { generateDefault, schemaToString } = useSchemaUtils();\n const field = useResolvedSchema(_field);\n const [show, setShow] = useState(!collapsible);\n const { info, updateInfo } = useFieldInfo(fieldName, field, depth);\n const id = stringifyFieldKey(fieldName);\n const dataEngine = useDataEngine();\n const [isDefined] = useFieldValue(fieldName, {\n compute(currentValue) {\n return currentValue !== undefined;\n },\n });\n\n if (_field === false) return;\n if (field.readOnly && !readOnly) return;\n if (field.writeOnly && !writeOnly) return;\n\n if (collapsible && !isDefined && show) setShow(false);\n\n function renderLabelTrigger(schema = field) {\n if (!collapsible) return renderLabelName();\n\n return (\n <button\n type=\"button\"\n className={cn(labelVariants(), 'inline-flex items-center gap-1 font-mono me-auto')}\n onClick={() => {\n dataEngine.init(fieldName, generateDefault(schema));\n setShow((prev) => !prev);\n }}\n >\n <ChevronRight className={cn('size-3.5 text-fd-muted-foreground', show && 'rotate-90')} />\n {name}\n {isRequired && <span className=\"text-red-400/80\">*</span>}\n </button>\n );\n }\n\n function renderLabelName() {\n return (\n <span className={cn(labelVariants(), 'font-mono me-auto')}>\n {name}\n {isRequired && <span className=\"text-red-400/80 mx-1\">*</span>}\n </span>\n );\n }\n\n function renderUnsetButton() {\n return (\n <button\n type=\"button\"\n onClick={() => dataEngine.delete(fieldName)}\n className=\"text-fd-muted-foreground hover:text-fd-accent-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n );\n }\n\n if (info.unionField && field[info.unionField] && field[info.unionField]!.length > 0) {\n const union = field[info.unionField]!;\n const showSelect = union.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={union[info.oneOf]}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n collapsible={collapsible}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.oneOf}\n onChange={(e) => {\n updateInfo({\n oneOf: Number(e.target.value),\n });\n }}\n >\n {union.map((item, i) => (\n <option key={i} value={i} className=\"bg-fd-popover text-fd-popover-foreground\">\n {schemaToString(item, FormatFlags.UseAlias)}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (Array.isArray(field.type)) {\n const showSelect = field.type.length > 1;\n\n return (\n <FieldSet\n {...props}\n name={name}\n fieldName={fieldName}\n isRequired={isRequired}\n field={{\n ...field,\n type: info.selectedType,\n }}\n collapsible={collapsible}\n depth={depth + 1}\n slotType={showSelect ? false : slotType}\n toolbar={\n <>\n {showSelect && (\n <select\n className=\"text-xs font-mono\"\n value={info.selectedType}\n onChange={(e) => {\n updateInfo({\n selectedType: e.target.value,\n });\n }}\n >\n {field.type.map((item) => (\n <option\n key={item}\n value={item}\n className=\"bg-fd-popover text-fd-popover-foreground\"\n >\n {item}\n </option>\n ))}\n </select>\n )}\n {toolbar}\n </>\n }\n />\n );\n }\n\n if (field.type === 'object') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full @container', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger(field)}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ObjectInput\n field={field}\n fieldName={fieldName}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n if (field.type === 'array') {\n return (\n <fieldset\n {...props}\n data-collapsible={collapsible}\n className={cn('flex flex-col gap-1.5 col-span-full', props.className)}\n >\n <div className={fieldLabelVariants()}>\n {renderLabelTrigger()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </div>\n {show && (\n <ArrayInput\n fieldName={fieldName}\n items={field.items ?? anyFields}\n className=\"rounded-lg border border-fd-primary/20 bg-fd-background/50 p-2 shadow-sm\"\n />\n )}\n </fieldset>\n );\n }\n\n return (\n <fieldset {...props} className={cn('flex flex-col gap-1.5', props.className)}>\n <label className={fieldLabelVariants()} htmlFor={id}>\n {renderLabelName()}\n {slotType ?? <FieldLabelType>{schemaToString(field)}</FieldLabelType>}\n {toolbar}\n {!isRequired && isDefined && renderUnsetButton()}\n </label>\n <FieldInput field={field} fieldName={fieldName} isRequired={isRequired} />\n </fieldset>\n );\n}\n\nfunction ArrayInput({\n fieldName,\n items: itemSchema,\n ...props\n}: {\n fieldName: FieldKey;\n items: ParsedSchema;\n} & ComponentProps<'div'>) {\n const name = fieldName.at(-1) ?? '';\n const { generateDefault } = useSchemaUtils();\n const { items, insertItem, removeItem } = useArray(fieldName);\n const t = useTranslations();\n\n return (\n <div {...props} className={cn('flex flex-col gap-2', props.className)}>\n {items.map((item) => (\n <FieldSet\n key={item.index}\n name={\n <span className=\"text-fd-muted-foreground\">\n {name}[{item.index}]\n </span>\n }\n field={itemSchema}\n isRequired\n fieldName={item.field}\n toolbar={\n <button\n type=\"button\"\n aria-label={t.playgroundRemoveItem}\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'icon-xs',\n }),\n )}\n onClick={() => removeItem(item.index)}\n >\n <Trash2 />\n </button>\n }\n />\n ))}\n <button\n type=\"button\"\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'gap-1.5 py-2',\n size: 'sm',\n }),\n )}\n onClick={() => {\n insertItem(generateDefault(itemSchema));\n }}\n >\n <Plus className=\"size-4\" />\n {t.playgroundNewItem}\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AA2BA,MAAM,qBAAqB,IAAI,0CAA0C;AAEzE,SAAS,eAAe,OAA+B;AACrD,QACE,oBAAC,QAAD;EAAM,GAAI;EAAO,WAAW,GAAG,oCAAoC,MAAM,UAAU;YAChF,MAAM;EACF,CAAA;;AAIX,SAAgB,YAAY,EAC1B,OAAO,QACP,WACA,GAAG,SAIsB;CACzB,MAAM,EAAE,oBAAoB,gBAAgB;CAC5C,MAAM,QAAQ,kBAAkB,OAAO;CACvC,MAAM,iBAAiB,MAAM,aAAa,OAAO,KAAK,MAAM,WAAW,GAAG,EAAE;CAC5E,MAAM,EACJ,oBAAoB,EAAE,EACtB,sBACA,qBAAqB,SAAS,eAAe,SAAS,QACpD;CACJ,MAAM,YAAY,OAAO,KAAK,kBAAkB,CAAC,SAAS,KAAK;CAE/D,MAAM,CAAC,UAAU,eAAe,SAAS,GAAG;CAC5C,MAAM,EAAE,YAAY,UAAU,UAAU,gBAAgB,UAAU,WAAW;EAC3E,MAAM;EACN,oBAAoB,gBAAgB,MAAM;EAC1C,YAAY,MAAM,cAAc,EAAE;EAClC,UAAU;EACS;EACpB,CAAC;CAEF,MAAM,mBAAmB,SAAS,eAAe,QAAQ,QAAQ,CAAC,YAAY,SAAS,IAAI,CAAC,GAAG,EAAE;CACjG,MAAM,IAAI,iBAAiB;AAE3B,QACE,qBAAC,OAAD;EACE,GAAI;EACJ,WAAW,GACT,+EACA,MAAM,UACP;YALH;GAOG,UAAU,iBAAiB,SAAS,KACnC,qBAAC,QAAD;IAAQ,OAAM;IAAG,eAAe;cAAhC,CACE,oBAAC,eAAD;KAAe,WAAU;eACvB,oBAAC,aAAD,EAAa,aAAa,EAAE,wBAA0B,CAAA;KACxC,CAAA,EAChB,oBAAC,eAAD,EAAA,UACG,iBAAiB,KAAK,QACrB,oBAAC,YAAD;KAAsB,OAAO;eAC1B;KACU,EAFI,IAEJ,CACb,EACY,CAAA,CACT;;GAGV,WAAW,KAAK,UAAU;IACzB,IAAI,UAAqB;AACzB,QAAI,MAAM,SAAS,aAAa,MAAM,SAAS,WAC7C,WACE,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE;KACd,WAAW,GACT,eAAe;MACb,OAAO;MACP,MAAM;MACP,CAAC,CACH;KACD,eAAe;AACb,eAAS,MAAM,IAAI;;eAGrB,oBAAC,QAAD,EAAU,CAAA;KACH,CAAA;AAIb,WACE,oBAAC,UAAD;KAEE,MAAM,MAAM;KACZ,OAAO,MAAM;KACb,WAAW,MAAM;KACjB,YAAY,MAAM,UAAU,SAAS,MAAM,IAAI;KACtC;KACT,EANK,MAAM,IAMX;KAEJ;GACD,aACC,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,OAAD;KACE,OAAO;KACP,aAAa,EAAE;KACf,WAAW,MAAM,YAAY,EAAE,OAAO,MAAM;KAC5C,YAAY,MAAM;AAChB,UAAI,EAAE,QAAQ,SAAS;AACrB,mBAAY,GAAG;AACf,gBAAS,SAAS;AAClB,SAAE,gBAAgB;;;KAGtB,CAAA,EACF,oBAAC,UAAD;KACE,MAAK;KACL,WAAW,GAAG,eAAe;MAAE,OAAO;MAAa,MAAM;MAAM,CAAC,EAAE,OAAO;KACzE,eAAe;AACb,eAAS,SAAS;AAClB,kBAAY,GAAG;;eAGhB,EAAE;KACI,CAAA,CACL;;GAEJ;;;AAIV,SAAgB,UAAU,EAAE,aAAsC;CAChE,MAAM,SAAS,eAAe;CAC9B,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CACvD,MAAM,CAAC,OAAO,YAAY,eAAe,KAAK,UAAU,OAAO,KAAK,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;AAE7F,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,YAAD;GACS;GACP,WAAU;GACV,WAAW,MAAM;AACf,aAAS,EAAE,OAAO,MAAM;AACxB,QAAI;AACF,YAAO,OAAO,WAAW,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;AACpD,cAAS,KAAK;aACP,GAAG;AACV,SAAI,aAAa,MAAO,UAAS,EAAE,QAAQ;;;GAG/C,CAAA,EACF,oBAAC,KAAD;GAAG,WAAU;aAA4D;GAAU,CAAA,CAC/E;;;AAIV,SAAgB,WAAW,EACzB,OACA,WACA,YACA,GAAG,SAKF;CACD,MAAM,CAAC,OAAO,YAAY,cAAc,UAAU;CAClD,MAAM,KAAK,kBAAkB,UAAU;CACvC,MAAM,IAAI,iBAAiB;AAC3B,KAAI,MAAM,SAAS,OAAQ;AAE3B,KAAI,MAAM,SAAS,YAAY,MAAM,WAAW,SAC9C,QACE,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,SAAD;EACE,SAAS;EACT,WAAW,GACT,eAAe;GACb,OAAO;GACP,WAAW;GACZ,CAAC,CACH;YAEA,iBAAiB,OAChB,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,QAAD;GAAM,WAAU;aAAoC,EAAE;GAA0B,CAAA,EAChF,oBAAC,QAAD;GAAM,WAAU;aAAgC,MAAM;GAAY,CAAA,CACjE,EAAA,CAAA,GAEH,oBAAC,QAAD;GAAM,WAAU;aAA4B,EAAE;GAA6B,CAAA;EAEvE,CAAA,EACR,oBAAC,SAAD;EACM;EACJ,MAAK;EACL,UAAU;EACV,WAAW,MAAM;AACf,OAAI,CAAC,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,WAAW,EAAG;AACpD,YAAS,EAAE,OAAO,MAAM,KAAK,EAAE,CAAC;;EAElC,QAAA;EACA,CAAA,CACD,EAAA,CAAA;AAIP,KAAI,MAAM,QAAQ,MAAM,KAAK,SAAS,GAAG;EACvC,MAAM,MAAM,MAAM,KAAK,QAAQ,MAAM;AAErC,SACE,qBAAC,QAAD;GACE,OAAO,QAAQ,MAAM,aAAa,KAAK,OAAO,IAAI;GAClD,gBAAgB,MAAM,SAAS,MAAM,KAAM,OAAO,EAAE,EAAE;aAFxD,CAIE,oBAAC,eAAD;IAAmB;IAAI,GAAI;cACzB,oBAAC,aAAD,EAAa,aAAa,EAAE,6BAA+B,CAAA;IAC7C,CAAA,EAChB,qBAAC,eAAD,EAAA,UAAA,CACG,MAAM,KAAK,KAAK,MAAM,MACrB,oBAAC,YAAD;IAAoB,OAAO,OAAO,EAAE;cACjC,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,MAAM,MAAM,EAAE;IACrD,EAFI,EAEJ,CACb,EACD,CAAC,cAAc,oBAAC,YAAD;IAAY,OAAM;cAAM,EAAE;IAAkC,CAAA,CAC9D,EAAA,CAAA,CACT;;;AAIb,KAAI,MAAM,SAAS,UACjB,QACE,qBAAC,QAAD;EACE,OAAO,OAAO,MAAM;EACpB,gBAAgB,UAAU,SAAS,UAAU,cAAc,KAAA,IAAY,UAAU,OAAO;YAF1F,CAIE,oBAAC,eAAD;GAAmB;GAAI,GAAI;aACzB,oBAAC,aAAD,EAAe,CAAA;GACD,CAAA,EAChB,qBAAC,eAAD,EAAA,UAAA;GACE,oBAAC,YAAD;IAAY,OAAM;cAAO;IAAiB,CAAA;GAC1C,oBAAC,YAAD;IAAY,OAAM;cAAQ;IAAkB,CAAA;GAC3C,CAAC,cAAc,oBAAC,YAAD;IAAY,OAAM;cAAa,EAAE;IAAkC,CAAA;GACrE,EAAA,CAAA,CACT;;CAIb,MAAM,WAAW,MAAM,SAAS,aAAa,MAAM,SAAS;AAC5D,QACE,oBAAC,OAAD;EACM;EACJ,aAAa,EAAE;EACf,MAAM,WAAW,WAAW;EAC5B,MAAM,MAAM,SAAS,YAAY,IAAI,KAAA;EACrC,OAAO,OAAO,SAAS,GAAG;EAC1B,WAAW,MAAM;AACf,OAAI,SACF,UAAS,OAAO,MAAM,EAAE,OAAO,cAAc,GAAG,KAAA,IAAY,EAAE,OAAO,cAAc;YAC1E,CAAC,SACV,UAAS,EAAE,OAAO,MAAM;;EAG5B,CAAA;;AAIN,SAAgB,SAAS,EACvB,OAAO,QACP,WACA,SACA,MACA,YACA,QAAQ,GACR,UACA,cAAc,MACd,GAAG,SAWF;CACD,MAAM,EAAE,UAAU,cAAc,gBAAgB;CAChD,MAAM,EAAE,iBAAiB,mBAAmB,gBAAgB;CAC5D,MAAM,QAAQ,kBAAkB,OAAO;CACvC,MAAM,CAAC,MAAM,WAAW,SAAS,CAAC,YAAY;CAC9C,MAAM,EAAE,MAAM,eAAe,aAAa,WAAW,OAAO,MAAM;CAClE,MAAM,KAAK,kBAAkB,UAAU;CACvC,MAAM,aAAa,eAAe;CAClC,MAAM,CAAC,aAAa,cAAc,WAAW,EAC3C,QAAQ,cAAc;AACpB,SAAO,iBAAiB,KAAA;IAE3B,CAAC;AAEF,KAAI,WAAW,MAAO;AACtB,KAAI,MAAM,YAAY,CAAC,SAAU;AACjC,KAAI,MAAM,aAAa,CAAC,UAAW;AAEnC,KAAI,eAAe,CAAC,aAAa,KAAM,SAAQ,MAAM;CAErD,SAAS,mBAAmB,SAAS,OAAO;AAC1C,MAAI,CAAC,YAAa,QAAO,iBAAiB;AAE1C,SACE,qBAAC,UAAD;GACE,MAAK;GACL,WAAW,GAAG,eAAe,EAAE,mDAAmD;GAClF,eAAe;AACb,eAAW,KAAK,WAAW,gBAAgB,OAAO,CAAC;AACnD,aAAS,SAAS,CAAC,KAAK;;aAL5B;IAQE,oBAAC,cAAD,EAAc,WAAW,GAAG,qCAAqC,QAAQ,YAAY,EAAI,CAAA;IACxF;IACA,cAAc,oBAAC,QAAD;KAAM,WAAU;eAAkB;KAAQ,CAAA;IAClD;;;CAIb,SAAS,kBAAkB;AACzB,SACE,qBAAC,QAAD;GAAM,WAAW,GAAG,eAAe,EAAE,oBAAoB;aAAzD,CACG,MACA,cAAc,oBAAC,QAAD;IAAM,WAAU;cAAuB;IAAQ,CAAA,CACzD;;;CAIX,SAAS,oBAAoB;AAC3B,SACE,oBAAC,UAAD;GACE,MAAK;GACL,eAAe,WAAW,OAAO,UAAU;GAC3C,WAAU;aAEV,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;GACnB,CAAA;;AAIb,KAAI,KAAK,cAAc,MAAM,KAAK,eAAe,MAAM,KAAK,YAAa,SAAS,GAAG;EACnF,MAAM,QAAQ,MAAM,KAAK;EACzB,MAAM,aAAa,MAAM,SAAS;AAElC,SACE,oBAAC,UAAD;GACE,GAAI;GACE;GACK;GACC;GACZ,OAAO,MAAM,KAAK;GAClB,OAAO,QAAQ;GACf,UAAU,aAAa,QAAQ;GAClB;GACb,SACE,qBAAA,YAAA,EAAA,UAAA,CACG,cACC,oBAAC,UAAD;IACE,WAAU;IACV,OAAO,KAAK;IACZ,WAAW,MAAM;AACf,gBAAW,EACT,OAAO,OAAO,EAAE,OAAO,MAAM,EAC9B,CAAC;;cAGH,MAAM,KAAK,MAAM,MAChB,oBAAC,UAAD;KAAgB,OAAO;KAAG,WAAU;eACjC,eAAe,MAAM,YAAY,SAAS;KACpC,EAFI,EAEJ,CACT;IACK,CAAA,EAEV,QACA,EAAA,CAAA;GAEL,CAAA;;AAIN,KAAI,MAAM,QAAQ,MAAM,KAAK,EAAE;EAC7B,MAAM,aAAa,MAAM,KAAK,SAAS;AAEvC,SACE,oBAAC,UAAD;GACE,GAAI;GACE;GACK;GACC;GACZ,OAAO;IACL,GAAG;IACH,MAAM,KAAK;IACZ;GACY;GACb,OAAO,QAAQ;GACf,UAAU,aAAa,QAAQ;GAC/B,SACE,qBAAA,YAAA,EAAA,UAAA,CACG,cACC,oBAAC,UAAD;IACE,WAAU;IACV,OAAO,KAAK;IACZ,WAAW,MAAM;AACf,gBAAW,EACT,cAAc,EAAE,OAAO,OACxB,CAAC;;cAGH,MAAM,KAAK,KAAK,SACf,oBAAC,UAAD;KAEE,OAAO;KACP,WAAU;eAET;KACM,EALF,KAKE,CACT;IACK,CAAA,EAEV,QACA,EAAA,CAAA;GAEL,CAAA;;AAIN,KAAI,MAAM,SAAS,SACjB,QACE,qBAAC,YAAD;EACE,GAAI;EACJ,oBAAkB;EAClB,WAAW,GAAG,kDAAkD,MAAM,UAAU;YAHlF,CAKE,qBAAC,OAAD;GAAK,WAAW,oBAAoB;aAApC;IACG,mBAAmB,MAAM;IACzB,YAAY,oBAAC,gBAAD,EAAA,UAAiB,eAAe,MAAM,EAAkB,CAAA;IACpE;IACA,CAAC,cAAc,aAAa,mBAAmB;IAC5C;MACL,QACC,oBAAC,aAAD;GACS;GACI;GACX,WAAU;GACV,CAAA,CAEK;;AAIf,KAAI,MAAM,SAAS,QACjB,QACE,qBAAC,YAAD;EACE,GAAI;EACJ,oBAAkB;EAClB,WAAW,GAAG,uCAAuC,MAAM,UAAU;YAHvE,CAKE,qBAAC,OAAD;GAAK,WAAW,oBAAoB;aAApC;IACG,oBAAoB;IACpB,YAAY,oBAAC,gBAAD,EAAA,UAAiB,eAAe,MAAM,EAAkB,CAAA;IACpE;IACA,CAAC,cAAc,aAAa,mBAAmB;IAC5C;MACL,QACC,oBAAC,YAAD;GACa;GACX,OAAO,MAAM,SAAS;GACtB,WAAU;GACV,CAAA,CAEK;;AAIf,QACE,qBAAC,YAAD;EAAU,GAAI;EAAO,WAAW,GAAG,yBAAyB,MAAM,UAAU;YAA5E,CACE,qBAAC,SAAD;GAAO,WAAW,oBAAoB;GAAE,SAAS;aAAjD;IACG,iBAAiB;IACjB,YAAY,oBAAC,gBAAD,EAAA,UAAiB,eAAe,MAAM,EAAkB,CAAA;IACpE;IACA,CAAC,cAAc,aAAa,mBAAmB;IAC1C;MACR,oBAAC,YAAD;GAAmB;GAAkB;GAAuB;GAAc,CAAA,CACjE;;;AAIf,SAAS,WAAW,EAClB,WACA,OAAO,YACP,GAAG,SAIsB;CACzB,MAAM,OAAO,UAAU,GAAG,GAAG,IAAI;CACjC,MAAM,EAAE,oBAAoB,gBAAgB;CAC5C,MAAM,EAAE,OAAO,YAAY,eAAe,SAAS,UAAU;CAC7D,MAAM,IAAI,iBAAiB;AAE3B,QACE,qBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,GAAG,uBAAuB,MAAM,UAAU;YAArE,CACG,MAAM,KAAK,SACV,oBAAC,UAAD;GAEE,MACE,qBAAC,QAAD;IAAM,WAAU;cAAhB;KACG;KAAK;KAAE,KAAK;KAAM;KACd;;GAET,OAAO;GACP,YAAA;GACA,WAAW,KAAK;GAChB,SACE,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,EAAE;IACd,WAAW,GACT,eAAe;KACb,OAAO;KACP,MAAM;KACP,CAAC,CACH;IACD,eAAe,WAAW,KAAK,MAAM;cAErC,oBAAC,QAAD,EAAU,CAAA;IACH,CAAA;GAEX,EAxBK,KAAK,MAwBV,CACF,EACF,qBAAC,UAAD;GACE,MAAK;GACL,WAAW,GACT,eAAe;IACb,OAAO;IACP,WAAW;IACX,MAAM;IACP,CAAC,CACH;GACD,eAAe;AACb,eAAW,gBAAgB,WAAW,CAAC;;aAV3C,CAaE,oBAAC,MAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EAAE,kBACI;KACL"}
|