fumadocs-openapi 11.4.3 → 12.0.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 (119) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/css/preset.css +0 -1
  3. package/dist/_virtual/_rolldown/runtime.js +10 -1
  4. package/dist/generate-file.d.ts +2 -2
  5. package/dist/generate-file.js +1 -1
  6. package/dist/i18n.d.ts +6 -8
  7. package/dist/i18n.js +2 -17
  8. package/dist/index.browser.d.ts +13 -0
  9. package/dist/index.browser.js +11 -0
  10. package/dist/index.d.ts +5 -2
  11. package/dist/index.js +3 -1
  12. package/dist/operation.d.ts +133 -0
  13. package/dist/operation.js +296 -0
  14. package/dist/packages/shared-api/dist/.translations/index.d.ts +29 -0
  15. package/dist/packages/shared-api/dist/.translations/keys.js +28 -0
  16. package/dist/packages/shared-api/dist/auto-anchor/client.js +20 -0
  17. package/dist/packages/shared-api/dist/auto-anchor/index.js +17 -0
  18. package/dist/packages/shared-api/dist/codegen.d.ts +42 -0
  19. package/dist/packages/shared-api/dist/codegen.js +35 -0
  20. package/dist/packages/shared-api/dist/components/accordion.js +71 -0
  21. package/dist/packages/shared-api/dist/components/badge.js +21 -0
  22. package/dist/packages/shared-api/dist/components/collapsible.d.ts +7 -0
  23. package/dist/packages/shared-api/dist/components/collapsible.js +16 -0
  24. package/dist/packages/shared-api/dist/components/defaults.d.ts +20 -0
  25. package/dist/packages/shared-api/dist/components/defaults.js +70 -0
  26. package/dist/packages/shared-api/dist/components/dialog.js +55 -0
  27. package/dist/packages/shared-api/dist/components/input.js +14 -0
  28. package/dist/packages/shared-api/dist/components/label.js +11 -0
  29. package/dist/packages/shared-api/dist/components/playground/inputs.js +439 -0
  30. package/dist/packages/shared-api/dist/components/playground/schema.js +112 -0
  31. package/dist/packages/shared-api/dist/components/popover.js +23 -0
  32. package/dist/packages/shared-api/dist/components/schema/client.d.ts +12 -0
  33. package/dist/packages/shared-api/dist/components/schema/client.js +508 -0
  34. package/dist/packages/shared-api/dist/components/schema/index.d.ts +9 -0
  35. package/dist/packages/shared-api/dist/components/schema/index.js +28 -0
  36. package/dist/packages/shared-api/dist/components/select-tab.js +54 -0
  37. package/dist/packages/shared-api/dist/components/select.js +70 -0
  38. package/dist/packages/shared-api/dist/components/spinner.js +14 -0
  39. package/dist/packages/shared-api/dist/i18n.d.ts +3 -0
  40. package/dist/packages/shared-api/dist/i18n.js +7 -0
  41. package/dist/packages/shared-api/dist/utils/cn.js +2 -0
  42. package/dist/packages/shared-api/dist/utils/id-to-title.js +12 -0
  43. package/dist/packages/shared-api/dist/utils/is-plain-object.js +8 -0
  44. package/dist/packages/shared-api/dist/utils/merge-refs.js +11 -0
  45. package/dist/packages/shared-api/dist/utils/url.js +13 -0
  46. package/dist/{utils → packages/shared-api/dist/utils}/use-query.js +2 -1
  47. package/dist/packages/shared-api/dist/utils/use-server-store.js +56 -0
  48. package/dist/playground/auth.d.ts +37 -0
  49. package/dist/playground/auth.js +216 -21
  50. package/dist/playground/fetcher.d.ts +11 -1
  51. package/dist/playground/index.d.ts +3 -0
  52. package/dist/playground/index.js +3 -0
  53. package/dist/requests/generators/index.d.ts +4 -4
  54. package/dist/requests/generators/index.js +2 -2
  55. package/dist/requests/index.d.ts +4 -0
  56. package/dist/requests/index.js +3 -0
  57. package/dist/requests/media/adapter.d.ts +1 -0
  58. package/dist/requests/media/encode.d.ts +7 -2
  59. package/dist/requests/media/resolve-adapter.d.ts +20 -0
  60. package/dist/server/index.d.ts +4 -7
  61. package/dist/server/index.js +1 -7
  62. package/dist/types.d.ts +0 -14
  63. package/dist/ui/base.d.ts +3 -2
  64. package/dist/ui/base.js +15 -166
  65. package/dist/ui/components/codeblock.js +3 -10
  66. package/dist/ui/components/heading.js +10 -19
  67. package/dist/ui/components/markdown.js +4 -6
  68. package/dist/ui/components/method-label.js +2 -17
  69. package/dist/ui/components/schema.js +28 -0
  70. package/dist/ui/index.d.ts +7 -198
  71. package/dist/ui/index.js +1 -3
  72. package/dist/ui/operation/index.js +142 -229
  73. package/dist/ui/operation/request-tabs.js +15 -23
  74. package/dist/ui/operation/response-tabs.js +9 -53
  75. package/dist/ui/operation/usage-tabs.js +35 -93
  76. package/dist/{playground → ui/playground}/client.d.ts +10 -21
  77. package/dist/ui/playground/client.js +432 -0
  78. package/dist/{playground → ui/playground}/components/oauth-dialog.js +26 -91
  79. package/dist/{playground → ui/playground}/components/result-display.d.ts +2 -2
  80. package/dist/{playground → ui/playground}/components/result-display.js +7 -7
  81. package/dist/{playground → ui/playground}/components/server-select.js +12 -13
  82. package/dist/{playground → ui/playground}/status-info.js +2 -2
  83. package/dist/{scalar → ui/scalar}/client.js +7 -5
  84. package/dist/{scalar → ui/scalar}/index.d.ts +2 -2
  85. package/dist/{scalar → ui/scalar}/index.js +3 -7
  86. package/dist/utils/create-page.d.ts +216 -0
  87. package/dist/utils/create-page.js +221 -0
  88. package/dist/utils/document/dereference.d.ts +2 -2
  89. package/dist/utils/document/dereference.js +8 -3
  90. package/dist/utils/document/load.js +2 -2
  91. package/dist/utils/get-example-requests.js +11 -13
  92. package/dist/utils/pages/builder.d.ts +15 -2
  93. package/dist/utils/pages/builder.js +6 -6
  94. package/dist/utils/pages/preset-auto.d.ts +1 -1
  95. package/dist/utils/pages/preset-auto.js +3 -3
  96. package/dist/utils/pages/to-static-data.js +4 -4
  97. package/dist/utils/pages/to-text.d.ts +1 -1
  98. package/dist/utils/pages/to-text.js +3 -5
  99. package/dist/utils/schema.js +5 -5
  100. package/dist/utils/use-server.d.ts +24 -0
  101. package/dist/utils/use-server.js +57 -0
  102. package/package.json +28 -20
  103. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/2.0-to-3.0/upgrade-from-two-to-three.js +0 -508
  104. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/3.0-to-3.1/upgrade-from-three-to-three-one.js +0 -152
  105. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/3.1-to-3.2/upgrade-from-three-one-to-three-two.js +0 -61
  106. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/helpers/traverse.js +0 -25
  107. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/upgrade.js +0 -15
  108. package/dist/playground/client.js +0 -574
  109. package/dist/ui/contexts/api.d.ts +0 -17
  110. package/dist/ui/contexts/api.js +0 -84
  111. package/dist/ui/create-client.d.ts +0 -9
  112. package/dist/ui/create-client.js +0 -7
  113. package/dist/ui/operation/context.d.ts +0 -15
  114. package/dist/ui/operation/context.js +0 -48
  115. package/dist/ui/operation/request-tabs.d.ts +0 -12
  116. package/dist/ui/operation/response-tabs.d.ts +0 -30
  117. package/dist/utils/get-example-requests.d.ts +0 -11
  118. package/dist/utils/schema.d.ts +0 -3
  119. package/dist/utils/storage-key.js +0 -15
@@ -1,68 +1,24 @@
1
1
  "use client";
2
- import { getPreferredType } from "../../utils/schema.js";
3
- import { useRenderContext } from "../contexts/api.js";
4
- import { ClientCodeBlock } from "../components/codeblock.js";
2
+ import { useRenderContext } from "../../utils/create-page.js";
3
+ import { useResponseExamples } from "../../operation.js";
4
+ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../../packages/shared-api/dist/components/accordion.js";
5
5
  import { Markdown } from "../components/markdown.js";
6
- import { getRaw } from "@scalar/json-magic/magic-proxy";
7
- import { useMemo } from "react";
8
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ import { ClientCodeBlock } from "../components/codeblock.js";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
8
  import { useTranslations } from "@fuma-translate/react";
10
- import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "@fumadocs/api-docs/components/accordion";
11
9
  import { Tab, Tabs } from "fumadocs-ui/components/tabs";
12
- import { sample } from "@fumadocs/api-docs/schema/sample";
13
10
  //#region src/ui/operation/response-tabs.tsx
14
- function ResponseTabs({ operation }) {
11
+ function ResponseTabs() {
15
12
  const ctx = useRenderContext();
16
- const { resolve } = ctx.schema;
17
- const t = useTranslations({ note: "operation page" });
18
- const tabs = useMemo(() => {
19
- const tabs = [];
20
- if (!operation.responses) return tabs;
21
- for (const [code, item] of Object.entries(operation.responses)) {
22
- const response = resolve(item);
23
- const media = response.content ? getPreferredType(response.content) : null;
24
- const responseOfType = media ? resolve(response.content?.[media]) : null;
25
- const tab = {
26
- code,
27
- response,
28
- mediaType: media
29
- };
30
- if (responseOfType?.examples) {
31
- tab.examples ??= [];
32
- for (const [key, item] of Object.entries(responseOfType.examples)) {
33
- const example = resolve(item);
34
- tab.examples.push({
35
- label: example?.summary ?? t("Example {key}", { variables: { key } }),
36
- sample: getRaw(example.value),
37
- description: example?.description
38
- });
39
- }
40
- } else if (responseOfType?.example || responseOfType?.schema) {
41
- tab.examples ??= [];
42
- tab.examples.push({
43
- label: t("Example"),
44
- sample: getRaw(responseOfType.example) ?? sample(responseOfType.schema)
45
- });
46
- }
47
- tabs.push(tab);
48
- }
49
- return tabs;
50
- }, [
51
- operation.responses,
52
- resolve,
53
- t
54
- ]);
13
+ const tabs = useResponseExamples();
55
14
  if (tabs.length === 0) return null;
56
- const { renderResponseTabs = renderResponseTabsDefault } = ctx.content ?? {};
57
- return renderResponseTabs({ tabs }, ctx);
58
- }
59
- function renderResponseTabsDefault({ tabs }) {
15
+ if (ctx.content?.renderResponseTabs) return ctx.content.renderResponseTabs({ tabs }, ctx);
60
16
  return /* @__PURE__ */ jsx(ResponseTabsDefaultContent, { tabs });
61
17
  }
62
18
  function ResponseTabsDefaultContent({ tabs }) {
63
19
  const t = useTranslations({ note: "operation page" });
64
20
  function renderExampleContent(example) {
65
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [example.description && /* @__PURE__ */ jsx(Markdown, { md: example.description }), /* @__PURE__ */ jsx(ClientCodeBlock, {
21
+ return /* @__PURE__ */ jsxs(Fragment, { children: [example.description && /* @__PURE__ */ jsx(Markdown, { md: example.description }), /* @__PURE__ */ jsx(ClientCodeBlock, {
66
22
  lang: "json",
67
23
  code: JSON.stringify(example.sample, null, 2)
68
24
  })] });
@@ -1,38 +1,26 @@
1
1
  "use client";
2
- import { useRenderContext, useServerContext } from "../contexts/api.js";
2
+ import { useRenderContext } from "../../utils/create-page.js";
3
+ import { useCodeUsage, useExampleRequests, useOperation } from "../../operation.js";
4
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../packages/shared-api/dist/components/select.js";
3
5
  import { ClientCodeBlock } from "../components/codeblock.js";
4
- import { createCodeUsageGeneratorRegistry, pathnameFromRequest } from "../../requests/generators/index.js";
5
- import { useOperationContext } from "./context.js";
6
6
  import { ResponseTabs } from "./response-tabs.js";
7
- import { useEffect, useMemo, useState } from "react";
8
7
  import { jsx, jsxs } from "react/jsx-runtime";
9
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@fumadocs/api-docs/components/select";
10
- import { joinURL, resolveServerUrl } from "@fumadocs/api-docs/utils/url";
11
8
  import { CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger } from "fumadocs-ui/components/codeblock";
12
9
  //#region src/ui/operation/usage-tabs.tsx
13
- function UsageTabs({ path, method, operation, pathItem }) {
10
+ function UsageTabs() {
14
11
  const ctx = useRenderContext();
15
- let { renderAPIExampleUsageTabs, renderAPIExampleLayout } = ctx.content ?? {};
16
- renderAPIExampleLayout ??= (slots) => {
17
- return /* @__PURE__ */ jsxs("div", {
18
- className: "prose-no-margin",
19
- children: [
20
- slots.selector,
21
- slots.usageTabs,
22
- slots.responseTabs
23
- ]
24
- });
25
- };
26
- renderAPIExampleUsageTabs ??= (registry) => {
27
- const map = Array.from(registry.map().entries());
28
- if (map.length === 0) return null;
29
- return /* @__PURE__ */ jsxs(CodeBlockTabs, {
12
+ const { operation, codeUsages } = useOperation();
13
+ let usageTabs;
14
+ if (ctx.content?.renderAPIExampleUsageTabs) usageTabs = ctx.content.renderAPIExampleUsageTabs(codeUsages, ctx);
15
+ else {
16
+ const items = Array.from(codeUsages.map());
17
+ usageTabs = items.length > 0 && /* @__PURE__ */ jsxs(CodeBlockTabs, {
30
18
  groupId: "fumadocs_openapi_requests",
31
- defaultValue: map[0][0],
32
- children: [/* @__PURE__ */ jsx(CodeBlockTabsList, { children: map.map(([id, item]) => /* @__PURE__ */ jsx(CodeBlockTabsTrigger, {
19
+ defaultValue: items[0][0],
20
+ children: [/* @__PURE__ */ jsx(CodeBlockTabsList, { children: items.map(([id, item]) => /* @__PURE__ */ jsx(CodeBlockTabsTrigger, {
33
21
  value: id,
34
22
  children: item.label ?? item.lang
35
- }, id)) }), map.map(([id, item]) => /* @__PURE__ */ jsx(CodeBlockTab, {
23
+ }, id)) }), items.map(([id, item]) => /* @__PURE__ */ jsx(CodeBlockTab, {
36
24
  value: id,
37
25
  children: /* @__PURE__ */ jsx(UsageTab, {
38
26
  id,
@@ -40,38 +28,24 @@ function UsageTabs({ path, method, operation, pathItem }) {
40
28
  })
41
29
  }, id))]
42
30
  });
43
- };
44
- const registry = useMemo(() => {
45
- const registry = createCodeUsageGeneratorRegistry(ctx.codeUsages);
46
- if (ctx.generateCodeSamples) for (const gen of ctx.generateCodeSamples({
47
- path,
48
- operation,
49
- method,
50
- pathItem
51
- })) registry.addInline(gen);
52
- if (operation["x-codeSamples"]) for (const sample of operation["x-codeSamples"]) registry.addInline(sample);
53
- return registry;
54
- }, [
55
- ctx,
56
- path,
57
- operation,
58
- method,
59
- pathItem
60
- ]);
61
- return renderAPIExampleLayout({
31
+ }
32
+ const slots = {
62
33
  selector: operation["x-exclusiveCodeSample"] ? null : /* @__PURE__ */ jsx(UsageTabsSelector, {}),
63
- usageTabs: renderAPIExampleUsageTabs(registry, ctx),
64
- responseTabs: /* @__PURE__ */ jsx(ResponseTabs, { operation })
65
- }, ctx);
34
+ usageTabs,
35
+ responseTabs: /* @__PURE__ */ jsx(ResponseTabs, {})
36
+ };
37
+ if (ctx.content?.renderAPIExampleLayout) return ctx.content.renderAPIExampleLayout(slots, ctx);
38
+ return /* @__PURE__ */ jsxs("div", {
39
+ className: "prose-no-margin",
40
+ children: [
41
+ slots.selector,
42
+ slots.usageTabs,
43
+ slots.responseTabs
44
+ ]
45
+ });
66
46
  }
67
47
  function UsageTabsSelector() {
68
- const { example: key, setExample: setKey, examples } = useOperationContext();
69
- const { APIExampleSelector: Override } = useRenderContext().operation ?? {};
70
- if (Override) return /* @__PURE__ */ jsx(Override, {
71
- items: examples,
72
- value: key,
73
- onValueChange: setKey
74
- });
48
+ const { items, selected, select } = useExampleRequests();
75
49
  function renderItem(item) {
76
50
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
77
51
  className: "font-medium text-sm",
@@ -81,58 +55,26 @@ function UsageTabsSelector() {
81
55
  children: item.description
82
56
  })] });
83
57
  }
84
- if (examples.length === 1) return null;
85
- const items = examples.map((item) => ({
58
+ if (items.length === 1) return null;
59
+ const options = items.map((item) => ({
86
60
  value: item.id,
87
61
  label: renderItem(item)
88
62
  }));
89
63
  return /* @__PURE__ */ jsxs(Select, {
90
- items,
91
- value: key,
92
- onValueChange: (v) => v !== null && setKey(v),
64
+ items: options,
65
+ value: selected,
66
+ onValueChange: (v) => v !== null && select(v),
93
67
  children: [/* @__PURE__ */ jsx(SelectTrigger, {
94
68
  className: "not-prose mb-2",
95
69
  children: /* @__PURE__ */ jsx(SelectValue, {})
96
- }), /* @__PURE__ */ jsx(SelectContent, { children: items.map((item) => /* @__PURE__ */ jsx(SelectItem, {
70
+ }), /* @__PURE__ */ jsx(SelectContent, { children: options.map((item) => /* @__PURE__ */ jsx(SelectItem, {
97
71
  value: item.value,
98
72
  children: item.label
99
73
  }, item.value)) })]
100
74
  });
101
75
  }
102
76
  function UsageTab({ id, lang }) {
103
- const { mediaAdapters, codeUsages } = useRenderContext();
104
- const { examples, example: selectedExampleId, route, addListener, removeListener } = useOperationContext();
105
- const { server } = useServerContext();
106
- const codegen = codeUsages.get(id);
107
- const [mounted, setMounted] = useState(false);
108
- const [data, setData] = useState(() => examples.find((example) => example.id === selectedExampleId)?.encoded);
109
- useEffect(() => {
110
- const listener = (_, encoded) => setData(encoded);
111
- addListener(listener);
112
- setMounted(true);
113
- return () => {
114
- removeListener(listener);
115
- };
116
- }, [addListener, removeListener]);
117
- const code = useMemo(() => {
118
- if (!data) return;
119
- const url = joinURL(server && mounted ? new URL(resolveServerUrl(server.url, server.variables), window.location.origin).href : "https://example.com", pathnameFromRequest(route, data));
120
- if (!codegen) return;
121
- return codegen.generate({
122
- ...data,
123
- url
124
- }, {
125
- mediaAdapters,
126
- custom: null
127
- });
128
- }, [
129
- data,
130
- server,
131
- route,
132
- mounted,
133
- codegen,
134
- mediaAdapters
135
- ]);
77
+ const code = useCodeUsage(id);
136
78
  if (!code) return null;
137
79
  return /* @__PURE__ */ jsx(ClientCodeBlock, {
138
80
  lang,
@@ -1,11 +1,12 @@
1
- import { BrowserFetcherOptions } from "./fetcher.js";
1
+ import { ParameterObject } from "../../types.js";
2
+ import { BrowserFetcherOptions } from "../../playground/fetcher.js";
2
3
  import { DefaultResultDisplay, ResultDisplayProps } from "./components/result-display.js";
3
- import { ParsedSchema } from "../utils/schema.js";
4
- import { HttpMethods, OperationObject, ParameterObject, PathItemObject } from "../types.js";
4
+ import { Collapsible } from "../../packages/shared-api/dist/components/collapsible.js";
5
+ import { AuthField } from "../../playground/auth.js";
5
6
  import { ComponentProps, FC, ReactNode } from "react";
6
- import { Collapsible } from "@fumadocs/api-docs/components/collapsible";
7
+ import { JsonSchema } from "@fumadocs/json-schema";
7
8
  import { FieldKey } from "@fumari/stf";
8
- //#region src/playground/client.d.ts
9
+ //#region src/ui/playground/client.d.ts
9
10
  export interface FormValues extends Record<string, unknown> {
10
11
  path: Record<string, unknown>;
11
12
  query: Record<string, unknown>;
@@ -13,11 +14,7 @@ export interface FormValues extends Record<string, unknown> {
13
14
  cookie: Record<string, unknown>;
14
15
  body: unknown;
15
16
  }
16
- export interface PlaygroundClientProps extends Omit<ComponentProps<'form'>, 'method'> {
17
- route: string;
18
- method: HttpMethods;
19
- operation: OperationObject;
20
- pathItem: PathItemObject;
17
+ export interface PlaygroundClientProps extends Omit<ComponentProps<'form'>, 'method'>, PlaygroundClientOptions {
21
18
  writeOnly: boolean;
22
19
  readOnly: boolean;
23
20
  }
@@ -39,7 +36,7 @@ export interface PlaygroundClientOptions {
39
36
  * render the parameter inputs of API endpoint.
40
37
  *
41
38
  * for updating values, use:
42
- * - the `Custom.useController()` from `fumadocs-openapi/playground/client`.
39
+ * - the `Custom.useController()` from `fumadocs-openapi/ui/playground/client`.
43
40
  *
44
41
  * Recommended types packages: `json-schema-typed`.
45
42
  */
@@ -52,20 +49,12 @@ export interface PlaygroundClientOptions {
52
49
  renderBodyField?: (fieldName: 'body', info: RequestBodyInfo) => ReactNode;
53
50
  }
54
51
  interface RequestBodyInfo {
55
- schema: ParsedSchema;
52
+ schema: JsonSchema;
56
53
  mediaType: string;
57
54
  }
58
- export default function PlaygroundClient({ route, method, operation, pathItem, writeOnly, readOnly, ...rest }: PlaygroundClientProps): import("react").JSX.Element;
55
+ export default function PlaygroundClient({ writeOnly, readOnly, transformAuthInputs, fetchOptions, components, renderParameterField, renderBodyField, ...rest }: PlaygroundClientProps): import("react").JSX.Element;
59
56
  declare const ParamTypes: readonly ['path', 'header', 'cookie', 'query'];
60
57
  type ParamType = (typeof ParamTypes)[number];
61
- export interface AuthField {
62
- fieldName: FieldKey;
63
- schemeId: string;
64
- storageKey: string;
65
- defaultValue: unknown;
66
- children: ReactNode;
67
- mapOutput?: (values: unknown) => unknown;
68
- }
69
58
  export declare function DefaultCollapsiblePanel({ title, children, ...props }: CollapsiblePanelProps): import("react").JSX.Element;
70
59
  export declare const Custom: {
71
60
  useController(fieldName: FieldKey, options?: {