@oaspect/react 0.1.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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +14 -0
  3. package/dist/api-reference.js +476 -0
  4. package/dist/api-reference.js.map +1 -0
  5. package/dist/auth-panel.js +116 -0
  6. package/dist/auth-panel.js.map +1 -0
  7. package/dist/code-block.js +105 -0
  8. package/dist/code-block.js.map +1 -0
  9. package/dist/i18n/ar.js +89 -0
  10. package/dist/i18n/ar.js.map +1 -0
  11. package/dist/i18n/context.js +50 -0
  12. package/dist/i18n/context.js.map +1 -0
  13. package/dist/i18n/en.js +89 -0
  14. package/dist/i18n/en.js.map +1 -0
  15. package/dist/i18n/index.js +37 -0
  16. package/dist/i18n/index.js.map +1 -0
  17. package/dist/i18n/tr.js +89 -0
  18. package/dist/i18n/tr.js.map +1 -0
  19. package/dist/icons.js +55 -0
  20. package/dist/icons.js.map +1 -0
  21. package/dist/index.d.ts +78 -0
  22. package/dist/index.js +12 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/intro.js +132 -0
  25. package/dist/intro.js.map +1 -0
  26. package/dist/lazy.js +41 -0
  27. package/dist/lazy.js.map +1 -0
  28. package/dist/logo.js +12 -0
  29. package/dist/logo.js.map +1 -0
  30. package/dist/markdown.js +170 -0
  31. package/dist/markdown.js.map +1 -0
  32. package/dist/method-badge.js +37 -0
  33. package/dist/method-badge.js.map +1 -0
  34. package/dist/models.js +27 -0
  35. package/dist/models.js.map +1 -0
  36. package/dist/oaspect.css +1703 -0
  37. package/dist/operation.js +267 -0
  38. package/dist/operation.js.map +1 -0
  39. package/dist/samples.js +129 -0
  40. package/dist/samples.js.map +1 -0
  41. package/dist/schema-tree.js +160 -0
  42. package/dist/schema-tree.js.map +1 -0
  43. package/dist/send.js +58 -0
  44. package/dist/send.js.map +1 -0
  45. package/dist/sidebar.js +125 -0
  46. package/dist/sidebar.js.map +1 -0
  47. package/dist/spec-context.js +23 -0
  48. package/dist/spec-context.js.map +1 -0
  49. package/dist/storage.js +30 -0
  50. package/dist/storage.js.map +1 -0
  51. package/dist/try-it.js +277 -0
  52. package/dist/try-it.js.map +1 -0
  53. package/package.json +66 -0
  54. package/tailwind.css +21 -0
@@ -0,0 +1,267 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { memo, useRef, useState } from "react";
4
+ import { jsonMediaType, linkTarget, mediaExample, resolveSchema, securityRequirements } from "@oaspect/core";
5
+ import CodeBlock, { CopyButton } from "./code-block.js";
6
+ import { useLocalized, useT } from "./i18n/context.js";
7
+ import Markdown from "./markdown.js";
8
+ import MethodBadge, { statusTone } from "./method-badge.js";
9
+ import { RequestSample, ResponseSample } from "./samples.js";
10
+ import SchemaTree, { FieldDetails } from "./schema-tree.js";
11
+ import { useModel, useSpec } from "./spec-context.js";
12
+ import { ChevronIcon, LockIcon } from "./icons.js";
13
+ import { useNearViewport } from "./lazy.js";
14
+ const PARAM_GROUPS = [
15
+ ["path", "params.path"],
16
+ ["query", "params.query"],
17
+ ["header", "params.header"],
18
+ ["cookie", "params.cookie"]
19
+ ];
20
+ function SectionTitle({ children, aside }) {
21
+ return /* @__PURE__ */ jsxs("div", { className: "mb-2 mt-8 flex items-center justify-between gap-2 border-b border-border pb-2", children: [
22
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold", children }),
23
+ aside
24
+ ] });
25
+ }
26
+ function Parameters({ parameters }) {
27
+ const spec = useSpec();
28
+ const t = useT();
29
+ const localized = useLocalized();
30
+ return PARAM_GROUPS.map(([location, title]) => {
31
+ const list = parameters.filter((param) => param.in === location);
32
+ if (list.length === 0) return null;
33
+ return /* @__PURE__ */ jsxs("div", { children: [
34
+ /* @__PURE__ */ jsx(SectionTitle, { children: t(title) }),
35
+ list.map((param) => {
36
+ const { schema, name } = resolveSchema(spec, param.schema ?? {});
37
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1 border-t border-border py-3 first:border-t-0", children: [
38
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-sm font-semibold", children: param.name }),
39
+ /* @__PURE__ */ jsx(
40
+ FieldDetails,
41
+ {
42
+ schema: param.example !== void 0 ? { ...schema, example: param.example } : schema,
43
+ name,
44
+ description: localized(param, "description"),
45
+ required: param.required,
46
+ deprecated: param.deprecated
47
+ }
48
+ )
49
+ ] }, param.name);
50
+ })
51
+ ] }, location);
52
+ });
53
+ }
54
+ function MediaSchema({ content }) {
55
+ const types = Object.keys(content);
56
+ const [type, setType] = useState(jsonMediaType(content));
57
+ const t = useT();
58
+ const media = content[type];
59
+ return /* @__PURE__ */ jsxs("div", { children: [
60
+ types.length > 1 && /* @__PURE__ */ jsx(
61
+ "select",
62
+ {
63
+ value: type,
64
+ onChange: (event) => setType(event.target.value),
65
+ className: "mb-2 rounded-md border border-border bg-background px-2 py-1 font-mono text-xs",
66
+ children: types.map((item) => /* @__PURE__ */ jsx("option", { children: item }, item))
67
+ }
68
+ ),
69
+ media?.schema ? /* @__PURE__ */ jsx(SchemaTree, { schema: media.schema }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("schema.none") })
70
+ ] });
71
+ }
72
+ function Links({ links }) {
73
+ const t = useT();
74
+ const model = useModel();
75
+ const localized = useLocalized();
76
+ return /* @__PURE__ */ jsxs("div", { children: [
77
+ /* @__PURE__ */ jsx("p", { className: "pb-1 text-xs font-semibold text-muted-foreground", children: t("operation.links") }),
78
+ links.map((link) => {
79
+ const target = model ? linkTarget(model, link) : void 0;
80
+ const parameters = Object.entries(link.parameters);
81
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1 border-t border-border py-2 first:border-t-0", children: [
82
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-2 text-sm", children: [
83
+ /* @__PURE__ */ jsx("span", { className: "font-mono font-semibold", children: link.name }),
84
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u2192" }),
85
+ target ? /* @__PURE__ */ jsx("a", { href: `#${target.anchor}`, className: "text-primary underline underline-offset-2", children: localized(target, "summary") || target.operationId || `${target.method.toUpperCase()} ${target.path}` }) : /* @__PURE__ */ jsx("code", { dir: "ltr", className: "font-mono text-xs text-muted-foreground", children: link.operationId ?? link.operationRef })
86
+ ] }),
87
+ /* @__PURE__ */ jsx(Markdown, { source: link.description, className: "text-muted-foreground" }),
88
+ parameters.length > 0 && /* @__PURE__ */ jsx("dl", { dir: "ltr", className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-0.5 font-mono text-xs", children: parameters.map(([name, expression]) => /* @__PURE__ */ jsxs("div", { className: "contents", children: [
89
+ /* @__PURE__ */ jsx("dt", { className: "font-semibold", children: name }),
90
+ /* @__PURE__ */ jsx("dd", { className: "break-all text-muted-foreground", children: typeof expression === "string" ? expression : JSON.stringify(expression) })
91
+ ] }, name)) })
92
+ ] }, link.name);
93
+ })
94
+ ] });
95
+ }
96
+ function ResponseRow({ response, defaultOpen }) {
97
+ const localized = useLocalized();
98
+ const [open, setOpen] = useState(defaultOpen);
99
+ const hasBody = Object.keys(response.content).length > 0;
100
+ const headers = Object.entries(response.headers);
101
+ const links = response.links ?? [];
102
+ const expandable = hasBody || headers.length > 0 || links.length > 0;
103
+ return /* @__PURE__ */ jsxs("div", { className: "border-t border-border first:border-t-0", children: [
104
+ /* @__PURE__ */ jsxs(
105
+ "button",
106
+ {
107
+ type: "button",
108
+ disabled: !expandable,
109
+ onClick: () => setOpen(!open),
110
+ className: "flex w-full items-baseline gap-3 py-3 text-start enabled:hover:text-primary",
111
+ children: [
112
+ /* @__PURE__ */ jsx("span", { className: `flex w-4 shrink-0 self-center transition ${expandable ? "" : "invisible"} ${open ? "rotate-90" : "rtl:-scale-x-100"}`, children: /* @__PURE__ */ jsx(ChevronIcon, {}) }),
113
+ /* @__PURE__ */ jsx("span", { className: `font-mono text-sm font-bold ${statusTone(response.status)}`, children: response.status }),
114
+ /* @__PURE__ */ jsx("span", { dir: "auto", className: "text-sm text-muted-foreground", children: localized(response, "description") })
115
+ ]
116
+ }
117
+ ),
118
+ open && expandable && /* @__PURE__ */ jsxs("div", { className: "mb-4 ms-7 space-y-4", children: [
119
+ headers.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
120
+ /* @__PURE__ */ jsx("p", { className: "pb-1 text-xs font-semibold text-muted-foreground", children: "Headers" }),
121
+ headers.map(([name, header]) => /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-2 py-1", children: [
122
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-sm font-semibold", children: name }),
123
+ /* @__PURE__ */ jsx(FieldDetails, { schema: header.schema ?? {}, description: localized(header, "description") })
124
+ ] }, name))
125
+ ] }),
126
+ hasBody && /* @__PURE__ */ jsx(MediaSchema, { content: response.content }),
127
+ links.length > 0 && /* @__PURE__ */ jsx(Links, { links })
128
+ ] })
129
+ ] });
130
+ }
131
+ function Callback({ operation }) {
132
+ const [open, setOpen] = useState(false);
133
+ const localized = useLocalized();
134
+ const t = useT();
135
+ return /* @__PURE__ */ jsxs("div", { className: "border-t border-border first:border-t-0", children: [
136
+ /* @__PURE__ */ jsxs(
137
+ "button",
138
+ {
139
+ type: "button",
140
+ onClick: () => setOpen(!open),
141
+ "aria-expanded": open,
142
+ className: "flex w-full items-center gap-3 py-3 text-start hover:text-primary",
143
+ children: [
144
+ /* @__PURE__ */ jsx("span", { className: `flex w-4 shrink-0 transition ${open ? "rotate-90" : "rtl:-scale-x-100"}`, children: /* @__PURE__ */ jsx(ChevronIcon, {}) }),
145
+ /* @__PURE__ */ jsx(MethodBadge, { method: operation.method, size: "sm" }),
146
+ /* @__PURE__ */ jsx("code", { dir: "ltr", className: "min-w-0 truncate font-mono text-xs", children: operation.path }),
147
+ /* @__PURE__ */ jsx("span", { dir: "auto", className: "truncate text-sm text-muted-foreground", children: localized(operation, "summary") })
148
+ ]
149
+ }
150
+ ),
151
+ open && /* @__PURE__ */ jsxs("div", { className: "mb-4 ms-7 space-y-3", children: [
152
+ /* @__PURE__ */ jsx(Markdown, { source: localized(operation, "description") }),
153
+ operation.requestBody?.content && /* @__PURE__ */ jsxs("div", { children: [
154
+ /* @__PURE__ */ jsx("p", { className: "pb-1 text-xs font-semibold text-muted-foreground", children: t("operation.requestBody") }),
155
+ /* @__PURE__ */ jsx(MediaSchema, { content: operation.requestBody.content })
156
+ ] }),
157
+ operation.responses.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
158
+ /* @__PURE__ */ jsx("p", { className: "pb-1 text-xs font-semibold text-muted-foreground", children: t("operation.responses") }),
159
+ operation.responses.map((response) => /* @__PURE__ */ jsx(ResponseRow, { response, defaultOpen: false }, response.status))
160
+ ] })
161
+ ] })
162
+ ] });
163
+ }
164
+ function PayloadSample({ operation }) {
165
+ const spec = useSpec();
166
+ const t = useT();
167
+ const content = operation.requestBody?.content;
168
+ const type = jsonMediaType(content);
169
+ if (!type) return null;
170
+ const example = mediaExample(spec, content[type]);
171
+ if (example === void 0) return null;
172
+ return /* @__PURE__ */ jsx(
173
+ CodeBlock,
174
+ {
175
+ code: typeof example === "string" ? example : JSON.stringify(example, null, 2),
176
+ toolbar: /* @__PURE__ */ jsx("span", { className: "px-1 text-xs font-medium text-white/60", children: t("webhooks.payload") })
177
+ }
178
+ );
179
+ }
180
+ function SecurityLine({ operation }) {
181
+ const t = useT();
182
+ const requirements = securityRequirements(operation);
183
+ if (!requirements.length) return null;
184
+ const optional = requirements.some((requirement) => requirement.schemes.length === 0);
185
+ const alternatives = requirements.filter((requirement) => requirement.schemes.length);
186
+ return /* @__PURE__ */ jsxs("p", { className: "mt-2 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [
187
+ /* @__PURE__ */ jsx(LockIcon, { className: "size-3.5" }),
188
+ /* @__PURE__ */ jsx("span", { children: t("operation.security") }),
189
+ alternatives.map((requirement, index) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
190
+ index > 0 && /* @__PURE__ */ jsx("span", { children: t("operation.securityOr") }),
191
+ /* @__PURE__ */ jsx("code", { dir: "ltr", className: "rounded bg-muted px-1 py-0.5 font-mono text-[11px]", children: requirement.schemes.map((name) => requirement.scopes[name]?.length ? `${name} (${requirement.scopes[name].join(", ")})` : name).join(" + ") })
192
+ ] }, index)),
193
+ optional && /* @__PURE__ */ jsxs("span", { children: [
194
+ "(",
195
+ t("operation.securityOptional"),
196
+ ")"
197
+ ] })
198
+ ] });
199
+ }
200
+ function Operation({ operation, onTry, eager = false }) {
201
+ const t = useT();
202
+ const localized = useLocalized();
203
+ const webhook = operation.kind === "webhook";
204
+ const ref = useRef(null);
205
+ const near = useNearViewport(ref, eager);
206
+ if (!near) {
207
+ return /* @__PURE__ */ jsxs("section", { ref, id: operation.anchor, "data-anchor": true, className: "min-h-[32rem] border-b border-border py-14", children: [
208
+ /* @__PURE__ */ jsx("h3", { className: "text-2xl font-semibold tracking-tight [overflow-wrap:anywhere]", children: localized(operation, "summary") || operation.path }),
209
+ /* @__PURE__ */ jsxs("p", { dir: "ltr", className: "mt-3 font-mono text-sm text-muted-foreground", children: [
210
+ operation.method.toUpperCase(),
211
+ " ",
212
+ operation.path
213
+ ] })
214
+ ] });
215
+ }
216
+ return /* @__PURE__ */ jsx("section", { ref, id: operation.anchor, "data-anchor": true, className: "border-b border-border py-14", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)] gap-10 xl:grid-cols-[minmax(0,1fr)_minmax(0,28rem)]", children: [
217
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
218
+ /* @__PURE__ */ jsxs("h3", { className: "flex flex-wrap items-center gap-2 text-2xl font-semibold tracking-tight [overflow-wrap:anywhere]", children: [
219
+ /* @__PURE__ */ jsx("a", { href: `#${operation.anchor}`, className: "hover:text-primary", children: localized(operation, "summary") || operation.path }),
220
+ operation.deprecated && /* @__PURE__ */ jsx("span", { className: "rounded-md bg-amber-500/15 px-2 py-0.5 text-xs font-medium text-amber-700 dark:text-amber-300", children: "deprecated" })
221
+ ] }),
222
+ /* @__PURE__ */ jsxs("div", { dir: "ltr", className: "mt-3 flex items-center gap-2 overflow-hidden rounded-lg border border-border bg-card px-2 py-1.5", children: [
223
+ /* @__PURE__ */ jsx(MethodBadge, { method: operation.method }),
224
+ /* @__PURE__ */ jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-sm", children: operation.path }),
225
+ /* @__PURE__ */ jsx(CopyButton, { text: operation.path, className: "text-muted-foreground hover:bg-muted hover:text-foreground" })
226
+ ] }),
227
+ operation.operationId && /* @__PURE__ */ jsxs("p", { dir: "ltr", className: "mt-2 text-start font-mono text-[11px] text-muted-foreground [unicode-bidi:plaintext]", children: [
228
+ "operationId: ",
229
+ operation.operationId
230
+ ] }),
231
+ /* @__PURE__ */ jsx(SecurityLine, { operation }),
232
+ /* @__PURE__ */ jsx(Markdown, { source: localized(operation, "description"), className: "mt-4" }),
233
+ /* @__PURE__ */ jsx(Parameters, { parameters: operation.parameters }),
234
+ operation.requestBody?.content && /* @__PURE__ */ jsxs("div", { children: [
235
+ /* @__PURE__ */ jsx(
236
+ SectionTitle,
237
+ {
238
+ aside: operation.requestBody.required && /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-rose-700 dark:text-rose-400", children: "required" }),
239
+ children: t("operation.requestBody")
240
+ }
241
+ ),
242
+ /* @__PURE__ */ jsx(Markdown, { source: localized(operation.requestBody, "description"), className: "pb-2 text-muted-foreground" }),
243
+ /* @__PURE__ */ jsx(MediaSchema, { content: operation.requestBody.content })
244
+ ] }),
245
+ operation.responses.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
246
+ /* @__PURE__ */ jsx(SectionTitle, { children: t("operation.responses") }),
247
+ operation.responses.map((response, index) => /* @__PURE__ */ jsx(ResponseRow, { response, defaultOpen: index === 0 && /^2/.test(response.status) }, response.status))
248
+ ] }),
249
+ operation.callbacks?.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
250
+ /* @__PURE__ */ jsx(SectionTitle, { children: t("operation.callbacks") }),
251
+ operation.callbacks.map((callback) => /* @__PURE__ */ jsxs("div", { children: [
252
+ /* @__PURE__ */ jsx("p", { className: "pt-2 font-mono text-xs font-semibold text-muted-foreground", children: callback.name }),
253
+ callback.operations.map((item) => /* @__PURE__ */ jsx(Callback, { operation: item }, item.anchor))
254
+ ] }, callback.name))
255
+ ] })
256
+ ] }),
257
+ /* @__PURE__ */ jsx("aside", { className: "min-w-0 space-y-4 xl:sticky xl:top-20 xl:self-start", children: webhook ? /* @__PURE__ */ jsx(PayloadSample, { operation }) : /* @__PURE__ */ jsxs(Fragment, { children: [
258
+ /* @__PURE__ */ jsx(RequestSample, { operation, onTry: onTry ? () => onTry(operation) : null }),
259
+ /* @__PURE__ */ jsx(ResponseSample, { operation })
260
+ ] }) })
261
+ ] }) });
262
+ }
263
+ var operation_default = memo(Operation);
264
+ export {
265
+ operation_default as default
266
+ };
267
+ //# sourceMappingURL=operation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/operation.jsx"],"sourcesContent":["\"use client\";\n\nimport { memo, useRef, useState } from \"react\";\nimport { jsonMediaType, linkTarget, mediaExample, resolveSchema, securityRequirements } from \"@oaspect/core\";\nimport CodeBlock, { CopyButton } from \"./code-block\";\nimport { useLocalized, useT } from \"./i18n/context\";\nimport Markdown from \"./markdown\";\nimport MethodBadge, { statusTone } from \"./method-badge\";\nimport { RequestSample, ResponseSample } from \"./samples\";\nimport SchemaTree, { FieldDetails } from \"./schema-tree\";\nimport { useModel, useSpec } from \"./spec-context\";\nimport { ChevronIcon, LockIcon } from \"./icons\";\nimport { useNearViewport } from \"./lazy\";\n\n// Titles are translation keys.\nconst PARAM_GROUPS = [\n [\"path\", \"params.path\"],\n [\"query\", \"params.query\"],\n [\"header\", \"params.header\"],\n [\"cookie\", \"params.cookie\"],\n];\n\nfunction SectionTitle({ children, aside }) {\n return (\n <div className=\"mb-2 mt-8 flex items-center justify-between gap-2 border-b border-border pb-2\">\n <h4 className=\"text-sm font-semibold\">{children}</h4>\n {aside}\n </div>\n );\n}\n\nfunction Parameters({ parameters }) {\n const spec = useSpec();\n const t = useT();\n const localized = useLocalized();\n\n return PARAM_GROUPS.map(([location, title]) => {\n const list = parameters.filter((param) => param.in === location);\n if (list.length === 0) return null;\n\n return (\n <div key={location}>\n <SectionTitle>{t(title)}</SectionTitle>\n {list.map((param) => {\n const { schema, name } = resolveSchema(spec, param.schema ?? {});\n return (\n <div key={param.name} className=\"flex flex-wrap items-baseline gap-x-2 gap-y-1 border-t border-border py-3 first:border-t-0\">\n <span className=\"font-mono text-sm font-semibold\">{param.name}</span>\n <FieldDetails\n schema={param.example !== undefined ? { ...schema, example: param.example } : schema}\n name={name}\n description={localized(param, \"description\")}\n required={param.required}\n deprecated={param.deprecated}\n />\n </div>\n );\n })}\n </div>\n );\n });\n}\n\nfunction MediaSchema({ content }) {\n const types = Object.keys(content);\n const [type, setType] = useState(jsonMediaType(content));\n const t = useT();\n const media = content[type];\n\n return (\n <div>\n {types.length > 1 && (\n <select\n value={type}\n onChange={(event) => setType(event.target.value)}\n className=\"mb-2 rounded-md border border-border bg-background px-2 py-1 font-mono text-xs\"\n >\n {types.map((item) => (\n <option key={item}>{item}</option>\n ))}\n </select>\n )}\n {media?.schema ? <SchemaTree schema={media.schema} /> : <p className=\"text-sm text-muted-foreground\">{t(\"schema.none\")}</p>}\n </div>\n );\n}\n\n// Response links: where a value from this response can be used next.\nfunction Links({ links }) {\n const t = useT();\n const model = useModel();\n const localized = useLocalized();\n\n return (\n <div>\n <p className=\"pb-1 text-xs font-semibold text-muted-foreground\">{t(\"operation.links\")}</p>\n {links.map((link) => {\n const target = model ? linkTarget(model, link) : undefined;\n const parameters = Object.entries(link.parameters);\n return (\n <div key={link.name} className=\"space-y-1 border-t border-border py-2 first:border-t-0\">\n <div className=\"flex flex-wrap items-baseline gap-2 text-sm\">\n <span className=\"font-mono font-semibold\">{link.name}</span>\n <span className=\"text-muted-foreground\">→</span>\n {target ? (\n <a href={`#${target.anchor}`} className=\"text-primary underline underline-offset-2\">\n {localized(target, \"summary\") || target.operationId || `${target.method.toUpperCase()} ${target.path}`}\n </a>\n ) : (\n <code dir=\"ltr\" className=\"font-mono text-xs text-muted-foreground\">{link.operationId ?? link.operationRef}</code>\n )}\n </div>\n <Markdown source={link.description} className=\"text-muted-foreground\" />\n {parameters.length > 0 && (\n <dl dir=\"ltr\" className=\"grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-0.5 font-mono text-xs\">\n {parameters.map(([name, expression]) => (\n <div key={name} className=\"contents\">\n <dt className=\"font-semibold\">{name}</dt>\n <dd className=\"break-all text-muted-foreground\">{typeof expression === \"string\" ? expression : JSON.stringify(expression)}</dd>\n </div>\n ))}\n </dl>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n\nfunction ResponseRow({ response, defaultOpen }) {\n const localized = useLocalized();\n const [open, setOpen] = useState(defaultOpen);\n const hasBody = Object.keys(response.content).length > 0;\n const headers = Object.entries(response.headers);\n const links = response.links ?? [];\n const expandable = hasBody || headers.length > 0 || links.length > 0;\n\n return (\n <div className=\"border-t border-border first:border-t-0\">\n <button\n type=\"button\"\n disabled={!expandable}\n onClick={() => setOpen(!open)}\n className=\"flex w-full items-baseline gap-3 py-3 text-start enabled:hover:text-primary\"\n >\n <span className={`flex w-4 shrink-0 self-center transition ${expandable ? \"\" : \"invisible\"} ${open ? \"rotate-90\" : \"rtl:-scale-x-100\"}`}>\n <ChevronIcon />\n </span>\n <span className={`font-mono text-sm font-bold ${statusTone(response.status)}`}>{response.status}</span>\n <span dir=\"auto\" className=\"text-sm text-muted-foreground\">{localized(response, \"description\")}</span>\n </button>\n {open && expandable && (\n <div className=\"mb-4 ms-7 space-y-4\">\n {headers.length > 0 && (\n <div>\n <p className=\"pb-1 text-xs font-semibold text-muted-foreground\">Headers</p>\n {headers.map(([name, header]) => (\n <div key={name} className=\"flex flex-wrap items-baseline gap-2 py-1\">\n <span className=\"font-mono text-sm font-semibold\">{name}</span>\n <FieldDetails schema={header.schema ?? {}} description={localized(header, \"description\")} />\n </div>\n ))}\n </div>\n )}\n {hasBody && <MediaSchema content={response.content} />}\n {links.length > 0 && <Links links={links} />}\n </div>\n )}\n </div>\n );\n}\n\n// Callback requests the API makes after this operation, per runtime expression.\nfunction Callback({ operation }) {\n const [open, setOpen] = useState(false);\n const localized = useLocalized();\n const t = useT();\n\n return (\n <div className=\"border-t border-border first:border-t-0\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n aria-expanded={open}\n className=\"flex w-full items-center gap-3 py-3 text-start hover:text-primary\"\n >\n <span className={`flex w-4 shrink-0 transition ${open ? \"rotate-90\" : \"rtl:-scale-x-100\"}`}>\n <ChevronIcon />\n </span>\n <MethodBadge method={operation.method} size=\"sm\" />\n <code dir=\"ltr\" className=\"min-w-0 truncate font-mono text-xs\">{operation.path}</code>\n <span dir=\"auto\" className=\"truncate text-sm text-muted-foreground\">{localized(operation, \"summary\")}</span>\n </button>\n {open && (\n <div className=\"mb-4 ms-7 space-y-3\">\n <Markdown source={localized(operation, \"description\")} />\n {operation.requestBody?.content && (\n <div>\n <p className=\"pb-1 text-xs font-semibold text-muted-foreground\">{t(\"operation.requestBody\")}</p>\n <MediaSchema content={operation.requestBody.content} />\n </div>\n )}\n {operation.responses.length > 0 && (\n <div>\n <p className=\"pb-1 text-xs font-semibold text-muted-foreground\">{t(\"operation.responses\")}</p>\n {operation.responses.map((response) => (\n <ResponseRow key={response.status} response={response} defaultOpen={false} />\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\n// Webhooks: the payload the API sends, in place of request samples.\nfunction PayloadSample({ operation }) {\n const spec = useSpec();\n const t = useT();\n const content = operation.requestBody?.content;\n const type = jsonMediaType(content);\n if (!type) return null;\n const example = mediaExample(spec, content[type]);\n if (example === undefined) return null;\n\n return (\n <CodeBlock\n code={typeof example === \"string\" ? example : JSON.stringify(example, null, 2)}\n toolbar={<span className=\"px-1 text-xs font-medium text-white/60\">{t(\"webhooks.payload\")}</span>}\n />\n );\n}\n\n// \"Requires: a or b + c\" from the operation's security requirements.\nfunction SecurityLine({ operation }) {\n const t = useT();\n const requirements = securityRequirements(operation);\n if (!requirements.length) return null;\n const optional = requirements.some((requirement) => requirement.schemes.length === 0);\n const alternatives = requirements.filter((requirement) => requirement.schemes.length);\n\n return (\n <p className=\"mt-2 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground\">\n <LockIcon className=\"size-3.5\" />\n <span>{t(\"operation.security\")}</span>\n {alternatives.map((requirement, index) => (\n <span key={index} className=\"flex items-center gap-1.5\">\n {index > 0 && <span>{t(\"operation.securityOr\")}</span>}\n <code dir=\"ltr\" className=\"rounded bg-muted px-1 py-0.5 font-mono text-[11px]\">\n {requirement.schemes.map((name) => (requirement.scopes[name]?.length ? `${name} (${requirement.scopes[name].join(\", \")})` : name)).join(\" + \")}\n </code>\n </span>\n ))}\n {optional && <span>({t(\"operation.securityOptional\")})</span>}\n </p>\n );\n}\n\nfunction Operation({ operation, onTry, eager = false }) {\n const t = useT();\n const localized = useLocalized();\n const webhook = operation.kind === \"webhook\";\n const ref = useRef(null);\n const near = useNearViewport(ref, eager);\n\n // The <section> stays the same element so anchors and the scroll spy keep\n // working; only its content switches from placeholder to full details.\n if (!near) {\n return (\n <section ref={ref} id={operation.anchor} data-anchor className=\"min-h-[32rem] border-b border-border py-14\">\n <h3 className=\"text-2xl font-semibold tracking-tight [overflow-wrap:anywhere]\">{localized(operation, \"summary\") || operation.path}</h3>\n <p dir=\"ltr\" className=\"mt-3 font-mono text-sm text-muted-foreground\">\n {operation.method.toUpperCase()} {operation.path}\n </p>\n </section>\n );\n }\n\n return (\n <section ref={ref} id={operation.anchor} data-anchor className=\"border-b border-border py-14\">\n <div className=\"grid grid-cols-[minmax(0,1fr)] gap-10 xl:grid-cols-[minmax(0,1fr)_minmax(0,28rem)]\">\n <div className=\"min-w-0\">\n <h3 className=\"flex flex-wrap items-center gap-2 text-2xl font-semibold tracking-tight [overflow-wrap:anywhere]\">\n <a href={`#${operation.anchor}`} className=\"hover:text-primary\">\n {localized(operation, \"summary\") || operation.path}\n </a>\n {operation.deprecated && (\n <span className=\"rounded-md bg-amber-500/15 px-2 py-0.5 text-xs font-medium text-amber-700 dark:text-amber-300\">\n deprecated\n </span>\n )}\n </h3>\n <div dir=\"ltr\" className=\"mt-3 flex items-center gap-2 overflow-hidden rounded-lg border border-border bg-card px-2 py-1.5\">\n <MethodBadge method={operation.method} />\n <code className=\"min-w-0 flex-1 truncate font-mono text-sm\">{operation.path}</code>\n <CopyButton text={operation.path} className=\"text-muted-foreground hover:bg-muted hover:text-foreground\" />\n </div>\n {operation.operationId && (\n <p dir=\"ltr\" className=\"mt-2 text-start font-mono text-[11px] text-muted-foreground [unicode-bidi:plaintext]\">operationId: {operation.operationId}</p>\n )}\n <SecurityLine operation={operation} />\n <Markdown source={localized(operation, \"description\")} className=\"mt-4\" />\n\n <Parameters parameters={operation.parameters} />\n\n {operation.requestBody?.content && (\n <div>\n <SectionTitle\n aside={\n operation.requestBody.required && (\n <span className=\"text-[11px] font-medium text-rose-700 dark:text-rose-400\">required</span>\n )\n }\n >\n {t(\"operation.requestBody\")}\n </SectionTitle>\n <Markdown source={localized(operation.requestBody, \"description\")} className=\"pb-2 text-muted-foreground\" />\n <MediaSchema content={operation.requestBody.content} />\n </div>\n )}\n\n {operation.responses.length > 0 && (\n <div>\n <SectionTitle>{t(\"operation.responses\")}</SectionTitle>\n {operation.responses.map((response, index) => (\n <ResponseRow key={response.status} response={response} defaultOpen={index === 0 && /^2/.test(response.status)} />\n ))}\n </div>\n )}\n\n {operation.callbacks?.length > 0 && (\n <div>\n <SectionTitle>{t(\"operation.callbacks\")}</SectionTitle>\n {operation.callbacks.map((callback) => (\n <div key={callback.name}>\n <p className=\"pt-2 font-mono text-xs font-semibold text-muted-foreground\">{callback.name}</p>\n {callback.operations.map((item) => (\n <Callback key={item.anchor} operation={item} />\n ))}\n </div>\n ))}\n </div>\n )}\n </div>\n\n <aside className=\"min-w-0 space-y-4 xl:sticky xl:top-20 xl:self-start\">\n {webhook ? (\n <PayloadSample operation={operation} />\n ) : (\n <>\n <RequestSample operation={operation} onTry={onTry ? () => onTry(operation) : null} />\n <ResponseSample operation={operation} />\n </>\n )}\n </aside>\n </div>\n </section>\n );\n}\n\nexport default memo(Operation);\n"],"mappings":"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","names":[]}
@@ -0,0 +1,129 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useMemo, useState } from "react";
4
+ import { buildRequest, defaultBody, defaultValues, jsonMediaType, mediaExample, mediaExamples, resolveSnippet, SNIPPET_LANGUAGES } from "@oaspect/core";
5
+ import { useT } from "./i18n/context.js";
6
+ import CodeBlock, { ToolbarTab } from "./code-block.js";
7
+ import { statusTone } from "./method-badge.js";
8
+ import { useSettings, useSpec } from "./spec-context.js";
9
+ import { PlayIcon } from "./icons.js";
10
+ function ToolbarSelect({ label, value, options, onChange }) {
11
+ return /* @__PURE__ */ jsx(
12
+ "select",
13
+ {
14
+ "aria-label": label,
15
+ title: label,
16
+ value,
17
+ onChange: (event) => onChange(event.target.value),
18
+ className: "shrink-0 cursor-pointer rounded-md border border-white/10 bg-white/5 py-1 ps-2 pe-7 text-xs font-medium text-white outline-none transition hover:bg-white/10 focus:border-white/30 [&>option]:bg-neutral-900",
19
+ children: options.map(([key, text]) => /* @__PURE__ */ jsx("option", { value: key, children: text }, key))
20
+ }
21
+ );
22
+ }
23
+ function withAuth(values, auth) {
24
+ return {
25
+ values: { ...values, query: { ...values.query, ...auth.query }, cookie: { ...values.cookie, ...auth.cookies } },
26
+ headers: auth.headers
27
+ };
28
+ }
29
+ function RequestSample({ operation, onTry }) {
30
+ const spec = useSpec();
31
+ const { server, authFor, language, setLanguage } = useSettings();
32
+ const t = useT();
33
+ const request = useMemo(
34
+ () => buildRequest(operation, {
35
+ server,
36
+ ...withAuth(defaultValues(spec, operation), authFor(operation)),
37
+ ...defaultBody(spec, operation)
38
+ }),
39
+ [spec, operation, server, authFor]
40
+ );
41
+ const { language: current, client } = resolveSnippet(language);
42
+ const selectLanguage = (key) => setLanguage(resolveSnippet(key).selection);
43
+ return /* @__PURE__ */ jsx(
44
+ CodeBlock,
45
+ {
46
+ language: current.highlight,
47
+ code: client.build(request),
48
+ toolbar: /* @__PURE__ */ jsxs(Fragment, { children: [
49
+ /* @__PURE__ */ jsx(
50
+ ToolbarSelect,
51
+ {
52
+ label: t("snippets.language"),
53
+ value: current.key,
54
+ onChange: selectLanguage,
55
+ options: SNIPPET_LANGUAGES.map((item) => [item.key, item.label])
56
+ }
57
+ ),
58
+ current.clients.length > 1 && /* @__PURE__ */ jsx(
59
+ ToolbarSelect,
60
+ {
61
+ label: t("snippets.client"),
62
+ value: client.key,
63
+ onChange: (key) => setLanguage(`${current.key}:${key}`),
64
+ options: current.clients.map((item) => [item.key, item.label])
65
+ }
66
+ )
67
+ ] }),
68
+ actions: onTry && /* @__PURE__ */ jsxs(
69
+ "button",
70
+ {
71
+ type: "button",
72
+ onClick: onTry,
73
+ className: "inline-flex items-center gap-1.5 rounded-md bg-primary px-2.5 py-1 text-xs font-semibold text-primary-foreground hover:opacity-90",
74
+ children: [
75
+ t("tryIt.open"),
76
+ /* @__PURE__ */ jsx(PlayIcon, { className: "size-2.5 rtl:-scale-x-100" })
77
+ ]
78
+ }
79
+ )
80
+ }
81
+ );
82
+ }
83
+ function ResponseSample({ operation }) {
84
+ const spec = useSpec();
85
+ const withBody = operation.responses.filter((response2) => jsonMediaType(response2.content));
86
+ const [status, setStatus] = useState(withBody[0]?.status);
87
+ const [exampleKey, setExampleKey] = useState(null);
88
+ if (withBody.length === 0) return null;
89
+ const response = withBody.find((item) => item.status === status) ?? withBody[0];
90
+ const media = response.content[jsonMediaType(response.content)];
91
+ const named = mediaExamples(spec, media);
92
+ const selected = named.find((item) => item.key === exampleKey) ?? named[0];
93
+ const value = selected ? selected.value : mediaExample(spec, media);
94
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
95
+ /* @__PURE__ */ jsx(
96
+ CodeBlock,
97
+ {
98
+ code: value === void 0 ? "" : JSON.stringify(value, null, 2),
99
+ toolbar: withBody.map((item) => /* @__PURE__ */ jsx(
100
+ ToolbarTab,
101
+ {
102
+ active: item.status === response.status,
103
+ onClick: () => {
104
+ setStatus(item.status);
105
+ setExampleKey(null);
106
+ },
107
+ children: /* @__PURE__ */ jsx("span", { className: item.status === response.status ? "" : statusTone(item.status, { onDark: true }), children: item.status })
108
+ },
109
+ item.status
110
+ ))
111
+ }
112
+ ),
113
+ named.length > 1 && /* @__PURE__ */ jsx(
114
+ "select",
115
+ {
116
+ value: selected?.key,
117
+ onChange: (event) => setExampleKey(event.target.value),
118
+ className: "w-full rounded-lg border border-border bg-background px-2 py-1.5 text-xs",
119
+ children: named.map((item) => /* @__PURE__ */ jsx("option", { value: item.key, children: item.summary }, item.key))
120
+ }
121
+ )
122
+ ] });
123
+ }
124
+ export {
125
+ RequestSample,
126
+ ResponseSample,
127
+ withAuth
128
+ };
129
+ //# sourceMappingURL=samples.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/samples.jsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { buildRequest, defaultBody, defaultValues, jsonMediaType, mediaExample, mediaExamples, resolveSnippet, SNIPPET_LANGUAGES } from \"@oaspect/core\";\nimport { useT } from \"./i18n/context\";\nimport CodeBlock, { ToolbarTab } from \"./code-block\";\nimport { statusTone } from \"./method-badge\";\nimport { useSettings, useSpec } from \"./spec-context\";\nimport { PlayIcon } from \"./icons\";\n\n// Compact <select> styled to sit in the dark code toolbar.\nfunction ToolbarSelect({ label, value, options, onChange }) {\n return (\n <select\n aria-label={label}\n title={label}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n className=\"shrink-0 cursor-pointer rounded-md border border-white/10 bg-white/5 py-1 ps-2 pe-7 text-xs font-medium text-white outline-none transition hover:bg-white/10 focus:border-white/30 [&>option]:bg-neutral-900\"\n >\n {options.map(([key, text]) => (\n <option key={key} value={key}>\n {text}\n </option>\n ))}\n </select>\n );\n}\n\n// Merges security parts (API keys in query/cookie, auth headers) into a request's values.\nexport function withAuth(values, auth) {\n return {\n values: { ...values, query: { ...values.query, ...auth.query }, cookie: { ...values.cookie, ...auth.cookies } },\n headers: auth.headers,\n };\n}\n\nexport function RequestSample({ operation, onTry }) {\n const spec = useSpec();\n const { server, authFor, language, setLanguage } = useSettings();\n const t = useT();\n\n const request = useMemo(\n () =>\n buildRequest(operation, {\n server,\n ...withAuth(defaultValues(spec, operation), authFor(operation)),\n ...defaultBody(spec, operation),\n }),\n [spec, operation, server, authFor],\n );\n\n const { language: current, client } = resolveSnippet(language);\n const selectLanguage = (key) => setLanguage(resolveSnippet(key).selection);\n\n return (\n <CodeBlock\n language={current.highlight}\n code={client.build(request)}\n toolbar={\n <>\n <ToolbarSelect\n label={t(\"snippets.language\")}\n value={current.key}\n onChange={selectLanguage}\n options={SNIPPET_LANGUAGES.map((item) => [item.key, item.label])}\n />\n {current.clients.length > 1 && (\n <ToolbarSelect\n label={t(\"snippets.client\")}\n value={client.key}\n onChange={(key) => setLanguage(`${current.key}:${key}`)}\n options={current.clients.map((item) => [item.key, item.label])}\n />\n )}\n </>\n }\n actions={\n onTry && (\n <button\n type=\"button\"\n onClick={onTry}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-2.5 py-1 text-xs font-semibold text-primary-foreground hover:opacity-90\"\n >\n {t(\"tryIt.open\")}\n <PlayIcon className=\"size-2.5 rtl:-scale-x-100\" />\n </button>\n )\n }\n />\n );\n}\n\nexport function ResponseSample({ operation }) {\n const spec = useSpec();\n const withBody = operation.responses.filter((response) => jsonMediaType(response.content));\n const [status, setStatus] = useState(withBody[0]?.status);\n const [exampleKey, setExampleKey] = useState(null);\n\n if (withBody.length === 0) return null;\n\n const response = withBody.find((item) => item.status === status) ?? withBody[0];\n const media = response.content[jsonMediaType(response.content)];\n const named = mediaExamples(spec, media);\n const selected = named.find((item) => item.key === exampleKey) ?? named[0];\n const value = selected ? selected.value : mediaExample(spec, media);\n\n return (\n <div className=\"space-y-2\">\n <CodeBlock\n code={value === undefined ? \"\" : JSON.stringify(value, null, 2)}\n toolbar={withBody.map((item) => (\n <ToolbarTab\n key={item.status}\n active={item.status === response.status}\n onClick={() => {\n setStatus(item.status);\n setExampleKey(null);\n }}\n >\n <span className={item.status === response.status ? \"\" : statusTone(item.status, { onDark: true })}>{item.status}</span>\n </ToolbarTab>\n ))}\n />\n {named.length > 1 && (\n <select\n value={selected?.key}\n onChange={(event) => setExampleKey(event.target.value)}\n className=\"w-full rounded-lg border border-border bg-background px-2 py-1.5 text-xs\"\n >\n {named.map((item) => (\n <option key={item.key} value={item.key}>\n {item.summary}\n </option>\n ))}\n </select>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["response"]}
@@ -0,0 +1,160 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { childrenOf, constraintsOf, modelAnchor, resolveSchema, typeLabel } from "@oaspect/core";
5
+ import { useLocalized, useT } from "./i18n/context.js";
6
+ import Markdown from "./markdown.js";
7
+ import { useSpec } from "./spec-context.js";
8
+ import { ChevronIcon } from "./icons.js";
9
+ function Chip({ children, className = "" }) {
10
+ return /* @__PURE__ */ jsx("span", { dir: "ltr", className: `rounded-md bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground ${className}`, children });
11
+ }
12
+ const formatValue = (value) => typeof value === "string" ? `"${value}"` : JSON.stringify(value);
13
+ function FieldDetails({ schema, name, description, required, deprecated, extra }) {
14
+ const spec = useSpec();
15
+ const t = useT();
16
+ const localized = useLocalized();
17
+ const constraints = constraintsOf(schema);
18
+ const text = description ?? localized(schema, "description");
19
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
20
+ /* @__PURE__ */ jsx("span", { dir: "ltr", className: "font-mono text-xs text-muted-foreground", children: name && schema.properties ? /* @__PURE__ */ jsx("a", { href: `#${modelAnchor(name)}`, className: "hover:text-primary", children: typeLabel(spec, schema, name) }) : typeLabel(spec, schema, name) }),
21
+ required && /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-rose-700 dark:text-rose-400", children: "required" }),
22
+ schema.nullable && /* @__PURE__ */ jsx(Chip, { children: "nullable" }),
23
+ schema.readOnly && /* @__PURE__ */ jsx(Chip, { children: "read-only" }),
24
+ schema.writeOnly && /* @__PURE__ */ jsx(Chip, { children: "write-only" }),
25
+ (deprecated || schema.deprecated) && /* @__PURE__ */ jsx(Chip, { className: "!bg-amber-500/15 !text-amber-700 dark:!text-amber-300", children: "deprecated" }),
26
+ extra,
27
+ (text || schema.enum || constraints.length > 0 || schema.pattern || schema.default !== void 0 || schema.example !== void 0) && /* @__PURE__ */ jsxs("div", { className: "basis-full space-y-2 pt-1", children: [
28
+ /* @__PURE__ */ jsx(Markdown, { source: text, className: "text-muted-foreground" }),
29
+ schema.enum && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 text-xs text-muted-foreground", children: [
30
+ /* @__PURE__ */ jsx("span", { children: t("schema.values") }),
31
+ schema.enum.map((value) => /* @__PURE__ */ jsx(Chip, { children: formatValue(value) }, String(value)))
32
+ ] }),
33
+ (constraints.length > 0 || schema.pattern) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
34
+ constraints.map((item) => /* @__PURE__ */ jsx(Chip, { children: item }, item)),
35
+ schema.pattern && /* @__PURE__ */ jsxs(Chip, { children: [
36
+ "pattern: ",
37
+ schema.pattern
38
+ ] })
39
+ ] }),
40
+ schema.default !== void 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
41
+ t("schema.default"),
42
+ " ",
43
+ /* @__PURE__ */ jsx(Chip, { children: formatValue(schema.default) })
44
+ ] }),
45
+ schema.example !== void 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
46
+ t("schema.example"),
47
+ " ",
48
+ /* @__PURE__ */ jsx(Chip, { children: formatValue(schema.example) })
49
+ ] })
50
+ ] })
51
+ ] });
52
+ }
53
+ function PropertyRow({ name, raw, required, depth, seen }) {
54
+ const spec = useSpec();
55
+ const { schema, name: refName } = resolveSchema(spec, raw);
56
+ const circular = refName && seen.has(refName);
57
+ const nested = circular ? null : childrenOf(spec, schema);
58
+ const [open, setOpen] = useState(false);
59
+ const t = useT();
60
+ return /* @__PURE__ */ jsxs("div", { className: "border-t border-border py-3 first:border-t-0", children: [
61
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
62
+ nested ? /* @__PURE__ */ jsxs(
63
+ "button",
64
+ {
65
+ type: "button",
66
+ onClick: () => setOpen(!open),
67
+ "aria-expanded": open,
68
+ className: "flex items-baseline gap-1 font-mono text-sm font-semibold hover:text-primary",
69
+ children: [
70
+ /* @__PURE__ */ jsx("span", { className: `inline-flex self-center transition ${open ? "rotate-90" : "rtl:-scale-x-100"}`, children: /* @__PURE__ */ jsx(ChevronIcon, { className: "size-3" }) }),
71
+ name
72
+ ]
73
+ }
74
+ ) : /* @__PURE__ */ jsx("span", { className: "font-mono text-sm font-semibold", children: name }),
75
+ /* @__PURE__ */ jsx(
76
+ FieldDetails,
77
+ {
78
+ schema,
79
+ name: refName,
80
+ required,
81
+ extra: circular && /* @__PURE__ */ jsxs(Chip, { children: [
82
+ "\u21BB ",
83
+ t("schema.circular")
84
+ ] })
85
+ }
86
+ )
87
+ ] }),
88
+ nested && open && /* @__PURE__ */ jsx("div", { className: "ms-1 mt-3 border-s-2 border-border ps-4", children: /* @__PURE__ */ jsx(SchemaBody, { schema, nested, depth: depth + 1, seen: refName ? new Set(seen).add(refName) : seen }) })
89
+ ] });
90
+ }
91
+ function SchemaBody({ schema, nested, depth, seen }) {
92
+ const spec = useSpec();
93
+ const [variant, setVariant] = useState(0);
94
+ const t = useT();
95
+ if (nested.kind === "properties") {
96
+ const required = new Set(schema.required ?? []);
97
+ return /* @__PURE__ */ jsx("div", { children: Object.entries(schema.properties).map(([key, value]) => /* @__PURE__ */ jsx(PropertyRow, { name: key, raw: value, required: required.has(key), depth, seen }, key)) });
98
+ }
99
+ if (nested.kind === "items" || nested.kind === "map") {
100
+ const inner2 = childrenOf(spec, nested.schema);
101
+ return /* @__PURE__ */ jsxs("div", { children: [
102
+ /* @__PURE__ */ jsxs("p", { className: "pb-2 text-xs text-muted-foreground", children: [
103
+ nested.kind === "items" ? t("schema.arrayItem") : t("schema.mapValue"),
104
+ ": ",
105
+ /* @__PURE__ */ jsx("span", { dir: "ltr", className: "font-mono", children: nested.name ?? typeLabel(spec, nested.schema) })
106
+ ] }),
107
+ /* @__PURE__ */ jsx(
108
+ SchemaBody,
109
+ {
110
+ schema: nested.schema,
111
+ nested: inner2,
112
+ depth,
113
+ seen: nested.name ? new Set(seen).add(nested.name) : seen
114
+ }
115
+ )
116
+ ] });
117
+ }
118
+ const current = nested.variants[variant] ?? nested.variants[0];
119
+ const inner = childrenOf(spec, current.schema);
120
+ return /* @__PURE__ */ jsxs("div", { children: [
121
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1 pb-2", children: [
122
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
123
+ nested.kind,
124
+ ":"
125
+ ] }),
126
+ nested.variants.map((item, index) => /* @__PURE__ */ jsx(
127
+ "button",
128
+ {
129
+ type: "button",
130
+ onClick: () => setVariant(index),
131
+ className: `rounded-md border px-2 py-0.5 font-mono text-[11px] transition ${index === variant ? "border-primary text-primary" : "border-border text-muted-foreground hover:text-foreground"}`,
132
+ children: item.name ?? item.schema.title ?? typeLabel(spec, item.schema)
133
+ },
134
+ index
135
+ ))
136
+ ] }),
137
+ inner ? /* @__PURE__ */ jsx(SchemaBody, { schema: current.schema, nested: inner, depth, seen }) : /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-baseline gap-2 py-2", children: /* @__PURE__ */ jsx(FieldDetails, { schema: current.schema, name: current.name }) })
138
+ ] });
139
+ }
140
+ function SchemaTree({ schema: raw, modelName }) {
141
+ const spec = useSpec();
142
+ const localized = useLocalized();
143
+ const resolved = resolveSchema(spec, raw);
144
+ const { schema } = resolved;
145
+ const name = resolved.name ?? modelName;
146
+ const nested = childrenOf(spec, schema);
147
+ const seen = name ? /* @__PURE__ */ new Set([name]) : /* @__PURE__ */ new Set();
148
+ if (!nested) {
149
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-baseline gap-2 py-2", children: /* @__PURE__ */ jsx(FieldDetails, { schema, name }) });
150
+ }
151
+ return /* @__PURE__ */ jsxs("div", { children: [
152
+ schema.description && /* @__PURE__ */ jsx(Markdown, { source: localized(schema, "description"), className: "pb-2 text-muted-foreground" }),
153
+ /* @__PURE__ */ jsx(SchemaBody, { schema, nested, depth: 0, seen })
154
+ ] });
155
+ }
156
+ export {
157
+ FieldDetails,
158
+ SchemaTree as default
159
+ };
160
+ //# sourceMappingURL=schema-tree.js.map