fumadocs-openapi 11.4.2 → 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 (125) 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/csharp.js +0 -1
  54. package/dist/requests/generators/go.js +0 -1
  55. package/dist/requests/generators/index.d.ts +4 -4
  56. package/dist/requests/generators/index.js +2 -2
  57. package/dist/requests/generators/java.js +0 -1
  58. package/dist/requests/generators/javascript.js +0 -1
  59. package/dist/requests/generators/python.js +0 -1
  60. package/dist/requests/generators/rust.js +0 -1
  61. package/dist/requests/index.d.ts +4 -0
  62. package/dist/requests/index.js +3 -0
  63. package/dist/requests/media/adapter.d.ts +1 -0
  64. package/dist/requests/media/encode.d.ts +7 -2
  65. package/dist/requests/media/resolve-adapter.d.ts +20 -0
  66. package/dist/server/index.d.ts +4 -7
  67. package/dist/server/index.js +1 -7
  68. package/dist/types.d.ts +0 -14
  69. package/dist/ui/base.d.ts +3 -2
  70. package/dist/ui/base.js +15 -166
  71. package/dist/ui/components/codeblock.js +3 -10
  72. package/dist/ui/components/heading.js +10 -19
  73. package/dist/ui/components/markdown.js +4 -6
  74. package/dist/ui/components/method-label.js +2 -17
  75. package/dist/ui/components/schema.js +28 -0
  76. package/dist/ui/index.d.ts +7 -198
  77. package/dist/ui/index.js +1 -3
  78. package/dist/ui/operation/index.js +143 -231
  79. package/dist/ui/operation/request-tabs.js +15 -23
  80. package/dist/ui/operation/response-tabs.js +9 -53
  81. package/dist/ui/operation/usage-tabs.js +35 -93
  82. package/dist/{playground → ui/playground}/client.d.ts +10 -21
  83. package/dist/ui/playground/client.js +432 -0
  84. package/dist/{playground → ui/playground}/components/oauth-dialog.js +27 -92
  85. package/dist/{playground → ui/playground}/components/result-display.d.ts +2 -2
  86. package/dist/{playground → ui/playground}/components/result-display.js +7 -7
  87. package/dist/{playground → ui/playground}/components/server-select.js +12 -13
  88. package/dist/{playground → ui/playground}/status-info.js +2 -2
  89. package/dist/{scalar → ui/scalar}/client.js +8 -6
  90. package/dist/{scalar → ui/scalar}/index.d.ts +2 -2
  91. package/dist/{scalar → ui/scalar}/index.js +3 -7
  92. package/dist/utils/create-page.d.ts +216 -0
  93. package/dist/utils/create-page.js +221 -0
  94. package/dist/utils/document/dereference.d.ts +2 -2
  95. package/dist/utils/document/dereference.js +8 -3
  96. package/dist/utils/document/load.js +2 -2
  97. package/dist/utils/get-example-requests.js +11 -13
  98. package/dist/utils/pages/builder.d.ts +15 -2
  99. package/dist/utils/pages/builder.js +6 -6
  100. package/dist/utils/pages/preset-auto.d.ts +1 -1
  101. package/dist/utils/pages/preset-auto.js +3 -3
  102. package/dist/utils/pages/to-static-data.js +4 -4
  103. package/dist/utils/pages/to-text.d.ts +1 -1
  104. package/dist/utils/pages/to-text.js +3 -5
  105. package/dist/utils/schema.js +5 -5
  106. package/dist/utils/use-server.d.ts +24 -0
  107. package/dist/utils/use-server.js +57 -0
  108. package/package.json +31 -20
  109. 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
  110. 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
  111. 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
  112. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/helpers/traverse.js +0 -25
  113. package/dist/node_modules/.pnpm/@scalar_openapi-upgrader@0.2.15/node_modules/@scalar/openapi-upgrader/dist/upgrade.js +0 -15
  114. package/dist/playground/client.js +0 -574
  115. package/dist/ui/contexts/api.d.ts +0 -17
  116. package/dist/ui/contexts/api.js +0 -84
  117. package/dist/ui/create-client.d.ts +0 -9
  118. package/dist/ui/create-client.js +0 -7
  119. package/dist/ui/operation/context.d.ts +0 -15
  120. package/dist/ui/operation/context.js +0 -48
  121. package/dist/ui/operation/request-tabs.d.ts +0 -12
  122. package/dist/ui/operation/response-tabs.d.ts +0 -30
  123. package/dist/utils/get-example-requests.d.ts +0 -11
  124. package/dist/utils/schema.d.ts +0 -3
  125. package/dist/utils/storage-key.js +0 -15
@@ -1,62 +1,48 @@
1
1
  "use client";
2
- import { methodKeys } from "../../utils/schema.js";
3
- import { ServerProvider, useRenderContext } from "../contexts/api.js";
4
- import { cn } from "../../utils/cn.js";
5
- import { Badge, MethodLabel } from "../components/method-label.js";
6
- import { isMediaTypeSupported } from "../../requests/media/resolve-adapter.js";
7
- import { OperationProvider } from "./context.js";
8
- import PlaygroundClient from "../../playground/client.js";
9
- import "../../requests/media/adapter.js";
2
+ import { useOpenAPI, useRenderContext, useTypeScriptDefinitions } from "../../utils/create-page.js";
3
+ import { OperationProvider, useOperation } from "../../operation.js";
4
+ import { AnchorSection } from "../../packages/shared-api/dist/auto-anchor/client.js";
5
+ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../../packages/shared-api/dist/components/accordion.js";
10
6
  import { Markdown } from "../components/markdown.js";
11
7
  import { UsageTabs } from "./usage-tabs.js";
8
+ import { Badge } from "../../packages/shared-api/dist/components/badge.js";
9
+ import { MethodLabel } from "../components/method-label.js";
10
+ import { SchemaUI } from "../components/schema.js";
12
11
  import { RequestTabs } from "./request-tabs.js";
13
- import { getExampleRequests } from "../../utils/get-example-requests.js";
12
+ import { cn } from "../../utils/cn.js";
13
+ import { SelectTab, SelectTabTrigger, SelectTabs } from "../../packages/shared-api/dist/components/select-tab.js";
14
14
  import { Heading } from "../components/heading.js";
15
- import { idToTitle } from "@fumadocs/api-docs/utils/id-to-title";
16
- import { Fragment, use, useMemo } from "react";
15
+ import PlaygroundClient from "../playground/client.js";
16
+ import { Fragment } from "react";
17
17
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
18
- import { Check, Copy } from "lucide-react";
19
18
  import { useTranslations } from "@fuma-translate/react";
19
+ import { Check, Copy } from "lucide-react";
20
20
  import { buttonVariants } from "fumadocs-ui/components/ui/button";
21
- import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "@fumadocs/api-docs/components/accordion";
22
- import { SelectTab, SelectTabTrigger, SelectTabs } from "@fumadocs/api-docs/components/select-tab";
23
- import { Callout } from "fumadocs-ui/components/callout";
24
- import { AnchorSection } from "@fumadocs/api-docs/auto-anchor/client";
25
21
  import { useCopyButton } from "fumadocs-ui/utils/use-copy-button";
22
+ import { Callout } from "fumadocs-ui/components/callout";
26
23
  //#region src/ui/operation/index.tsx
27
- const paramTypeKeys = [
28
- "path",
29
- "query",
30
- "header",
31
- "cookie"
32
- ];
33
- function Operation({ type = "operation", path, operation, pathItem, method, showTitle, showDescription, headingLevel = 2 }) {
24
+ function Operation({ type, path, method, operation, pathItem, ...props }) {
25
+ return /* @__PURE__ */ jsx(OperationProvider, {
26
+ type,
27
+ path,
28
+ method,
29
+ operation,
30
+ pathItem,
31
+ children: /* @__PURE__ */ jsx(OperationContent, { ...props })
32
+ });
33
+ }
34
+ function OperationContent({ showTitle, showDescription, headingLevel = 2 }) {
34
35
  const t = useTranslations({ note: "operation page" });
36
+ const { resolve } = useOpenAPI().doc;
35
37
  const ctx = useRenderContext();
36
- const { schema: { dereferenced, resolve } } = ctx;
37
- const body = resolve(operation.requestBody);
38
+ const { type, path, method, operation, pathItem, title, description, requestBody, parameters, security, responses, callbacks } = useOperation();
38
39
  let headNode = null;
39
- const operationDescription = operation.description ?? pathItem.description;
40
- const descriptionNode = showDescription && operationDescription && /* @__PURE__ */ jsx(Markdown, { md: operationDescription });
40
+ const descriptionNode = showDescription && description && /* @__PURE__ */ jsx(Markdown, { md: description });
41
41
  let bodyNode = null;
42
42
  let authNode = null;
43
43
  let responseNode = null;
44
44
  let callbacksNode = null;
45
- const exampleRequests = useMemo(() => getExampleRequests({
46
- path,
47
- operation,
48
- method,
49
- pathItem,
50
- ctx
51
- }), [
52
- ctx,
53
- operation,
54
- method,
55
- pathItem,
56
- path
57
- ]);
58
45
  if (showTitle) {
59
- const title = operation.summary || pathItem.summary || (operation.operationId ? idToTitle(operation.operationId) : path);
60
46
  headNode = /* @__PURE__ */ jsxs("div", {
61
47
  className: "flex gap-2 items-center justify-between",
62
48
  children: [/* @__PURE__ */ jsx(Heading, {
@@ -76,14 +62,14 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
76
62
  title: t("Deprecated"),
77
63
  className: "mt-0!"
78
64
  });
79
- const contentTypes = body?.content ? Object.entries(body.content) : null;
80
- if (contentTypes && contentTypes.length > 0) {
81
- const items = contentTypes.map(([type]) => ({
65
+ if (requestBody) {
66
+ const contentTypes = Object.entries(requestBody.content);
67
+ const items = contentTypes.map(([mediaType]) => ({
82
68
  label: /* @__PURE__ */ jsx("code", {
83
69
  className: "text-xs",
84
- children: type
70
+ children: mediaType
85
71
  }),
86
- value: type
72
+ value: mediaType
87
73
  }));
88
74
  bodyNode = /* @__PURE__ */ jsxs(SelectTabs, {
89
75
  defaultValue: items[0].value,
@@ -103,53 +89,41 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
103
89
  children: items[0].label
104
90
  })]
105
91
  }),
106
- body?.description && /* @__PURE__ */ jsx(Markdown, { md: body.description }),
107
- contentTypes.map(([type, content]) => {
108
- if (!isMediaTypeSupported(type, ctx.mediaAdapters)) throw new Error(`Media type ${type} is not supported (in ${path})`);
109
- return /* @__PURE__ */ jsx(SelectTab, {
110
- anchorSegments: ["request-body", type],
111
- value: type,
112
- children: /* @__PURE__ */ jsx(RequestBodyContentItem, {
113
- content: resolve(content),
114
- operation,
115
- method
116
- })
117
- }, type);
118
- })
92
+ requestBody.description && /* @__PURE__ */ jsx(Markdown, { md: requestBody.description }),
93
+ contentTypes.map(([mediaType, content]) => /* @__PURE__ */ jsx(SelectTab, {
94
+ anchorSegments: ["request-body", mediaType],
95
+ value: mediaType,
96
+ children: /* @__PURE__ */ jsx(RequestBodyContentItem, {
97
+ content,
98
+ required: requestBody.required,
99
+ method
100
+ })
101
+ }, mediaType))
119
102
  ]
120
103
  });
121
104
  }
122
- if (operation.responses && ctx.showResponseSchema !== false) {
123
- const statuses = Object.keys(operation.responses);
124
- responseNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
125
- id: "response-body",
126
- depth: headingLevel,
127
- children: t("Response Body")
128
- }), /* @__PURE__ */ jsx(Accordions, {
129
- type: "multiple",
130
- children: statuses.map((status) => /* @__PURE__ */ jsx(ResponseAccordion, {
131
- status,
132
- operation
133
- }, status))
134
- })] });
135
- }
136
- const parameters = [...operation.parameters ?? [], ...pathItem.parameters ?? []].map((param) => resolve(param));
137
- const parameterNode = paramTypeKeys.map((type) => {
138
- const params = parameters.filter((param) => param.in === type);
139
- if (!params || params.length === 0) return;
140
- const parameterLabel = type === "path" ? t("Path Parameters") : type === "query" ? t("Query Parameters") : type === "header" ? t("Header Parameters") : t("Cookie Parameters");
105
+ if (responses.length > 0 && ctx.showResponseSchema !== false) responseNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
106
+ id: "response-body",
107
+ depth: headingLevel,
108
+ children: t("Response Body")
109
+ }), /* @__PURE__ */ jsx(Accordions, {
110
+ type: "multiple",
111
+ children: responses.map((item) => /* @__PURE__ */ jsx(ResponseAccordion, { item }, item.status))
112
+ })] });
113
+ const parameterNode = parameters.map(({ in: location, items }) => {
114
+ const parameterLabel = location === "path" ? t("Path Parameters") : location === "query" ? t("Query Parameters") : location === "header" ? t("Header Parameters") : t("Cookie Parameters");
141
115
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Heading, {
142
- id: `parameters-${type}`,
116
+ id: `parameters-${location}`,
143
117
  depth: headingLevel,
144
118
  children: parameterLabel
145
119
  }), /* @__PURE__ */ jsx(AnchorSection, {
146
- segments: ["parameters", type],
120
+ segments: ["parameters", location],
147
121
  children: /* @__PURE__ */ jsx("div", {
148
122
  className: "flex flex-col",
149
- children: params.map((param) => {
123
+ children: items.map((param) => {
150
124
  if (param.schema == null) return;
151
125
  const schema = resolve(param.schema);
152
- return /* @__PURE__ */ jsx(ctx.SchemaUI, {
126
+ return /* @__PURE__ */ jsx(SchemaUI, {
153
127
  client: {
154
128
  name: param.name,
155
129
  required: param.required
@@ -164,17 +138,15 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
164
138
  }, param.name);
165
139
  })
166
140
  })
167
- })] }, type);
141
+ })] }, location);
168
142
  });
169
- const securities = (operation.security ?? dereferenced.security ?? []).filter((v) => Object.keys(v).length > 0);
170
- if (type === "operation" && securities.length > 0) {
171
- const securitySchemes = dereferenced.components?.securitySchemes;
172
- const items = securities.map((security, i) => {
143
+ if (security.length > 0) {
144
+ const items = security.map((requirement, i) => {
173
145
  return {
174
146
  value: String(i),
175
147
  label: /* @__PURE__ */ jsx("div", {
176
148
  className: "flex flex-col text-xs min-w-0",
177
- children: Object.entries(security).map(([key, scopes]) => /* @__PURE__ */ jsxs("code", {
149
+ children: requirement.map(({ key, scopes }) => /* @__PURE__ */ jsxs("code", {
178
150
  className: "truncate",
179
151
  children: [
180
152
  /* @__PURE__ */ jsx("span", {
@@ -204,43 +176,22 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
204
176
  className: "not-prose",
205
177
  children: items[0].label
206
178
  })]
207
- }), securities.map((security, i) => /* @__PURE__ */ jsx(SelectTab, {
179
+ }), security.map((requirement, i) => /* @__PURE__ */ jsx(SelectTab, {
208
180
  value: items[i].value,
209
- children: Object.entries(security).map(([key, scopes]) => {
210
- const scheme = resolve(securitySchemes?.[key]);
211
- if (!scheme) return;
212
- return /* @__PURE__ */ jsx(AuthScheme, {
213
- scheme,
214
- scopes
215
- }, key);
216
- })
181
+ children: requirement.map(({ key, scopes, scheme }) => scheme && /* @__PURE__ */ jsx(AuthScheme, {
182
+ scheme,
183
+ scopes
184
+ }, key))
217
185
  }, i))]
218
186
  });
219
187
  }
220
- const webhookCallbacks = [];
221
- for (const [name, item] of Object.entries(operation.callbacks ?? {})) {
222
- const callbacks = resolve(item);
223
- for (const [path, pathItem] of Object.entries(callbacks)) {
224
- const callback = resolve(pathItem);
225
- for (const method of methodKeys) {
226
- if (!callback[method]) continue;
227
- webhookCallbacks.push({
228
- name,
229
- path,
230
- method,
231
- callback,
232
- operation: callback[method]
233
- });
234
- }
235
- }
236
- }
237
- if (webhookCallbacks.length > 0) callbacksNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
188
+ if (callbacks.length > 0) callbacksNode = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Heading, {
238
189
  id: "callbacks",
239
190
  depth: headingLevel,
240
191
  children: t("Callbacks")
241
192
  }), /* @__PURE__ */ jsx(Accordions, {
242
193
  type: "multiple",
243
- children: webhookCallbacks.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, {
194
+ children: callbacks.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, {
244
195
  value: `${item.name}\0${item.path}\0${item.method}`,
245
196
  anchorSegments: [
246
197
  "callbacks",
@@ -267,51 +218,28 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
267
218
  path,
268
219
  headingLevel: headingLevel + 1,
269
220
  method: item.method,
270
- pathItem: item.callback,
221
+ pathItem: item.pathItem,
271
222
  operation: item.operation
272
223
  })
273
224
  }) })]
274
225
  }, i))
275
226
  })] });
276
- let { renderOperationLayout, renderWebhookLayout } = ctx.content ?? {};
277
227
  if (type === "operation") {
278
- renderOperationLayout ??= (slots) => {
279
- return /* @__PURE__ */ jsxs("div", {
280
- className: "flex flex-col gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
281
- children: [/* @__PURE__ */ jsxs("div", {
282
- className: "min-w-0 flex-1",
283
- children: [
284
- slots.header,
285
- slots.apiPlayground,
286
- slots.description,
287
- slots.authSchemes,
288
- slots.parameters,
289
- slots.body,
290
- slots.responses,
291
- slots.callbacks
292
- ]
293
- }), /* @__PURE__ */ jsx("div", {
294
- className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]",
295
- children: slots.apiExample
296
- })]
297
- });
298
- };
228
+ const playground = ctx.playground;
299
229
  let apiPlayground;
300
- if (ctx.playground?.enabled ?? true) apiPlayground = ctx.playground?.render ? ctx.playground.render({
301
- path,
302
- method,
303
- operation,
304
- pathItem,
305
- ctx
306
- }) : /* @__PURE__ */ jsx(PlaygroundClient, {
307
- operation,
308
- pathItem,
309
- route: path,
310
- method,
311
- writeOnly: true,
312
- readOnly: false
313
- });
314
- else apiPlayground = /* @__PURE__ */ jsxs("div", {
230
+ if (playground?.enabled ?? true) {
231
+ const { enabled: _, render, ...options } = playground ?? {};
232
+ apiPlayground = render ? render({
233
+ path,
234
+ method,
235
+ operation,
236
+ pathItem
237
+ }) : /* @__PURE__ */ jsx(PlaygroundClient, {
238
+ ...options,
239
+ writeOnly: true,
240
+ readOnly: false
241
+ });
242
+ } else apiPlayground = /* @__PURE__ */ jsxs("div", {
315
243
  className: "flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose",
316
244
  children: [/* @__PURE__ */ jsx(MethodLabel, {
317
245
  className: "text-xs",
@@ -321,7 +249,7 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
321
249
  children: path
322
250
  })]
323
251
  });
324
- let content = renderOperationLayout({
252
+ const slots = {
325
253
  header: headNode,
326
254
  description: descriptionNode,
327
255
  authSchemes: authNode,
@@ -330,37 +258,22 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
330
258
  parameters: parameterNode,
331
259
  responses: responseNode,
332
260
  apiPlayground,
333
- apiExample: /* @__PURE__ */ jsx(UsageTabs, {
334
- path,
335
- method,
336
- operation,
337
- pathItem
338
- })
339
- }, {
261
+ apiExample: /* @__PURE__ */ jsx(UsageTabs, {})
262
+ };
263
+ if (ctx.content?.renderOperationLayout) return ctx.content.renderOperationLayout(slots, {
340
264
  path,
341
265
  operation,
342
266
  method,
343
267
  pathItem,
344
268
  ctx
345
269
  });
346
- content = /* @__PURE__ */ jsx(OperationProvider, {
347
- defaultExampleId: operation["x-exclusiveCodeSample"] ?? operation["x-selectedCodeSample"],
348
- route: path,
349
- examples: exampleRequests,
350
- children: content
351
- });
352
- if (operation.servers || pathItem.servers) content = /* @__PURE__ */ jsx(ServerProvider, {
353
- servers: operation.servers ?? pathItem.servers,
354
- children: content
355
- });
356
- return content;
357
- } else {
358
- renderWebhookLayout ??= (slots) => /* @__PURE__ */ jsxs("div", {
359
- className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
270
+ return /* @__PURE__ */ jsxs("div", {
271
+ className: "flex flex-col gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
360
272
  children: [/* @__PURE__ */ jsxs("div", {
361
- className: "min-w-0 flex-1 prose-no-margin",
273
+ className: "min-w-0 flex-1",
362
274
  children: [
363
275
  slots.header,
276
+ slots.apiPlayground,
364
277
  slots.description,
365
278
  slots.authSchemes,
366
279
  slots.parameters,
@@ -370,58 +283,63 @@ function Operation({ type = "operation", path, operation, pathItem, method, show
370
283
  ]
371
284
  }), /* @__PURE__ */ jsx("div", {
372
285
  className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]",
373
- children: slots.requests
286
+ children: slots.apiExample
374
287
  })]
375
288
  });
376
- return renderWebhookLayout({
377
- header: headNode,
378
- description: descriptionNode,
379
- authSchemes: authNode,
380
- body: bodyNode,
381
- callbacks: callbacksNode,
382
- parameters: parameterNode,
383
- responses: responseNode,
384
- requests: /* @__PURE__ */ jsx(RequestTabs, {
385
- examples: exampleRequests,
386
- path,
387
- method,
388
- pathItem,
389
- operation
390
- })
391
- });
392
289
  }
290
+ const slots = {
291
+ header: headNode,
292
+ description: descriptionNode,
293
+ authSchemes: authNode,
294
+ body: bodyNode,
295
+ callbacks: callbacksNode,
296
+ parameters: parameterNode,
297
+ responses: responseNode,
298
+ requests: /* @__PURE__ */ jsx(RequestTabs, {})
299
+ };
300
+ if (ctx.content?.renderWebhookLayout) return ctx.content.renderWebhookLayout(slots);
301
+ return /* @__PURE__ */ jsxs("div", {
302
+ className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
303
+ children: [/* @__PURE__ */ jsxs("div", {
304
+ className: "min-w-0 flex-1 prose-no-margin",
305
+ children: [
306
+ slots.header,
307
+ slots.description,
308
+ slots.authSchemes,
309
+ slots.parameters,
310
+ slots.body,
311
+ slots.responses,
312
+ slots.callbacks
313
+ ]
314
+ }), /* @__PURE__ */ jsx("div", {
315
+ className: "@4xl:sticky @4xl:top-[calc(var(--fd-docs-row-1,2rem)+1rem)] @4xl:w-[400px]",
316
+ children: slots.requests
317
+ })]
318
+ });
393
319
  }
394
- function RequestBodyContentItem({ content, method, operation }) {
395
- const ctx = useRenderContext();
396
- let ts = useMemo(() => {
397
- if (!content.schema || !ctx.generateTypeScriptDefinitions) return;
398
- return ctx.generateTypeScriptDefinitions(content.schema, {
399
- name: "RequestBody",
400
- readOnly: false,
401
- writeOnly: true,
402
- ctx
403
- });
404
- }, [content.schema, ctx]);
405
- if (ts instanceof Promise) ts = use(ts);
320
+ function RequestBodyContentItem({ content, required, method }) {
321
+ const ts = useTypeScriptDefinitions(content.schema, {
322
+ name: "RequestBody",
323
+ readOnly: false,
324
+ writeOnly: true
325
+ });
406
326
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [ts && /* @__PURE__ */ jsx(CopyTypeScriptPanel, {
407
327
  name: "request body",
408
328
  code: ts,
409
329
  className: "my-4 last:mb-0"
410
- }), content.schema && /* @__PURE__ */ jsx(ctx.SchemaUI, {
330
+ }), content.schema && /* @__PURE__ */ jsx(SchemaUI, {
411
331
  client: {
412
332
  name: "body",
413
333
  as: "body",
414
- required: ctx.schema.resolve(operation.requestBody)?.required
334
+ required
415
335
  },
416
336
  root: content.schema,
417
337
  readOnly: method === "get",
418
338
  writeOnly: method !== "get"
419
339
  })] });
420
340
  }
421
- function ResponseAccordion({ status, operation }) {
422
- const { schema } = useRenderContext();
423
- const response = schema.resolve(operation.responses[status]);
424
- const contentTypes = response.content ? Object.entries(response.content) : [];
341
+ function ResponseAccordion({ item: { status, response, content } }) {
342
+ const contentTypes = Object.entries(content);
425
343
  const items = contentTypes.map(([key]) => ({
426
344
  label: /* @__PURE__ */ jsx("code", {
427
345
  className: "text-xs",
@@ -449,32 +367,26 @@ function ResponseAccordion({ status, operation }) {
449
367
  children: [response.description && /* @__PURE__ */ jsx("div", {
450
368
  className: "prose-no-margin mt-3 mb-2",
451
369
  children: /* @__PURE__ */ jsx(Markdown, { md: response.description })
452
- }), contentTypes.map(([type, item]) => /* @__PURE__ */ jsx(SelectTab, {
453
- value: type,
454
- anchorSegments: [type],
455
- children: /* @__PURE__ */ jsx(RepsonseAccordionItem, { item: schema.resolve(item) })
456
- }, type))]
370
+ }), contentTypes.map(([mediaType, media]) => /* @__PURE__ */ jsx(SelectTab, {
371
+ value: mediaType,
372
+ anchorSegments: [mediaType],
373
+ children: /* @__PURE__ */ jsx(ResponseAccordionItem, { item: media })
374
+ }, mediaType))]
457
375
  })]
458
376
  })
459
377
  });
460
378
  }
461
- function RepsonseAccordionItem({ item: { schema } }) {
462
- const ctx = useRenderContext();
463
- let ts = useMemo(() => {
464
- if (!schema || !ctx.generateTypeScriptDefinitions) return;
465
- return ctx.generateTypeScriptDefinitions(schema, {
466
- name: "ResponseBody",
467
- readOnly: true,
468
- writeOnly: false,
469
- ctx
470
- });
471
- }, [ctx, schema]);
472
- if (ts instanceof Promise) ts = use(ts);
379
+ function ResponseAccordionItem({ item: { schema } }) {
380
+ const ts = useTypeScriptDefinitions(schema, {
381
+ name: "ResponseBody",
382
+ readOnly: true,
383
+ writeOnly: false
384
+ });
473
385
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [ts && /* @__PURE__ */ jsx(CopyTypeScriptPanel, {
474
386
  name: "response body",
475
387
  code: ts,
476
388
  className: "mb-2"
477
- }), schema && /* @__PURE__ */ jsx(ctx.SchemaUI, {
389
+ }), schema && /* @__PURE__ */ jsx(SchemaUI, {
478
390
  client: {
479
391
  name: "response",
480
392
  as: "body"
@@ -562,7 +474,7 @@ function CopyTypeScriptPanel({ name, code, className }) {
562
474
  })] }), /* @__PURE__ */ jsxs("button", {
563
475
  onClick: onCopy,
564
476
  className: cn(buttonVariants({
565
- color: "secondary",
477
+ variant: "secondary",
566
478
  className: "p-2 gap-2",
567
479
  size: "sm"
568
480
  })),
@@ -1,32 +1,30 @@
1
1
  "use client";
2
- import { useRenderContext } from "../contexts/api.js";
2
+ import { useRenderContext } from "../../utils/create-page.js";
3
+ import { useExampleRequests, useOperation } from "../../operation.js";
4
+ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "../../packages/shared-api/dist/components/accordion.js";
5
+ import { Markdown } from "../components/markdown.js";
3
6
  import { ClientCodeBlock } from "../components/codeblock.js";
4
- import { pathnameFromRequest } from "../../requests/generators/index.js";
5
7
  import { MethodLabel } from "../components/method-label.js";
6
- import { Markdown } from "../components/markdown.js";
7
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
9
  import { useTranslations } from "@fuma-translate/react";
9
- import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Accordions } from "@fumadocs/api-docs/components/accordion";
10
10
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "fumadocs-ui/components/tabs";
11
11
  //#region src/ui/operation/request-tabs.tsx
12
- function RequestTabs({ path, operation, method, pathItem, examples }) {
12
+ function RequestTabs() {
13
13
  const ctx = useRenderContext();
14
+ const { path, method, operation, pathItem } = useOperation();
15
+ const { items } = useExampleRequests();
14
16
  if (!operation.requestBody) return null;
15
- const { renderRequestTabs = renderRequestTabsDefault } = ctx.content ?? {};
16
- return renderRequestTabs({
17
- items: examples,
17
+ if (ctx.content?.renderRequestTabs) return ctx.content.renderRequestTabs({
18
+ items,
18
19
  route: path,
19
20
  method,
20
21
  pathItem,
21
22
  operation
22
23
  }, ctx);
24
+ return /* @__PURE__ */ jsx(RequestTabsDefaultContent, { items });
23
25
  }
24
- function renderRequestTabsDefault(options) {
25
- return /* @__PURE__ */ jsx(RequestTabsDefaultContent, { options });
26
- }
27
- function RequestTabsDefaultContent({ options }) {
26
+ function RequestTabsDefaultContent({ items }) {
28
27
  const t = useTranslations({ note: "operation page" });
29
- const { items } = options;
30
28
  let children;
31
29
  if (items.length > 1) children = /* @__PURE__ */ jsxs(Tabs, {
32
30
  defaultValue: items[0].id,
@@ -35,16 +33,10 @@ function RequestTabsDefaultContent({ options }) {
35
33
  children: item.id === "_default" ? t("Default") : item.name
36
34
  }, item.id)) }), items.map((item) => /* @__PURE__ */ jsx(TabsContent, {
37
35
  value: item.id,
38
- children: /* @__PURE__ */ jsx(RequestTabsItem, {
39
- item,
40
- options
41
- })
36
+ children: /* @__PURE__ */ jsx(RequestTabsItem, { item })
42
37
  }, item.id))]
43
38
  });
44
- else if (items.length === 1) children = /* @__PURE__ */ jsx(RequestTabsItem, {
45
- item: items[0],
46
- options
47
- });
39
+ else if (items.length === 1) children = /* @__PURE__ */ jsx(RequestTabsItem, { item: items[0] });
48
40
  else children = /* @__PURE__ */ jsx("p", {
49
41
  className: "text-fd-muted-foreground text-xs",
50
42
  children: t("Empty")
@@ -57,7 +49,7 @@ function RequestTabsDefaultContent({ options }) {
57
49
  }), children]
58
50
  });
59
51
  }
60
- function RequestTabsItem({ item, options }) {
52
+ function RequestTabsItem({ item }) {
61
53
  const t = useTranslations({ note: "operation page" });
62
54
  const requestData = item.data;
63
55
  const displayNames = {
@@ -74,7 +66,7 @@ function RequestTabsItem({ item, options }) {
74
66
  item.description && /* @__PURE__ */ jsx(Markdown, { md: item.description }),
75
67
  /* @__PURE__ */ jsxs("div", {
76
68
  className: "flex flex-row gap-2 items-center justify-between",
77
- children: [/* @__PURE__ */ jsx(MethodLabel, { children: requestData.method }), /* @__PURE__ */ jsx("code", { children: pathnameFromRequest(options.route, item.encoded) })]
69
+ children: [/* @__PURE__ */ jsx(MethodLabel, { children: requestData.method }), /* @__PURE__ */ jsx("code", { children: item.pathname })]
78
70
  }),
79
71
  /* @__PURE__ */ jsx(Accordions, {
80
72
  type: "multiple",