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.
Files changed (59) hide show
  1. package/css/generated/shared.css +64 -15
  2. package/dist/i18n.d.ts +100 -0
  3. package/dist/i18n.d.ts.map +1 -0
  4. package/dist/i18n.js +113 -0
  5. package/dist/i18n.js.map +1 -0
  6. package/dist/playground/client.d.ts.map +1 -1
  7. package/dist/playground/client.js +35 -23
  8. package/dist/playground/client.js.map +1 -1
  9. package/dist/playground/components/inputs.js +16 -12
  10. package/dist/playground/components/inputs.js.map +1 -1
  11. package/dist/playground/components/oauth-dialog.js +45 -44
  12. package/dist/playground/components/oauth-dialog.js.map +1 -1
  13. package/dist/playground/components/server-select.js +7 -4
  14. package/dist/playground/components/server-select.js.map +1 -1
  15. package/dist/playground/status-info.js +18 -11
  16. package/dist/playground/status-info.js.map +1 -1
  17. package/dist/types.d.ts +3 -1
  18. package/dist/types.d.ts.map +1 -1
  19. package/dist/ui/base.d.ts +7 -6
  20. package/dist/ui/base.d.ts.map +1 -1
  21. package/dist/ui/base.js +13 -7
  22. package/dist/ui/base.js.map +1 -1
  23. package/dist/ui/client/i18n.js +19 -0
  24. package/dist/ui/client/i18n.js.map +1 -0
  25. package/dist/ui/components/codeblock.d.ts +15 -0
  26. package/dist/ui/components/codeblock.d.ts.map +1 -0
  27. package/dist/ui/components/codeblock.js +27 -0
  28. package/dist/ui/components/codeblock.js.map +1 -0
  29. package/dist/ui/components/dialog.js +17 -13
  30. package/dist/ui/components/dialog.js.map +1 -1
  31. package/dist/ui/full.client.js +6 -7
  32. package/dist/ui/full.client.js.map +1 -1
  33. package/dist/ui/full.d.ts.map +1 -1
  34. package/dist/ui/full.js +8 -4
  35. package/dist/ui/full.js.map +1 -1
  36. package/dist/ui/operation/client.js +7 -8
  37. package/dist/ui/operation/client.js.map +1 -1
  38. package/dist/ui/operation/index.js +42 -19
  39. package/dist/ui/operation/index.js.map +1 -1
  40. package/dist/ui/operation/request-tabs.d.ts.map +1 -1
  41. package/dist/ui/operation/request-tabs.js +9 -8
  42. package/dist/ui/operation/request-tabs.js.map +1 -1
  43. package/dist/ui/operation/response-tabs.d.ts +1 -1
  44. package/dist/ui/operation/response-tabs.d.ts.map +1 -1
  45. package/dist/ui/operation/response-tabs.js +13 -12
  46. package/dist/ui/operation/response-tabs.js.map +1 -1
  47. package/dist/ui/operation/usage-tabs/client.js +4 -5
  48. package/dist/ui/operation/usage-tabs/client.js.map +1 -1
  49. package/dist/ui/schema/client.d.ts.map +1 -1
  50. package/dist/ui/schema/client.js +32 -21
  51. package/dist/ui/schema/client.js.map +1 -1
  52. package/dist/ui/schema/index.d.ts +1 -1
  53. package/dist/ui/schema/index.d.ts.map +1 -1
  54. package/dist/ui/schema/index.js +11 -10
  55. package/dist/ui/schema/index.js.map +1 -1
  56. package/dist/utils/process-document.d.ts +1 -1
  57. package/dist/utils/process-document.js +19 -15
  58. package/dist/utils/process-document.js.map +1 -1
  59. 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" }) : "Send"
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: "Authorization",
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: "Header",
195
- cookie: "Cookies",
196
- query: "Query",
197
- path: "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
- }, [parameters, renderParameterField]), body && /* @__PURE__ */ jsx(CollapsiblePanel, {
214
- title: "Body",
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: "Close JSON Editor"
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: "Open JSON Editor"
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: "Access Token"
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: "Authorize"
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: "Authorization (header)",
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: "Authorization (header)",
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: "OpenID Connect is not supported at the moment, you can still set an access token here."
361
+ children: t.openIdUnsupported
353
362
  })] })
354
363
  });
355
364
  }
356
365
  return transform ? transform(result) : result;
357
- }, [securities, transform]);
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 statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);
407
- const { shikiOptions } = useApiContext();
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: "Close"
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(DynamicCodeBlock, {
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: "Show Property" })
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": "Remove Item",
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: "Enter Property Name",
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: "New"
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: "Selected"
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: "Upload"
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: "Select" })
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: "Unset"
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: "Unset"
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: "Enter value",
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": "Remove Item",
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" }), "New Item"]
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":"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"}