@djangocfg/ui-tools 2.1.287 → 2.1.290

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 (105) hide show
  1. package/README.md +14 -3
  2. package/dist/DocsLayout-IKH7BLSU.cjs +3464 -0
  3. package/dist/DocsLayout-IKH7BLSU.cjs.map +1 -0
  4. package/dist/DocsLayout-JPXFUKAR.mjs +3457 -0
  5. package/dist/DocsLayout-JPXFUKAR.mjs.map +1 -0
  6. package/dist/{PrettyCode.client-5GABIN2I.cjs → PrettyCode.client-RPDIE5CH.cjs} +104 -3
  7. package/dist/PrettyCode.client-RPDIE5CH.cjs.map +1 -0
  8. package/dist/{PrettyCode.client-IZTXXYHG.mjs → PrettyCode.client-SPMTQEG4.mjs} +106 -5
  9. package/dist/PrettyCode.client-SPMTQEG4.mjs.map +1 -0
  10. package/dist/{chunk-IULI4XII.cjs → chunk-5Q4UMSWB.cjs} +355 -9
  11. package/dist/chunk-5Q4UMSWB.cjs.map +1 -0
  12. package/dist/{chunk-VZGQC3NG.mjs → chunk-EFWOJPA6.mjs} +349 -9
  13. package/dist/chunk-EFWOJPA6.mjs.map +1 -0
  14. package/dist/index.cjs +10 -10
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +34 -0
  17. package/dist/index.d.ts +34 -0
  18. package/dist/index.mjs +5 -5
  19. package/dist/index.mjs.map +1 -1
  20. package/package.json +21 -14
  21. package/src/components/markdown/MarkdownMessage.tsx +46 -0
  22. package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +93 -157
  23. package/src/tools/OpenapiViewer/README.md +114 -6
  24. package/src/tools/OpenapiViewer/components/DocsLayout/ApiIntroSection.tsx +20 -6
  25. package/src/tools/OpenapiViewer/components/DocsLayout/DocsView.tsx +331 -53
  26. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/CodeSamples/LanguageTabs.tsx +36 -0
  27. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/CodeSamples/index.tsx +56 -0
  28. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/CodeSamples/useCodeSnippet.ts +77 -0
  29. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/MetaActions.tsx +146 -0
  30. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/MethodBadge.tsx +6 -0
  31. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/PathDisplay.tsx +26 -0
  32. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/index.tsx +87 -0
  33. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Parameters/ParamGroup.tsx +30 -0
  34. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Parameters/ParamRow.tsx +36 -0
  35. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Parameters/index.tsx +22 -0
  36. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/RequestBody/index.tsx +33 -0
  37. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/ResponseBody.tsx +76 -0
  38. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/ResponseRow.tsx +80 -0
  39. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/StatusTag.tsx +32 -0
  40. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/index.tsx +21 -0
  41. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +106 -0
  42. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +127 -0
  43. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/index.tsx +31 -0
  44. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/types.ts +28 -0
  45. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/SectionHeader.tsx +87 -0
  46. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/defaults.ts +27 -0
  47. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/index.tsx +45 -0
  48. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/context.tsx +56 -0
  49. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/hooks/useSectionHash.ts +63 -0
  50. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/index.tsx +96 -0
  51. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/store/index.ts +133 -0
  52. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/store/selectors.ts +40 -0
  53. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/types.ts +17 -0
  54. package/src/tools/OpenapiViewer/components/DocsLayout/SchemaCopyMenu.tsx +40 -11
  55. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/BrandHeader.tsx +48 -0
  56. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/CategoryBlock.tsx +33 -0
  57. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/EndpointRow.tsx +73 -0
  58. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/MethodChips.tsx +43 -0
  59. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/SchemaSection.tsx +27 -0
  60. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/SearchInput.tsx +45 -0
  61. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/SidebarBody.tsx +50 -0
  62. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/Toolbar.tsx +64 -0
  63. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/buildVM.ts +126 -0
  64. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/index.tsx +112 -0
  65. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/types.ts +42 -0
  66. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/useDebouncedValue.ts +14 -0
  67. package/src/tools/OpenapiViewer/components/DocsLayout/SlideInPlayground.tsx +10 -7
  68. package/src/tools/OpenapiViewer/components/DocsLayout/TryItSheet.tsx +9 -6
  69. package/src/tools/OpenapiViewer/components/DocsLayout/anchor.ts +19 -2
  70. package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +38 -21
  71. package/src/tools/OpenapiViewer/components/DocsLayout/index.tsx +168 -50
  72. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/PrettyView.tsx +55 -0
  73. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/PreviewView.tsx +115 -0
  74. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/RawView.tsx +24 -0
  75. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/StatusBar.tsx +63 -0
  76. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/ViewTabs.tsx +45 -0
  77. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/detectContent.ts +97 -0
  78. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/index.tsx +93 -0
  79. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/types.ts +26 -0
  80. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/useResponseView.ts +62 -0
  81. package/src/tools/OpenapiViewer/hooks/index.ts +3 -1
  82. package/src/tools/OpenapiViewer/hooks/useDocsUrlSync.ts +119 -0
  83. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +164 -74
  84. package/src/tools/OpenapiViewer/types.ts +46 -1
  85. package/src/tools/OpenapiViewer/utils/codeSamples.ts +287 -0
  86. package/src/tools/OpenapiViewer/utils/index.ts +3 -0
  87. package/src/tools/OpenapiViewer/utils/operationToHar.ts +119 -0
  88. package/src/tools/OpenapiViewer/utils/sampler.ts +72 -0
  89. package/src/tools/OpenapiViewer/utils/scrollParent.ts +68 -0
  90. package/src/tools/PrettyCode/PrettyCode.client.tsx +88 -1
  91. package/src/tools/PrettyCode/PrettyCode.story.tsx +114 -361
  92. package/src/tools/PrettyCode/index.tsx +13 -0
  93. package/src/tools/PrettyCode/lazy.tsx +5 -0
  94. package/src/tools/PrettyCode/registerPrismLanguages.ts +111 -0
  95. package/dist/DocsLayout-BCVU6TTX.cjs +0 -2027
  96. package/dist/DocsLayout-BCVU6TTX.cjs.map +0 -1
  97. package/dist/DocsLayout-ERETJLLV.mjs +0 -2020
  98. package/dist/DocsLayout-ERETJLLV.mjs.map +0 -1
  99. package/dist/PrettyCode.client-5GABIN2I.cjs.map +0 -1
  100. package/dist/PrettyCode.client-IZTXXYHG.mjs.map +0 -1
  101. package/dist/chunk-IULI4XII.cjs.map +0 -1
  102. package/dist/chunk-VZGQC3NG.mjs.map +0 -1
  103. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc.tsx +0 -268
  104. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar.tsx +0 -211
  105. package/src/tools/OpenapiViewer/components/shared/ResponsePanel.tsx +0 -127
@@ -0,0 +1,3464 @@
1
+ 'use strict';
2
+
3
+ var chunk5Q4UMSWB_cjs = require('./chunk-5Q4UMSWB.cjs');
4
+ var chunk33AMWFBZ_cjs = require('./chunk-33AMWFBZ.cjs');
5
+ require('./chunk-2SMCH62O.cjs');
6
+ var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
7
+ var React12 = require('react');
8
+ var lodashEs = require('lodash-es');
9
+ var components = require('@djangocfg/ui-core/components');
10
+ var hooks = require('@djangocfg/ui-core/hooks');
11
+ var consola = require('consola');
12
+ var lucideReact = require('lucide-react');
13
+ var lib = require('@djangocfg/ui-core/lib');
14
+ var jsxRuntime = require('react/jsx-runtime');
15
+ var zustand = require('zustand');
16
+ var middleware = require('zustand/middleware');
17
+
18
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
19
+
20
+ var React12__default = /*#__PURE__*/_interopDefault(React12);
21
+ var consola__default = /*#__PURE__*/_interopDefault(consola);
22
+
23
+ var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
24
+ var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl, schemaId, specRoot) => {
25
+ const endpoints = [];
26
+ if (!schema.paths) return [];
27
+ for (const [path, methods] of Object.entries(schema.paths)) {
28
+ for (const method of HTTP_METHODS) {
29
+ const op = methods[method];
30
+ if (!op) continue;
31
+ const methodUpper = method.toUpperCase();
32
+ const summary = (op.summary || "").trim();
33
+ const description = op.description || summary || `${methodUpper} ${path}`;
34
+ const category = op.tags?.[0] || "Other";
35
+ const parameters = [];
36
+ const allParams = [...methods.parameters || [], ...op.parameters || []];
37
+ for (const param of allParams) {
38
+ parameters.push({
39
+ name: param.name,
40
+ type: param.schema?.type || "string",
41
+ required: param.required || false,
42
+ description: param.description
43
+ });
44
+ }
45
+ const responses = [];
46
+ if (op.responses) {
47
+ for (const [code, response] of Object.entries(op.responses)) {
48
+ const respContent = response.content;
49
+ const contentKeys = respContent ? Object.keys(respContent) : [];
50
+ const chosenContentType = respContent?.["application/json"] ? "application/json" : contentKeys[0];
51
+ const chosen = chosenContentType ? respContent?.[chosenContentType] : void 0;
52
+ const respSchema = chosen?.schema;
53
+ responses.push({
54
+ code,
55
+ description: response.description || `Response ${code}`,
56
+ contentType: chosenContentType,
57
+ schema: respSchema,
58
+ example: respSchema ? chunk5Q4UMSWB_cjs.sampleSchemaJson(respSchema, { skipWriteOnly: true }, specRoot) : void 0
59
+ });
60
+ }
61
+ }
62
+ let requestBody;
63
+ if (op.requestBody) {
64
+ const content = op.requestBody.content;
65
+ const mediaType = content?.["application/json"] || content?.[Object.keys(content || {})[0]];
66
+ const rawSchema = mediaType?.schema;
67
+ requestBody = {
68
+ type: rawSchema?.type || "object",
69
+ description: op.requestBody.description,
70
+ schema: rawSchema,
71
+ example: rawSchema ? chunk5Q4UMSWB_cjs.sampleSchemaJson(rawSchema, { skipReadOnly: true }, specRoot) : void 0
72
+ };
73
+ }
74
+ const endpoint = {
75
+ name: path.split("/").pop() || path,
76
+ method: methodUpper,
77
+ path: baseUrl ? chunk5Q4UMSWB_cjs.joinUrl(baseUrl, path) : path,
78
+ summary,
79
+ description,
80
+ category,
81
+ parameters: parameters.length > 0 ? parameters : void 0,
82
+ requestBody,
83
+ responses: responses.length > 0 ? responses : void 0,
84
+ schemaId
85
+ };
86
+ endpoints.push(endpoint);
87
+ }
88
+ }
89
+ return endpoints;
90
+ }, "extractEndpoints");
91
+ var getCategories = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpoints) => {
92
+ const categories = /* @__PURE__ */ new Set();
93
+ endpoints.forEach((endpoint) => categories.add(endpoint.category));
94
+ return Array.from(categories).sort();
95
+ }, "getCategories");
96
+ var fetchSchema = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(async (url) => {
97
+ const response = await fetch(url, {
98
+ headers: {
99
+ "Accept": "application/json"
100
+ }
101
+ });
102
+ if (!response.ok) {
103
+ throw new Error(`Failed to fetch schema: ${response.statusText}`);
104
+ }
105
+ return response.json();
106
+ }, "fetchSchema");
107
+ function useOpenApiSchema({
108
+ schemas,
109
+ defaultSchemaId,
110
+ baseUrl: configBaseUrl,
111
+ preloadAll = false
112
+ }) {
113
+ const [loading, setLoading] = React12.useState(true);
114
+ const [error, setError] = React12.useState(null);
115
+ const [currentSchemaId, setCurrentSchemaId] = React12.useState(
116
+ defaultSchemaId || schemas[0]?.id
117
+ );
118
+ const [loadedSchemas, setLoadedSchemas] = React12.useState(
119
+ /* @__PURE__ */ new Map()
120
+ );
121
+ const [loadStates, setLoadStates] = React12.useState(/* @__PURE__ */ new Map());
122
+ const currentSchema = React12.useMemo(
123
+ () => schemas.find((s) => s.id === currentSchemaId) || null,
124
+ [schemas, currentSchemaId]
125
+ );
126
+ const currentOpenApiSchema = React12.useMemo(
127
+ () => currentSchemaId ? loadedSchemas.get(currentSchemaId) : null,
128
+ [loadedSchemas, currentSchemaId]
129
+ );
130
+ const dereferencedSchema = React12.useMemo(
131
+ () => currentOpenApiSchema ? chunk5Q4UMSWB_cjs.dereferenceSchema(currentOpenApiSchema) : null,
132
+ [currentOpenApiSchema]
133
+ );
134
+ const resolvedBaseUrl = React12.useMemo(
135
+ () => chunk5Q4UMSWB_cjs.resolveBaseUrl({
136
+ schemaSource: currentSchema?.baseUrl,
137
+ config: configBaseUrl,
138
+ fromServers: currentOpenApiSchema?.servers?.[0]?.url
139
+ }),
140
+ [currentSchema?.baseUrl, configBaseUrl, currentOpenApiSchema]
141
+ );
142
+ const endpoints = React12.useMemo(
143
+ () => dereferencedSchema ? extractEndpoints(dereferencedSchema, resolvedBaseUrl, currentSchemaId, currentOpenApiSchema ?? void 0) : [],
144
+ [dereferencedSchema, resolvedBaseUrl, currentSchemaId, currentOpenApiSchema]
145
+ );
146
+ const categories = React12.useMemo(() => getCategories(endpoints), [endpoints]);
147
+ const schemaInfo = React12.useMemo(() => {
148
+ if (!currentOpenApiSchema?.info) return null;
149
+ const { title, version, description } = currentOpenApiSchema.info;
150
+ return {
151
+ title,
152
+ version,
153
+ description,
154
+ servers: currentOpenApiSchema.servers
155
+ };
156
+ }, [currentOpenApiSchema]);
157
+ React12.useEffect(() => {
158
+ if (preloadAll) return;
159
+ if (!currentSchema) return;
160
+ if (loadedSchemas.has(currentSchema.id)) {
161
+ setLoading(false);
162
+ return;
163
+ }
164
+ setLoading(true);
165
+ setError(null);
166
+ fetchSchema(currentSchema.url).then((schema) => {
167
+ setLoadedSchemas((prev) => new Map(prev).set(currentSchema.id, schema));
168
+ consola__default.default.success(`Schema loaded: ${currentSchema.name}`);
169
+ setLoading(false);
170
+ }).catch((err) => {
171
+ consola__default.default.error(`Error loading schema from ${currentSchema.url}:`, err);
172
+ setError(err instanceof Error ? err.message : "Failed to load schema");
173
+ setLoading(false);
174
+ });
175
+ }, [currentSchema, loadedSchemas, preloadAll]);
176
+ React12.useEffect(() => {
177
+ if (!preloadAll) return;
178
+ if (schemas.length === 0) {
179
+ setLoading(false);
180
+ return;
181
+ }
182
+ let cancelled = false;
183
+ const pending = schemas.filter((s) => !loadedSchemas.has(s.id));
184
+ if (pending.length === 0) {
185
+ setLoading(false);
186
+ return;
187
+ }
188
+ setLoading(true);
189
+ setLoadStates((prev) => {
190
+ const next = new Map(prev);
191
+ for (const s of pending) next.set(s.id, { loading: true, error: null });
192
+ return next;
193
+ });
194
+ Promise.allSettled(
195
+ pending.map(
196
+ (s) => fetchSchema(s.url).then((schema) => ({ id: s.id, name: s.name, schema }))
197
+ )
198
+ ).then((results) => {
199
+ if (cancelled) return;
200
+ setLoadedSchemas((prev) => {
201
+ const next = new Map(prev);
202
+ for (const r of results) {
203
+ if (r.status === "fulfilled") {
204
+ next.set(r.value.id, r.value.schema);
205
+ consola__default.default.success(`Schema loaded: ${r.value.name}`);
206
+ }
207
+ }
208
+ return next;
209
+ });
210
+ setLoadStates((prev) => {
211
+ const next = new Map(prev);
212
+ results.forEach((r, i) => {
213
+ const src = pending[i];
214
+ if (r.status === "fulfilled") {
215
+ next.set(src.id, { loading: false, error: null });
216
+ } else {
217
+ const msg = r.reason instanceof Error ? r.reason.message : "Failed to load schema";
218
+ consola__default.default.error(`Error loading schema from ${src.url}:`, r.reason);
219
+ next.set(src.id, { loading: false, error: msg });
220
+ }
221
+ });
222
+ return next;
223
+ });
224
+ setLoading(false);
225
+ });
226
+ return () => {
227
+ cancelled = true;
228
+ };
229
+ }, [preloadAll, schemas, loadedSchemas]);
230
+ const schemasData = React12.useMemo(() => {
231
+ if (!preloadAll) return [];
232
+ return schemas.map((src) => {
233
+ const raw = loadedSchemas.get(src.id) ?? null;
234
+ const deref = raw ? chunk5Q4UMSWB_cjs.dereferenceSchema(raw) : null;
235
+ const resolved = chunk5Q4UMSWB_cjs.resolveBaseUrl({
236
+ schemaSource: src.baseUrl,
237
+ config: configBaseUrl,
238
+ fromServers: raw?.servers?.[0]?.url
239
+ });
240
+ const info = raw?.info ? {
241
+ title: raw.info.title,
242
+ version: raw.info.version,
243
+ description: raw.info.description,
244
+ servers: raw.servers
245
+ } : null;
246
+ const eps = deref ? extractEndpoints(deref, resolved, src.id, raw ?? void 0) : [];
247
+ const state = loadStates.get(src.id) ?? { loading: !raw, error: null };
248
+ return {
249
+ source: src,
250
+ info,
251
+ rawSchema: raw,
252
+ endpoints: eps,
253
+ resolvedBaseUrl: resolved || void 0,
254
+ loading: state.loading,
255
+ error: state.error
256
+ };
257
+ });
258
+ }, [preloadAll, schemas, loadedSchemas, loadStates, configBaseUrl]);
259
+ const setCurrentSchema = React12.useCallback((schemaId) => {
260
+ setCurrentSchemaId(schemaId);
261
+ }, []);
262
+ const refresh = React12.useCallback(() => {
263
+ if (!currentSchema) return;
264
+ setLoading(true);
265
+ setError(null);
266
+ setLoadedSchemas((prev) => {
267
+ const next = new Map(prev);
268
+ next.delete(currentSchema.id);
269
+ return next;
270
+ });
271
+ fetchSchema(currentSchema.url).then((schema) => {
272
+ setLoadedSchemas((prev) => new Map(prev).set(currentSchema.id, schema));
273
+ consola__default.default.success(`Schema refreshed: ${currentSchema.name}`);
274
+ setLoading(false);
275
+ }).catch((err) => {
276
+ consola__default.default.error(`Error refreshing schema from ${currentSchema.url}:`, err);
277
+ setError(err instanceof Error ? err.message : "Failed to refresh schema");
278
+ setLoading(false);
279
+ });
280
+ }, [currentSchema]);
281
+ return {
282
+ loading,
283
+ error,
284
+ endpoints,
285
+ categories,
286
+ schemas,
287
+ currentSchema,
288
+ schemaInfo,
289
+ rawSchema: currentOpenApiSchema ?? null,
290
+ // Consumers expect ``undefined`` when no base URL was resolved (for
291
+ // conditional ``{ baseUrl?: … }`` plumbing). Turn the empty-string
292
+ // convention from the resolver into undefined at the API boundary.
293
+ resolvedBaseUrl: resolvedBaseUrl || void 0,
294
+ setCurrentSchema,
295
+ refresh,
296
+ schemasData
297
+ };
298
+ }
299
+ chunkWGEGR3DF_cjs.__name(useOpenApiSchema, "useOpenApiSchema");
300
+ function parseDocsHash(hash) {
301
+ const raw = hash.startsWith("#") ? hash.slice(1) : hash;
302
+ if (!raw) return { schemaId: null, anchor: null };
303
+ const [schemaId = null, ...rest] = raw.split("/");
304
+ const anchor = rest.length > 0 ? rest.join("/") : null;
305
+ return {
306
+ schemaId: schemaId || null,
307
+ anchor: anchor || null
308
+ };
309
+ }
310
+ chunkWGEGR3DF_cjs.__name(parseDocsHash, "parseDocsHash");
311
+ function buildDocsHash(schemaId, anchor) {
312
+ if (!schemaId && !anchor) return "";
313
+ if (schemaId && anchor) return `#${schemaId}/${anchor}`;
314
+ if (schemaId) return `#${schemaId}`;
315
+ return anchor ? `#${anchor}` : "";
316
+ }
317
+ chunkWGEGR3DF_cjs.__name(buildDocsHash, "buildDocsHash");
318
+ function useDocsUrlSync({
319
+ enabled,
320
+ currentSchemaId,
321
+ activeAnchor,
322
+ onHashTarget
323
+ }) {
324
+ const primedRef = React12.useRef(false);
325
+ const onHashTargetRef = React12.useRef(onHashTarget);
326
+ React12.useEffect(() => {
327
+ onHashTargetRef.current = onHashTarget;
328
+ }, [onHashTarget]);
329
+ React12.useEffect(() => {
330
+ if (!enabled || typeof window === "undefined") return;
331
+ const apply = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
332
+ onHashTargetRef.current(parseDocsHash(window.location.hash));
333
+ }, "apply");
334
+ apply();
335
+ primedRef.current = true;
336
+ window.addEventListener("hashchange", apply);
337
+ window.addEventListener("popstate", apply);
338
+ return () => {
339
+ window.removeEventListener("hashchange", apply);
340
+ window.removeEventListener("popstate", apply);
341
+ };
342
+ }, [enabled]);
343
+ React12.useEffect(() => {
344
+ if (!enabled || typeof window === "undefined") return;
345
+ if (!primedRef.current) return;
346
+ const next = buildDocsHash(currentSchemaId, activeAnchor);
347
+ const current = window.location.hash;
348
+ if (next === current) return;
349
+ const url = next ? `${window.location.pathname}${window.location.search}${next}` : `${window.location.pathname}${window.location.search}`;
350
+ window.history.replaceState(window.history.state, "", url);
351
+ }, [enabled, currentSchemaId, activeAnchor]);
352
+ const pushTarget = React12.useCallback(
353
+ (schemaId, anchor) => {
354
+ if (!enabled || typeof window === "undefined") return;
355
+ const next = buildDocsHash(schemaId, anchor);
356
+ const url = next ? `${window.location.pathname}${window.location.search}${next}` : `${window.location.pathname}${window.location.search}`;
357
+ window.history.pushState(window.history.state, "", url);
358
+ },
359
+ [enabled]
360
+ );
361
+ return { pushTarget };
362
+ }
363
+ chunkWGEGR3DF_cjs.__name(useDocsUrlSync, "useDocsUrlSync");
364
+ var EMPTY_DRAFT = { parameters: {}, requestBody: "" };
365
+ function storageKey(schemaId, ep) {
366
+ if (!schemaId || !ep) return null;
367
+ return `openapi-playground:draft:${schemaId}:${ep.method}:${ep.path}`;
368
+ }
369
+ chunkWGEGR3DF_cjs.__name(storageKey, "storageKey");
370
+ function readDraft(key) {
371
+ if (!key || typeof window === "undefined") return EMPTY_DRAFT;
372
+ try {
373
+ const raw = window.localStorage.getItem(key);
374
+ if (!raw) return EMPTY_DRAFT;
375
+ const parsed = JSON.parse(raw);
376
+ return {
377
+ parameters: parsed?.parameters ?? {},
378
+ requestBody: typeof parsed?.requestBody === "string" ? parsed.requestBody : ""
379
+ };
380
+ } catch {
381
+ return EMPTY_DRAFT;
382
+ }
383
+ }
384
+ chunkWGEGR3DF_cjs.__name(readDraft, "readDraft");
385
+ function writeDraft(key, value) {
386
+ if (!key || typeof window === "undefined") return;
387
+ try {
388
+ if (Object.keys(value.parameters).length === 0 && !value.requestBody) {
389
+ window.localStorage.removeItem(key);
390
+ return;
391
+ }
392
+ window.localStorage.setItem(key, JSON.stringify(value));
393
+ } catch {
394
+ }
395
+ }
396
+ chunkWGEGR3DF_cjs.__name(writeDraft, "writeDraft");
397
+ function useEndpointDraft(schemaId, endpoint) {
398
+ const key = storageKey(schemaId, endpoint);
399
+ const [draft, setDraftSnapshot] = React12.useState(() => readDraft(key));
400
+ const loadedKeyRef = React12.useRef(key);
401
+ React12.useEffect(() => {
402
+ if (loadedKeyRef.current === key) return;
403
+ loadedKeyRef.current = key;
404
+ setDraftSnapshot(readDraft(key));
405
+ }, [key]);
406
+ const keyRef = React12.useRef(key);
407
+ React12.useEffect(() => {
408
+ keyRef.current = key;
409
+ }, [key]);
410
+ const latestRef = React12.useRef(draft);
411
+ React12.useEffect(() => {
412
+ latestRef.current = draft;
413
+ }, [draft]);
414
+ const setParameters = React12.useCallback((params) => {
415
+ const next = {
416
+ parameters: params,
417
+ requestBody: latestRef.current.requestBody
418
+ };
419
+ latestRef.current = next;
420
+ writeDraft(keyRef.current, next);
421
+ }, []);
422
+ const setRequestBody = React12.useCallback((body) => {
423
+ const next = {
424
+ parameters: latestRef.current.parameters,
425
+ requestBody: body
426
+ };
427
+ latestRef.current = next;
428
+ writeDraft(keyRef.current, next);
429
+ }, []);
430
+ const reset = React12.useCallback(() => {
431
+ latestRef.current = EMPTY_DRAFT;
432
+ if (keyRef.current && typeof window !== "undefined") {
433
+ try {
434
+ window.localStorage.removeItem(keyRef.current);
435
+ } catch {
436
+ }
437
+ }
438
+ setDraftSnapshot(EMPTY_DRAFT);
439
+ }, []);
440
+ return { draft, setParameters, setRequestBody, reset };
441
+ }
442
+ chunkWGEGR3DF_cjs.__name(useEndpointDraft, "useEndpointDraft");
443
+
444
+ // src/tools/OpenapiViewer/components/shared/EndpointDraftSync.tsx
445
+ function EndpointDraftSync({ schemaId }) {
446
+ const { state, setParameters, setRequestBody, setActiveSchemaId } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
447
+ const ep = state.selectedEndpoint;
448
+ React12.useEffect(() => {
449
+ setActiveSchemaId(schemaId);
450
+ }, [schemaId, setActiveSchemaId]);
451
+ const { draft, setParameters: persistParams, setRequestBody: persistBody } = useEndpointDraft(schemaId, ep);
452
+ const lastLoadedKeyRef = React12.useRef(null);
453
+ const lastPersistedParamsRef = React12.useRef("");
454
+ const lastPersistedBodyRef = React12.useRef("");
455
+ const currentKey = ep ? `${ep.method}|${ep.path}` : null;
456
+ React12.useEffect(() => {
457
+ if (!ep || !currentKey) {
458
+ lastLoadedKeyRef.current = null;
459
+ return;
460
+ }
461
+ if (lastLoadedKeyRef.current === currentKey) return;
462
+ lastLoadedKeyRef.current = currentKey;
463
+ const hasStoredParams = draft.parameters && Object.keys(draft.parameters).length > 0;
464
+ const hasStoredBody = typeof draft.requestBody === "string" && draft.requestBody !== "";
465
+ if (hasStoredParams) {
466
+ setParameters(draft.parameters);
467
+ lastPersistedParamsRef.current = JSON.stringify(draft.parameters);
468
+ } else {
469
+ lastPersistedParamsRef.current = JSON.stringify(state.parameters);
470
+ }
471
+ if (hasStoredBody) {
472
+ setRequestBody(draft.requestBody);
473
+ lastPersistedBodyRef.current = draft.requestBody;
474
+ } else {
475
+ lastPersistedBodyRef.current = state.requestBody;
476
+ }
477
+ }, [currentKey]);
478
+ React12.useEffect(() => {
479
+ if (!ep || lastLoadedKeyRef.current !== currentKey) return;
480
+ const serialised = JSON.stringify(state.parameters);
481
+ if (serialised === lastPersistedParamsRef.current) return;
482
+ lastPersistedParamsRef.current = serialised;
483
+ persistParams(state.parameters);
484
+ }, [state.parameters, ep, currentKey, persistParams]);
485
+ React12.useEffect(() => {
486
+ if (!ep || lastLoadedKeyRef.current !== currentKey) return;
487
+ if (state.requestBody === lastPersistedBodyRef.current) return;
488
+ lastPersistedBodyRef.current = state.requestBody;
489
+ persistBody(state.requestBody);
490
+ }, [state.requestBody, ep, currentKey, persistBody]);
491
+ return null;
492
+ }
493
+ chunkWGEGR3DF_cjs.__name(EndpointDraftSync, "EndpointDraftSync");
494
+
495
+ // src/tools/OpenapiViewer/components/DocsLayout/anchor.ts
496
+ function endpointAnchor(ep, schemaId) {
497
+ const slug = ep.path.replace(/^https?:\/\/[^/]+/, "").replace(/[{}]/g, "").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
498
+ const schemaSlug = schemaId ? `${slugifySchemaId(schemaId)}-` : "";
499
+ return `ep-${schemaSlug}${ep.method.toLowerCase()}-${slug}`;
500
+ }
501
+ chunkWGEGR3DF_cjs.__name(endpointAnchor, "endpointAnchor");
502
+ function slugifySchemaId(id) {
503
+ return id.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
504
+ }
505
+ chunkWGEGR3DF_cjs.__name(slugifySchemaId, "slugifySchemaId");
506
+ var METHOD_STYLES = {
507
+ GET: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/25",
508
+ POST: "bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/25",
509
+ PUT: "bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/25",
510
+ PATCH: "bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/25",
511
+ DELETE: "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/25"
512
+ };
513
+ var METHOD_FALLBACK = "bg-muted text-muted-foreground border-border";
514
+ function getMethodStyle(method) {
515
+ return METHOD_STYLES[method.toUpperCase()] ?? METHOD_FALLBACK;
516
+ }
517
+ chunkWGEGR3DF_cjs.__name(getMethodStyle, "getMethodStyle");
518
+ function getStatusStyle(status) {
519
+ if (status >= 500) return "bg-red-500/10 text-red-500 dark:text-red-400 border-red-500/25";
520
+ if (status >= 400) return "bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/25";
521
+ if (status >= 300) return "bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/25";
522
+ return "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/25";
523
+ }
524
+ chunkWGEGR3DF_cjs.__name(getStatusStyle, "getStatusStyle");
525
+ function MethodBadge({ method }) {
526
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn(
527
+ "inline-flex shrink-0 items-center rounded border px-1.5 py-px",
528
+ "font-mono text-[10px] font-bold uppercase tracking-wider leading-none",
529
+ getMethodStyle(method)
530
+ ), children: method });
531
+ }
532
+ chunkWGEGR3DF_cjs.__name(MethodBadge, "MethodBadge");
533
+ function StatusBadge({ status }) {
534
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn(
535
+ "inline-flex items-center rounded border px-1.5 py-px",
536
+ "font-mono text-[11px] font-bold leading-none",
537
+ getStatusStyle(status)
538
+ ), children: status });
539
+ }
540
+ chunkWGEGR3DF_cjs.__name(StatusBadge, "StatusBadge");
541
+ function SectionLabel({ children }) {
542
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60 select-none", children });
543
+ }
544
+ chunkWGEGR3DF_cjs.__name(SectionLabel, "SectionLabel");
545
+ function Panel({ children, className }) {
546
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: lib.cn("flex flex-col min-h-0 overflow-hidden", className), children });
547
+ }
548
+ chunkWGEGR3DF_cjs.__name(Panel, "Panel");
549
+ function ScrollArea({ children, className }) {
550
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: lib.cn("flex-1 overflow-y-auto min-h-0", className), children });
551
+ }
552
+ chunkWGEGR3DF_cjs.__name(ScrollArea, "ScrollArea");
553
+ function EmptyState({
554
+ icon: Icon,
555
+ text,
556
+ className
557
+ }) {
558
+ return /* @__PURE__ */ jsxRuntime.jsxs(
559
+ "div",
560
+ {
561
+ className: lib.cn(
562
+ "flex flex-col items-center justify-center h-full gap-3 px-6 text-center",
563
+ className
564
+ ),
565
+ children: [
566
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-7 w-7 text-muted-foreground/25" }),
567
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: text })
568
+ ]
569
+ }
570
+ );
571
+ }
572
+ chunkWGEGR3DF_cjs.__name(EmptyState, "EmptyState");
573
+ function CollapsibleSection({
574
+ label,
575
+ action,
576
+ children,
577
+ defaultOpen = false
578
+ }) {
579
+ const [open, setOpen] = React12__default.default.useState(defaultOpen);
580
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0", children: [
581
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
582
+ /* @__PURE__ */ jsxRuntime.jsxs(
583
+ "button",
584
+ {
585
+ type: "button",
586
+ onClick: () => setOpen((v) => !v),
587
+ className: "flex items-center gap-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60 hover:text-muted-foreground transition-colors py-1",
588
+ children: [
589
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: lib.cn("h-3 w-3 transition-transform", open && "rotate-90") }),
590
+ label
591
+ ]
592
+ }
593
+ ),
594
+ action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: action })
595
+ ] }),
596
+ open && /* @__PURE__ */ jsxRuntime.jsx("div", { children })
597
+ ] });
598
+ }
599
+ chunkWGEGR3DF_cjs.__name(CollapsibleSection, "CollapsibleSection");
600
+ var FLAVOUR_LABELS = {
601
+ markdown: {
602
+ title: "Markdown for LLM",
603
+ hint: "Endpoints + params as prose. Smallest."
604
+ },
605
+ compact: {
606
+ title: "Compact JSON",
607
+ hint: "Dereferenced, no examples, minified."
608
+ },
609
+ raw: {
610
+ title: "Raw JSON",
611
+ hint: "Full OpenAPI document with $refs."
612
+ }
613
+ };
614
+ function SchemaCopyMenu({ schema, endpoints, baseUrl, variant = "button" }) {
615
+ const [sizeCache, setSizeCache] = React12.useState({});
616
+ const [justCopied, setJustCopied] = React12.useState(null);
617
+ const [open, setOpen] = React12.useState(false);
618
+ const isReady = schema !== null && endpoints.length > 0;
619
+ const build = React12.useCallback(
620
+ (flavour) => {
621
+ if (!schema) return "";
622
+ if (flavour === "markdown") return chunk5Q4UMSWB_cjs.toMarkdown(schema, endpoints, baseUrl);
623
+ if (flavour === "compact") return chunk5Q4UMSWB_cjs.toCompactJson(schema, baseUrl);
624
+ return chunk5Q4UMSWB_cjs.toRawJson(schema, baseUrl);
625
+ },
626
+ [schema, endpoints, baseUrl]
627
+ );
628
+ const handleCopy = React12.useCallback(
629
+ async (flavour) => {
630
+ if (!isReady) return;
631
+ const text = build(flavour);
632
+ const label = FLAVOUR_LABELS[flavour].title;
633
+ try {
634
+ await navigator.clipboard.writeText(text);
635
+ const size = chunk5Q4UMSWB_cjs.formatBytes(text);
636
+ setSizeCache((prev) => ({ ...prev, [flavour]: size }));
637
+ setJustCopied(flavour);
638
+ setTimeout(() => setJustCopied(null), 1500);
639
+ setOpen(false);
640
+ hooks.toast.success(`Copied ${label}`, { description: size });
641
+ } catch (err) {
642
+ const message = err instanceof Error ? err.message : "Clipboard permission denied";
643
+ hooks.toast.error("Copy failed", { description: message });
644
+ }
645
+ },
646
+ [build, isReady]
647
+ );
648
+ const flavours = React12.useMemo(() => ["markdown", "compact", "raw"], []);
649
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.DropdownMenu, { open, onOpenChange: setOpen, children: [
650
+ /* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuTrigger, { asChild: true, children: variant === "icon" ? /* @__PURE__ */ jsxRuntime.jsx(
651
+ components.Button,
652
+ {
653
+ variant: "ghost",
654
+ size: "icon",
655
+ className: "h-7 w-7 shrink-0",
656
+ disabled: !isReady,
657
+ title: "Copy schema for AI",
658
+ "aria-label": "Copy schema for AI",
659
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" })
660
+ }
661
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(components.Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: !isReady, children: [
662
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3 w-3" }),
663
+ "Copy for AI",
664
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3 w-3 opacity-60" })
665
+ ] }) }),
666
+ /* @__PURE__ */ jsxRuntime.jsxs(
667
+ components.DropdownMenuContent,
668
+ {
669
+ side: "right",
670
+ align: "start",
671
+ sideOffset: 6,
672
+ collisionPadding: 8,
673
+ className: "w-60 max-w-[calc(100vw-16px)]",
674
+ children: [
675
+ /* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuLabel, { className: "text-[10px] uppercase tracking-wider text-muted-foreground/70", children: "Copy schema" }),
676
+ /* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuSeparator, {}),
677
+ flavours.map((f) => {
678
+ const label = FLAVOUR_LABELS[f];
679
+ const size = sizeCache[f];
680
+ const isDone = justCopied === f;
681
+ return /* @__PURE__ */ jsxRuntime.jsxs(
682
+ components.DropdownMenuItem,
683
+ {
684
+ onClick: (e) => {
685
+ e.preventDefault();
686
+ void handleCopy(f);
687
+ },
688
+ className: "flex flex-col items-start gap-0.5 py-2 cursor-pointer",
689
+ children: [
690
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2", children: [
691
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium flex-1", children: label.title }),
692
+ isDone ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-[10px] text-emerald-500", children: [
693
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" }),
694
+ " Copied"
695
+ ] }) : size ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-mono text-muted-foreground/70 tabular-nums", children: size }) : null
696
+ ] }),
697
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/70 leading-snug line-clamp-1", children: label.hint })
698
+ ]
699
+ },
700
+ f
701
+ );
702
+ })
703
+ ]
704
+ }
705
+ )
706
+ ] });
707
+ }
708
+ chunkWGEGR3DF_cjs.__name(SchemaCopyMenu, "SchemaCopyMenu");
709
+ function BrandHeader({ info, endpoints, rawSchema, resolvedBaseUrl }) {
710
+ const apiTitle = info?.title ?? "API Reference";
711
+ const copyReady = rawSchema !== null && rawSchema !== void 0 && endpoints.length > 0;
712
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-3 py-2.5 flex items-start gap-2", children: [
713
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
714
+ /* @__PURE__ */ jsxRuntime.jsx(
715
+ "div",
716
+ {
717
+ className: "text-[13px] font-semibold text-foreground leading-tight truncate",
718
+ title: apiTitle,
719
+ children: apiTitle
720
+ }
721
+ ),
722
+ info?.version && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-[10px] text-muted-foreground/60 leading-tight mt-0.5", children: [
723
+ "v",
724
+ info.version
725
+ ] })
726
+ ] }),
727
+ copyReady && /* @__PURE__ */ jsxRuntime.jsx(
728
+ SchemaCopyMenu,
729
+ {
730
+ schema: rawSchema ?? null,
731
+ endpoints,
732
+ baseUrl: resolvedBaseUrl,
733
+ variant: "icon"
734
+ }
735
+ )
736
+ ] });
737
+ }
738
+ chunkWGEGR3DF_cjs.__name(BrandHeader, "BrandHeader");
739
+
740
+ // src/tools/OpenapiViewer/components/DocsLayout/sidebarLabel.ts
741
+ function longestCommonPrefix(paths) {
742
+ if (paths.length === 0) return "";
743
+ if (paths.length === 1) return "";
744
+ const segments = paths.map((p) => p.split("/"));
745
+ const minLen = Math.min(...segments.map((s) => s.length));
746
+ const shared = [];
747
+ for (let i = 0; i < minLen; i++) {
748
+ const first = segments[0][i];
749
+ if (segments.every((s) => s[i] === first)) {
750
+ shared.push(first);
751
+ } else {
752
+ break;
753
+ }
754
+ }
755
+ const joined = shared.join("/");
756
+ return joined;
757
+ }
758
+ chunkWGEGR3DF_cjs.__name(longestCommonPrefix, "longestCommonPrefix");
759
+ function sidebarLabel(ep, groupCommonPrefix) {
760
+ if (ep.summary) return ep.summary;
761
+ if (groupCommonPrefix && ep.path.startsWith(groupCommonPrefix)) {
762
+ const tail = ep.path.slice(groupCommonPrefix.length) || "/";
763
+ return tail;
764
+ }
765
+ return relativePath2(ep.path);
766
+ }
767
+ chunkWGEGR3DF_cjs.__name(sidebarLabel, "sidebarLabel");
768
+ function relativePath2(full) {
769
+ try {
770
+ return new URL(full).pathname;
771
+ } catch {
772
+ return full;
773
+ }
774
+ }
775
+ chunkWGEGR3DF_cjs.__name(relativePath2, "relativePath");
776
+ function sidebarTooltip(ep) {
777
+ return `${ep.method} ${relativePath2(ep.path)}`;
778
+ }
779
+ chunkWGEGR3DF_cjs.__name(sidebarTooltip, "sidebarTooltip");
780
+
781
+ // src/tools/OpenapiViewer/components/DocsLayout/grouping.ts
782
+ var METHOD_ORDER = {
783
+ GET: 0,
784
+ POST: 1,
785
+ PUT: 2,
786
+ PATCH: 3,
787
+ DELETE: 4
788
+ };
789
+ var methodRank = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((ep) => METHOD_ORDER[ep.method] ?? 99, "methodRank");
790
+ function groupEndpoints(list) {
791
+ const byCategory = lodashEs.groupBy(list, "category");
792
+ const all = Object.entries(byCategory).map(([category, endpoints]) => ({
793
+ category,
794
+ endpoints: lodashEs.orderBy(endpoints, ["path", methodRank], ["asc", "asc"]),
795
+ commonPrefix: longestCommonPrefix(endpoints.map((e) => e.path))
796
+ }));
797
+ const [other, named] = lodashEs.partition(all, (g) => g.category === "Other");
798
+ return [...lodashEs.sortBy(named, (g) => g.category.toLowerCase()), ...other];
799
+ }
800
+ chunkWGEGR3DF_cjs.__name(groupEndpoints, "groupEndpoints");
801
+ function buildSchemaSections(sources, endpointsBySchema) {
802
+ return sources.map((source) => ({
803
+ source,
804
+ groups: groupEndpoints(endpointsBySchema[source.id] ?? [])
805
+ }));
806
+ }
807
+ chunkWGEGR3DF_cjs.__name(buildSchemaSections, "buildSchemaSections");
808
+
809
+ // src/tools/OpenapiViewer/components/DocsLayout/Sidebar/buildVM.ts
810
+ function filterEndpoints(list, query, method) {
811
+ let out = list;
812
+ if (method !== "ALL") {
813
+ out = out.filter((e) => e.method === method);
814
+ }
815
+ if (query) {
816
+ const q = query.toLowerCase();
817
+ out = out.filter(
818
+ (e) => e.summary.toLowerCase().includes(q) || e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.path.toLowerCase().includes(q)
819
+ );
820
+ }
821
+ return out;
822
+ }
823
+ chunkWGEGR3DF_cjs.__name(filterEndpoints, "filterEndpoints");
824
+ function buildCategory(group, activeEndpointId, schemaId, keyPrefix) {
825
+ const rows = group.endpoints.map((ep) => {
826
+ const anchor = endpointAnchor(ep, schemaId ?? ep.schemaId ?? null);
827
+ return {
828
+ key: `${ep.method}-${ep.path}`,
829
+ anchor,
830
+ schemaId: schemaId ?? ep.schemaId ?? null,
831
+ label: sidebarLabel(ep, group.commonPrefix),
832
+ tooltip: sidebarTooltip(ep),
833
+ method: ep.method,
834
+ useMono: !ep.summary,
835
+ isActive: activeEndpointId === anchor
836
+ };
837
+ });
838
+ return {
839
+ key: `${keyPrefix}${group.category}`,
840
+ category: group.category,
841
+ rows
842
+ };
843
+ }
844
+ chunkWGEGR3DF_cjs.__name(buildCategory, "buildCategory");
845
+ function emptyTextFor(query, method, defaultText) {
846
+ if (query && method !== "ALL") return `No ${method} endpoints match "${query}"`;
847
+ if (query) return `No endpoints match "${query}"`;
848
+ if (method !== "ALL") return `No ${method} endpoints`;
849
+ return defaultText;
850
+ }
851
+ chunkWGEGR3DF_cjs.__name(emptyTextFor, "emptyTextFor");
852
+ function buildFlatVM(endpoints, selectedVersion, query, method, activeEndpointId) {
853
+ const filtered = filterEndpoints(
854
+ chunk5Q4UMSWB_cjs.deduplicateEndpoints(endpoints, selectedVersion),
855
+ query,
856
+ method
857
+ );
858
+ const groups = groupEndpoints(filtered);
859
+ return {
860
+ kind: "flat",
861
+ categories: groups.map((g) => buildCategory(g, activeEndpointId, null, "")),
862
+ emptyText: emptyTextFor(query, method, "No endpoints in this schema")
863
+ };
864
+ }
865
+ chunkWGEGR3DF_cjs.__name(buildFlatVM, "buildFlatVM");
866
+ function buildSectionsVM(schemas, endpointsBySchema, selectedVersion, query, method, activeEndpointId) {
867
+ const filteredMap = {};
868
+ for (const src of schemas) {
869
+ const raw = endpointsBySchema[src.id] ?? [];
870
+ filteredMap[src.id] = filterEndpoints(
871
+ chunk5Q4UMSWB_cjs.deduplicateEndpoints(raw, selectedVersion),
872
+ query,
873
+ method
874
+ );
875
+ }
876
+ const rawSections = buildSchemaSections(schemas, filteredMap);
877
+ const sections = rawSections.filter((s) => s.groups.length > 0).map((s) => ({
878
+ sourceId: s.source.id,
879
+ sourceName: s.source.name,
880
+ categories: s.groups.map(
881
+ (g) => buildCategory(g, activeEndpointId, s.source.id, `${s.source.id}-`)
882
+ )
883
+ }));
884
+ return {
885
+ kind: "sections",
886
+ sections,
887
+ emptyText: emptyTextFor(query, method, "No endpoints in any schema")
888
+ };
889
+ }
890
+ chunkWGEGR3DF_cjs.__name(buildSectionsVM, "buildSectionsVM");
891
+ var EndpointRow = React12__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function EndpointRow2({
892
+ row,
893
+ onNavigate
894
+ }) {
895
+ const displayLabel = row.label.replace(/\.$/, "");
896
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.Tooltip, { delayDuration: 350, children: [
897
+ /* @__PURE__ */ jsxRuntime.jsx(components.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
898
+ "button",
899
+ {
900
+ onClick: () => onNavigate(row.anchor, row.schemaId),
901
+ "aria-current": row.isActive ? "location" : void 0,
902
+ className: lib.cn(
903
+ "relative w-full text-left grid grid-cols-[52px_minmax(0,1fr)] items-baseline gap-2 pl-3 pr-3 py-1 transition-colors",
904
+ row.isActive ? "bg-primary/10 text-foreground" : "hover:bg-muted/40 text-foreground/75 hover:text-foreground"
905
+ ),
906
+ children: [
907
+ row.isActive && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded-r bg-primary" }),
908
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "justify-self-start", children: /* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: row.method }) }),
909
+ /* @__PURE__ */ jsxRuntime.jsx(
910
+ "span",
911
+ {
912
+ className: lib.cn(
913
+ "line-clamp-2 leading-snug min-w-0",
914
+ row.useMono ? "font-mono text-[11px] break-all" : "text-[12px]",
915
+ row.isActive && "text-foreground font-medium"
916
+ ),
917
+ children: displayLabel
918
+ }
919
+ )
920
+ ]
921
+ }
922
+ ) }),
923
+ /* @__PURE__ */ jsxRuntime.jsx(components.TooltipContent, { side: "right", align: "center", className: "font-mono text-[11px]", children: row.tooltip })
924
+ ] });
925
+ }, "EndpointRow"));
926
+ var CategoryBlock = React12__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function CategoryBlock2({
927
+ category,
928
+ onNavigate
929
+ }) {
930
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2.5 last:mb-1", children: [
931
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-3 pb-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/50 select-none", children: category.category }),
932
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: category.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(EndpointRow, { row, onNavigate }, row.key)) })
933
+ ] });
934
+ }, "CategoryBlock"));
935
+ function SchemaSection({ section, onNavigate }) {
936
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 last:mb-2", children: [
937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-1.5 sticky top-0 z-[1] bg-background/95 backdrop-blur-[2px] border-b border-border/40", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold uppercase tracking-[0.12em] text-foreground/80", children: section.sourceName }) }),
938
+ section.categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBlock, { category: cat, onNavigate }, cat.key))
939
+ ] });
940
+ }
941
+ chunkWGEGR3DF_cjs.__name(SchemaSection, "SchemaSection");
942
+ function SidebarBody({ body, onNavigate }) {
943
+ if (body.kind === "flat") {
944
+ if (body.categories.length === 0) {
945
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: body.emptyText });
946
+ }
947
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-1.5", children: body.categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBlock, { category: cat, onNavigate }, cat.key)) });
948
+ }
949
+ if (body.sections.length === 0) {
950
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: body.emptyText });
951
+ }
952
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-1.5", children: body.sections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(SchemaSection, { section, onNavigate }, section.sourceId)) });
953
+ }
954
+ chunkWGEGR3DF_cjs.__name(SidebarBody, "SidebarBody");
955
+
956
+ // src/tools/OpenapiViewer/components/DocsLayout/Sidebar/types.ts
957
+ var METHOD_FILTERS = ["ALL", "GET", "POST", "PUT", "PATCH", "DELETE"];
958
+ function MethodChips({ value, onChange }) {
959
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 overflow-x-auto -mx-1 px-1 pb-px", children: METHOD_FILTERS.map((m) => {
960
+ const active = value === m;
961
+ return /* @__PURE__ */ jsxRuntime.jsx(
962
+ "button",
963
+ {
964
+ type: "button",
965
+ onClick: () => onChange(m),
966
+ "aria-pressed": active,
967
+ className: lib.cn(
968
+ "shrink-0 px-2 h-6 rounded font-mono text-[10px] font-semibold tracking-wide uppercase transition-colors",
969
+ active ? "bg-foreground text-background" : "text-muted-foreground/70 hover:text-foreground hover:bg-muted"
970
+ ),
971
+ children: m
972
+ },
973
+ m
974
+ );
975
+ }) });
976
+ }
977
+ chunkWGEGR3DF_cjs.__name(MethodChips, "MethodChips");
978
+ function SearchInput({ value, onChange, placeholder }) {
979
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
980
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/50 pointer-events-none" }),
981
+ /* @__PURE__ */ jsxRuntime.jsx(
982
+ components.Input,
983
+ {
984
+ placeholder: placeholder ?? "Search endpoints\u2026",
985
+ value,
986
+ onChange: (e) => onChange(e.target.value),
987
+ className: "pl-8 pr-7 h-8 text-xs"
988
+ }
989
+ ),
990
+ value && /* @__PURE__ */ jsxRuntime.jsx(
991
+ "button",
992
+ {
993
+ type: "button",
994
+ onClick: () => onChange(""),
995
+ "aria-label": "Clear search",
996
+ className: lib.cn(
997
+ "absolute right-1.5 top-1/2 -translate-y-1/2 h-5 w-5 rounded",
998
+ "inline-flex items-center justify-center",
999
+ "text-muted-foreground/50 hover:text-foreground hover:bg-muted transition-colors"
1000
+ ),
1001
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3 w-3" })
1002
+ }
1003
+ )
1004
+ ] });
1005
+ }
1006
+ chunkWGEGR3DF_cjs.__name(SearchInput, "SearchInput");
1007
+ function Toolbar({
1008
+ schemas,
1009
+ currentSchemaId,
1010
+ onSchemaChange,
1011
+ showSchemaSelector,
1012
+ search,
1013
+ onSearchChange,
1014
+ methodFilter,
1015
+ onMethodFilterChange
1016
+ }) {
1017
+ const schemaOptions = React12__default.default.useMemo(
1018
+ () => schemas.map((s) => ({ value: s.id, label: s.name })),
1019
+ [schemas]
1020
+ );
1021
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-3 py-2.5 space-y-2", children: [
1022
+ showSchemaSelector && /* @__PURE__ */ jsxRuntime.jsx(
1023
+ components.Combobox,
1024
+ {
1025
+ options: schemaOptions,
1026
+ value: currentSchemaId ?? "",
1027
+ onValueChange: (id) => id && onSchemaChange(id),
1028
+ placeholder: "Select API",
1029
+ searchPlaceholder: "Search APIs\u2026",
1030
+ emptyText: "No APIs found",
1031
+ className: "w-full h-8 text-xs"
1032
+ }
1033
+ ),
1034
+ /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { value: search, onChange: onSearchChange }),
1035
+ /* @__PURE__ */ jsxRuntime.jsx(MethodChips, { value: methodFilter, onChange: onMethodFilterChange })
1036
+ ] });
1037
+ }
1038
+ chunkWGEGR3DF_cjs.__name(Toolbar, "Toolbar");
1039
+ function useDebouncedValue(value, delayMs = 120) {
1040
+ const [debounced, setDebounced] = React12.useState(value);
1041
+ React12.useEffect(() => {
1042
+ const id = setTimeout(() => setDebounced(value), delayMs);
1043
+ return () => clearTimeout(id);
1044
+ }, [value, delayMs]);
1045
+ return debounced;
1046
+ }
1047
+ chunkWGEGR3DF_cjs.__name(useDebouncedValue, "useDebouncedValue");
1048
+ function DocsSidebar({
1049
+ info,
1050
+ endpoints,
1051
+ schemas,
1052
+ currentSchemaId,
1053
+ onSchemaChange,
1054
+ activeEndpointId,
1055
+ selectedVersion,
1056
+ onNavigate,
1057
+ grouping = "selector",
1058
+ endpointsBySchema,
1059
+ rawSchema,
1060
+ resolvedBaseUrl
1061
+ }) {
1062
+ const [search, setSearch] = React12.useState("");
1063
+ const [methodFilter, setMethodFilter] = React12.useState("ALL");
1064
+ const debouncedSearch = useDebouncedValue(search);
1065
+ const body = React12.useMemo(() => {
1066
+ if (grouping === "sections") {
1067
+ return buildSectionsVM(
1068
+ schemas,
1069
+ endpointsBySchema ?? {},
1070
+ selectedVersion,
1071
+ debouncedSearch,
1072
+ methodFilter,
1073
+ activeEndpointId
1074
+ );
1075
+ }
1076
+ return buildFlatVM(
1077
+ endpoints,
1078
+ selectedVersion,
1079
+ debouncedSearch,
1080
+ methodFilter,
1081
+ activeEndpointId
1082
+ );
1083
+ }, [
1084
+ grouping,
1085
+ schemas,
1086
+ endpointsBySchema,
1087
+ endpoints,
1088
+ selectedVersion,
1089
+ debouncedSearch,
1090
+ methodFilter,
1091
+ activeEndpointId
1092
+ ]);
1093
+ const hasMultipleSchemas = schemas.length > 1;
1094
+ const showSchemaSelector = grouping === "selector" && hasMultipleSchemas;
1095
+ return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "flex flex-col h-full min-h-0 border-r bg-muted/10", children: [
1096
+ /* @__PURE__ */ jsxRuntime.jsx(
1097
+ BrandHeader,
1098
+ {
1099
+ info,
1100
+ endpoints,
1101
+ rawSchema,
1102
+ resolvedBaseUrl
1103
+ }
1104
+ ),
1105
+ /* @__PURE__ */ jsxRuntime.jsx(
1106
+ Toolbar,
1107
+ {
1108
+ schemas,
1109
+ currentSchemaId,
1110
+ onSchemaChange,
1111
+ showSchemaSelector,
1112
+ search,
1113
+ onSearchChange: setSearch,
1114
+ methodFilter,
1115
+ onMethodFilterChange: setMethodFilter
1116
+ }
1117
+ ),
1118
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarBody, { body, onNavigate }) })
1119
+ ] });
1120
+ }
1121
+ chunkWGEGR3DF_cjs.__name(DocsSidebar, "DocsSidebar");
1122
+
1123
+ // src/tools/OpenapiViewer/utils/scrollParent.ts
1124
+ function getScrollParent(el) {
1125
+ if (typeof window === "undefined") return null;
1126
+ if (!el) return window;
1127
+ let cur = el.parentElement;
1128
+ while (cur && cur !== document.body && cur !== document.documentElement) {
1129
+ const style = getComputedStyle(cur);
1130
+ const overflowY = style.overflowY;
1131
+ const canScroll = (overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay") && cur.scrollHeight > cur.clientHeight;
1132
+ if (canScroll) return cur;
1133
+ cur = cur.parentElement;
1134
+ }
1135
+ return window;
1136
+ }
1137
+ chunkWGEGR3DF_cjs.__name(getScrollParent, "getScrollParent");
1138
+ function getScrollTop(target) {
1139
+ return target === window ? window.scrollY : target.scrollTop;
1140
+ }
1141
+ chunkWGEGR3DF_cjs.__name(getScrollTop, "getScrollTop");
1142
+ function getViewportHeight(target) {
1143
+ return target === window ? window.innerHeight : target.clientHeight;
1144
+ }
1145
+ chunkWGEGR3DF_cjs.__name(getViewportHeight, "getViewportHeight");
1146
+ function getTargetTop(target) {
1147
+ return target === window ? 0 : target.getBoundingClientRect().top;
1148
+ }
1149
+ chunkWGEGR3DF_cjs.__name(getTargetTop, "getTargetTop");
1150
+ function scrollTargetTo(target, top) {
1151
+ if (target === window) {
1152
+ window.scrollTo({ top, behavior: "smooth" });
1153
+ return;
1154
+ }
1155
+ target.scrollTop = top;
1156
+ }
1157
+ chunkWGEGR3DF_cjs.__name(scrollTargetTo, "scrollTargetTo");
1158
+ function ApiIntroSection({ info, schema, endpoints, resolvedBaseUrl }) {
1159
+ const baseUrlRows = resolvedBaseUrl ? [{ url: resolvedBaseUrl, description: info.servers?.[0]?.description }] : (info.servers ?? []).map((s) => ({ url: s.url, description: s.description }));
1160
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pb-10 mb-10 border-b", children: [
1161
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 flex-wrap", children: [
1162
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap min-w-0", children: [
1163
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl font-semibold tracking-tight text-foreground leading-tight", children: info.title }),
1164
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center rounded-full bg-muted px-2 py-0.5 font-mono text-[11px] text-muted-foreground", children: [
1165
+ "v",
1166
+ info.version
1167
+ ] })
1168
+ ] }),
1169
+ /* @__PURE__ */ jsxRuntime.jsx(
1170
+ SchemaCopyMenu,
1171
+ {
1172
+ schema,
1173
+ endpoints,
1174
+ baseUrl: resolvedBaseUrl
1175
+ }
1176
+ )
1177
+ ] }),
1178
+ info.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(chunk5Q4UMSWB_cjs.MarkdownMessage, { content: info.description }) }),
1179
+ baseUrlRows.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-2", children: [
1180
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60", children: "Base URL" }),
1181
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: baseUrlRows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1182
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-xs px-2 py-1 rounded bg-muted border", children: row.url }),
1183
+ row.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: row.description })
1184
+ ] }, `${row.url}-${i}`)) })
1185
+ ] })
1186
+ ] });
1187
+ }
1188
+ chunkWGEGR3DF_cjs.__name(ApiIntroSection, "ApiIntroSection");
1189
+ var EndpointDocContext = React12.createContext(null);
1190
+ function EndpointDocProvider({ endpointId, method, children }) {
1191
+ const value = React12.useMemo(() => ({ endpointId, method }), [endpointId, method]);
1192
+ return /* @__PURE__ */ jsxRuntime.jsx(EndpointDocContext.Provider, { value, children });
1193
+ }
1194
+ chunkWGEGR3DF_cjs.__name(EndpointDocProvider, "EndpointDocProvider");
1195
+ function useEndpointDocContext() {
1196
+ const ctx = React12.useContext(EndpointDocContext);
1197
+ if (!ctx) {
1198
+ throw new Error(
1199
+ "[OpenapiViewer] useEndpointDocContext must be used inside <EndpointDocProvider>."
1200
+ );
1201
+ }
1202
+ return ctx;
1203
+ }
1204
+ chunkWGEGR3DF_cjs.__name(useEndpointDocContext, "useEndpointDocContext");
1205
+ var sectionKey = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpointId, sectionId) => `${endpointId}:${sectionId}`, "sectionKey");
1206
+ var initialState = {
1207
+ openSections: {},
1208
+ activeCodeTab: {}
1209
+ };
1210
+ var useEndpointDocStore = zustand.create()(
1211
+ middleware.persist(
1212
+ (set) => ({
1213
+ ...initialState,
1214
+ toggleSection: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpointId, sectionId) => set((state) => {
1215
+ const key = sectionKey(endpointId, sectionId);
1216
+ const current = state.openSections[key];
1217
+ return {
1218
+ openSections: {
1219
+ ...state.openSections,
1220
+ // If there's no explicit override yet, the user's
1221
+ // first click means "flip from the default". We
1222
+ // assume the default was ``true`` for the most
1223
+ // common case (bodies/responses) and ``false``
1224
+ // otherwise; the Section component tracks this
1225
+ // via its ``defaultOpen`` prop and never calls
1226
+ // toggle on sections whose defaults match the
1227
+ // next state.
1228
+ [key]: current === void 0 ? false : !current
1229
+ }
1230
+ };
1231
+ }), "toggleSection"),
1232
+ setSectionOpen: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpointId, sectionId, open) => set((state) => ({
1233
+ openSections: {
1234
+ ...state.openSections,
1235
+ [sectionKey(endpointId, sectionId)]: open
1236
+ }
1237
+ })), "setSectionOpen"),
1238
+ setCodeTab: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpointId, tab) => set((state) => ({
1239
+ activeCodeTab: {
1240
+ ...state.activeCodeTab,
1241
+ [endpointId]: tab
1242
+ }
1243
+ })), "setCodeTab"),
1244
+ expandAll: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpointId, sectionIds) => set((state) => {
1245
+ const next = { ...state.openSections };
1246
+ for (const sid of sectionIds) {
1247
+ next[sectionKey(endpointId, sid)] = true;
1248
+ }
1249
+ return { openSections: next };
1250
+ }), "expandAll"),
1251
+ collapseAll: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpointId, sectionIds) => set((state) => {
1252
+ const next = { ...state.openSections };
1253
+ for (const sid of sectionIds) {
1254
+ next[sectionKey(endpointId, sid)] = false;
1255
+ }
1256
+ return { openSections: next };
1257
+ }), "collapseAll")
1258
+ }),
1259
+ {
1260
+ name: "openapi-viewer:endpoint-doc",
1261
+ storage: middleware.createJSONStorage(() => {
1262
+ if (typeof window === "undefined") {
1263
+ return {
1264
+ getItem: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => null, "getItem"),
1265
+ setItem: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
1266
+ }, "setItem"),
1267
+ removeItem: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
1268
+ }, "removeItem")
1269
+ };
1270
+ }
1271
+ return window.sessionStorage;
1272
+ }),
1273
+ // Only persist user overrides, not the functions. Zustand
1274
+ // serialises everything by default and logs a warning on
1275
+ // non-serialisable values; partialize keeps the payload lean.
1276
+ partialize: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((state) => ({
1277
+ openSections: state.openSections,
1278
+ activeCodeTab: state.activeCodeTab
1279
+ }), "partialize")
1280
+ }
1281
+ )
1282
+ );
1283
+
1284
+ // src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/store/selectors.ts
1285
+ function useIsSectionOpen(endpointId, sectionId, defaultOpen) {
1286
+ return useEndpointDocStore((s) => {
1287
+ const explicit = s.openSections[sectionKey(endpointId, sectionId)];
1288
+ return explicit === void 0 ? defaultOpen : explicit;
1289
+ });
1290
+ }
1291
+ chunkWGEGR3DF_cjs.__name(useIsSectionOpen, "useIsSectionOpen");
1292
+ function useActiveCodeTab(endpointId, fallback = "curl") {
1293
+ return useEndpointDocStore((s) => s.activeCodeTab[endpointId] ?? fallback);
1294
+ }
1295
+ chunkWGEGR3DF_cjs.__name(useActiveCodeTab, "useActiveCodeTab");
1296
+ function LanguageTabs({ activeId, onChange }) {
1297
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 overflow-x-auto -mx-1 px-1", children: chunk5Q4UMSWB_cjs.CODE_SAMPLE_TARGETS.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
1298
+ "button",
1299
+ {
1300
+ type: "button",
1301
+ onClick: () => onChange(t.id),
1302
+ className: lib.cn(
1303
+ "shrink-0 h-7 px-2.5 rounded text-xs font-medium transition-colors",
1304
+ activeId === t.id ? "bg-muted text-foreground" : "text-muted-foreground/70 hover:text-foreground hover:bg-muted/50"
1305
+ ),
1306
+ children: t.label
1307
+ },
1308
+ t.id
1309
+ )) });
1310
+ }
1311
+ chunkWGEGR3DF_cjs.__name(LanguageTabs, "LanguageTabs");
1312
+ function useCodeSnippet({
1313
+ endpoint,
1314
+ body,
1315
+ parameters,
1316
+ headers,
1317
+ baseUrl,
1318
+ activeId
1319
+ }) {
1320
+ const effectiveBody = body ?? endpoint.requestBody?.example;
1321
+ const har = React12.useMemo(() => {
1322
+ const h = chunk5Q4UMSWB_cjs.buildHarRequest({
1323
+ endpoint,
1324
+ body: effectiveBody,
1325
+ parameters,
1326
+ headers,
1327
+ baseUrl
1328
+ });
1329
+ return baseUrl ? h : { ...h, url: chunk5Q4UMSWB_cjs.resolveAbsolute(h.url) };
1330
+ }, [endpoint, effectiveBody, parameters, headers, baseUrl]);
1331
+ return React12.useMemo(() => {
1332
+ const target = chunk5Q4UMSWB_cjs.CODE_SAMPLE_TARGETS.find((t) => t.id === activeId);
1333
+ const code = chunk5Q4UMSWB_cjs.renderSnippet(har, activeId);
1334
+ return {
1335
+ snippet: code ?? `// Snippet for ${target.label} is unavailable for this request.`,
1336
+ prism: target.prism
1337
+ };
1338
+ }, [har, activeId]);
1339
+ }
1340
+ chunkWGEGR3DF_cjs.__name(useCodeSnippet, "useCodeSnippet");
1341
+ function CodeSamples({ endpoint, body, parameters, headers, baseUrl }) {
1342
+ const { endpointId } = useEndpointDocContext();
1343
+ const activeId = useActiveCodeTab(endpointId);
1344
+ const setCodeTab = useEndpointDocStore((s) => s.setCodeTab);
1345
+ const { snippet, prism } = useCodeSnippet({
1346
+ endpoint,
1347
+ body,
1348
+ parameters,
1349
+ headers,
1350
+ baseUrl,
1351
+ activeId
1352
+ });
1353
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2.5", children: [
1354
+ /* @__PURE__ */ jsxRuntime.jsx(LanguageTabs, { activeId, onChange: (id) => setCodeTab(endpointId, id) }),
1355
+ /* @__PURE__ */ jsxRuntime.jsx(
1356
+ chunk5Q4UMSWB_cjs.PrettyCode_default,
1357
+ {
1358
+ data: snippet,
1359
+ language: prism,
1360
+ isCompact: true,
1361
+ maxLines: 20
1362
+ }
1363
+ )
1364
+ ] });
1365
+ }
1366
+ chunkWGEGR3DF_cjs.__name(CodeSamples, "CodeSamples");
1367
+ function IconButton({ label, onClick, children, active }) {
1368
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.Tooltip, { children: [
1369
+ /* @__PURE__ */ jsxRuntime.jsx(components.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
1370
+ "button",
1371
+ {
1372
+ type: "button",
1373
+ onClick,
1374
+ "aria-label": label,
1375
+ className: lib.cn(
1376
+ "shrink-0 h-6 w-6 inline-flex items-center justify-center rounded",
1377
+ "text-muted-foreground/60 hover:text-foreground hover:bg-muted transition-colors",
1378
+ active && "text-emerald-500 hover:text-emerald-500"
1379
+ ),
1380
+ children
1381
+ }
1382
+ ) }),
1383
+ /* @__PURE__ */ jsxRuntime.jsx(components.TooltipContent, { side: "bottom", className: "text-[11px]", children: label })
1384
+ ] });
1385
+ }
1386
+ chunkWGEGR3DF_cjs.__name(IconButton, "IconButton");
1387
+ function MetaActions({ anchor, endpointMarkdown, presentSections }) {
1388
+ const { endpointId } = useEndpointDocContext();
1389
+ const expandAll = useEndpointDocStore((s) => s.expandAll);
1390
+ const collapseAll = useEndpointDocStore((s) => s.collapseAll);
1391
+ const openSections = useEndpointDocStore((s) => s.openSections);
1392
+ const [justCopied, setJustCopied] = React12.useState(null);
1393
+ const flash = React12.useCallback((which) => {
1394
+ setJustCopied(which);
1395
+ setTimeout(() => setJustCopied(null), 1200);
1396
+ }, []);
1397
+ const mostlyOpen = React12.useMemo(() => {
1398
+ if (presentSections.length === 0) return false;
1399
+ let openCount = 0;
1400
+ for (const sid of presentSections) {
1401
+ if (openSections[sectionKey(endpointId, sid)]) openCount += 1;
1402
+ }
1403
+ return openCount > presentSections.length / 2;
1404
+ }, [openSections, presentSections, endpointId]);
1405
+ const copyLink = React12.useCallback(() => {
1406
+ if (typeof window === "undefined") return;
1407
+ const url = `${window.location.origin}${window.location.pathname}#${anchor}`;
1408
+ void navigator.clipboard?.writeText(url).then(() => flash("link"));
1409
+ }, [anchor, flash]);
1410
+ const copyMarkdown = React12.useCallback(() => {
1411
+ if (typeof window === "undefined") return;
1412
+ void navigator.clipboard?.writeText(endpointMarkdown).then(() => flash("md"));
1413
+ }, [endpointMarkdown, flash]);
1414
+ const toggleAll = React12.useCallback(() => {
1415
+ if (mostlyOpen) collapseAll(endpointId, presentSections);
1416
+ else expandAll(endpointId, presentSections);
1417
+ }, [mostlyOpen, collapseAll, expandAll, endpointId, presentSections]);
1418
+ return /* @__PURE__ */ jsxRuntime.jsx(components.SafeTooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
1419
+ /* @__PURE__ */ jsxRuntime.jsx(
1420
+ IconButton,
1421
+ {
1422
+ label: justCopied === "link" ? "Copied!" : "Copy link to endpoint",
1423
+ onClick: copyLink,
1424
+ active: justCopied === "link",
1425
+ children: justCopied === "link" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { className: "h-3.5 w-3.5" })
1426
+ }
1427
+ ),
1428
+ /* @__PURE__ */ jsxRuntime.jsx(
1429
+ IconButton,
1430
+ {
1431
+ label: justCopied === "md" ? "Copied!" : "Copy as Markdown (for AI)",
1432
+ onClick: copyMarkdown,
1433
+ active: justCopied === "md",
1434
+ children: justCopied === "md" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode2, { className: "h-3.5 w-3.5" })
1435
+ }
1436
+ ),
1437
+ presentSections.length >= 2 && /* @__PURE__ */ jsxRuntime.jsx(
1438
+ IconButton,
1439
+ {
1440
+ label: mostlyOpen ? "Collapse all sections" : "Expand all sections",
1441
+ onClick: toggleAll,
1442
+ children: mostlyOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsDownUp, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { className: "h-3.5 w-3.5" })
1443
+ }
1444
+ )
1445
+ ] }) });
1446
+ }
1447
+ chunkWGEGR3DF_cjs.__name(MetaActions, "MetaActions");
1448
+ function PathDisplay({ path }) {
1449
+ return /* @__PURE__ */ jsxRuntime.jsx(
1450
+ "code",
1451
+ {
1452
+ className: "block font-mono text-lg md:text-xl font-semibold text-foreground leading-tight",
1453
+ style: { overflowWrap: "anywhere", wordBreak: "break-word" },
1454
+ children: chunk5Q4UMSWB_cjs.relativePath(path)
1455
+ }
1456
+ );
1457
+ }
1458
+ chunkWGEGR3DF_cjs.__name(PathDisplay, "PathDisplay");
1459
+ function EndpointHeader({
1460
+ endpoint,
1461
+ anchor,
1462
+ isLoadedInPlayground,
1463
+ onTryIt,
1464
+ presentSections
1465
+ }) {
1466
+ const endpointMd = React12.useMemo(() => chunk5Q4UMSWB_cjs.endpointToMarkdown(endpoint), [endpoint]);
1467
+ return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "space-y-3", children: [
1468
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap", children: [
1469
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
1470
+ /* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: endpoint.method }),
1471
+ /* @__PURE__ */ jsxRuntime.jsx(
1472
+ MetaActions,
1473
+ {
1474
+ anchor,
1475
+ endpointMarkdown: endpointMd,
1476
+ presentSections
1477
+ }
1478
+ )
1479
+ ] }),
1480
+ /* @__PURE__ */ jsxRuntime.jsxs(
1481
+ components.Button,
1482
+ {
1483
+ size: "sm",
1484
+ variant: isLoadedInPlayground ? "secondary" : "default",
1485
+ onClick: onTryIt,
1486
+ className: "ml-auto h-7 text-xs gap-1.5 px-2.5",
1487
+ children: [
1488
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-3 w-3" }),
1489
+ isLoadedInPlayground ? "Loaded" : "Try it"
1490
+ ]
1491
+ }
1492
+ )
1493
+ ] }),
1494
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(PathDisplay, { path: endpoint.path }) }),
1495
+ endpoint.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(chunk5Q4UMSWB_cjs.MarkdownMessage, { content: endpoint.description }) })
1496
+ ] });
1497
+ }
1498
+ chunkWGEGR3DF_cjs.__name(EndpointHeader, "EndpointHeader");
1499
+ function ParamRow({ param }) {
1500
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2.5 bg-background space-y-1", children: [
1501
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1502
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-xs font-medium text-foreground", children: param.name }),
1503
+ param.required && /* @__PURE__ */ jsxRuntime.jsx(
1504
+ "span",
1505
+ {
1506
+ title: "Required",
1507
+ className: "text-[9px] text-destructive font-bold leading-none",
1508
+ children: "*"
1509
+ }
1510
+ ),
1511
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground/70", children: param.type })
1512
+ ] }),
1513
+ param.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground leading-relaxed break-words", children: param.description })
1514
+ ] });
1515
+ }
1516
+ chunkWGEGR3DF_cjs.__name(ParamRow, "ParamRow");
1517
+ function ParamGroup({ label, params }) {
1518
+ if (params.length === 0) return null;
1519
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1520
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] font-semibold uppercase tracking-[0.1em] text-muted-foreground/60 px-1", children: label }),
1521
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y border rounded-md overflow-hidden", children: params.map((p) => /* @__PURE__ */ jsxRuntime.jsx(ParamRow, { param: p }, `${label}-${p.name}`)) })
1522
+ ] });
1523
+ }
1524
+ chunkWGEGR3DF_cjs.__name(ParamGroup, "ParamGroup");
1525
+ function Parameters({ pathParams, queryParams }) {
1526
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1527
+ /* @__PURE__ */ jsxRuntime.jsx(ParamGroup, { label: "Path", params: pathParams }),
1528
+ /* @__PURE__ */ jsxRuntime.jsx(ParamGroup, { label: "Query", params: queryParams })
1529
+ ] });
1530
+ }
1531
+ chunkWGEGR3DF_cjs.__name(Parameters, "Parameters");
1532
+
1533
+ // src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts
1534
+ var MAX_DEPTH = 5;
1535
+ function mergeAllOf(branches) {
1536
+ const properties = {};
1537
+ const required = [];
1538
+ for (const b of branches) {
1539
+ if (b.properties) Object.assign(properties, b.properties);
1540
+ if (Array.isArray(b.required)) required.push(...b.required);
1541
+ }
1542
+ return { type: "object", properties, required };
1543
+ }
1544
+ chunkWGEGR3DF_cjs.__name(mergeAllOf, "mergeAllOf");
1545
+ function describeType(node) {
1546
+ if (node.type === "array") {
1547
+ const itemLabel = node.items ? describeType(node.items).label : "any";
1548
+ return { label: `array<${itemLabel}>`, kind: "array" };
1549
+ }
1550
+ if (node.type === "object" || node.properties) {
1551
+ return { label: "object", kind: "object" };
1552
+ }
1553
+ const base = node.type || "any";
1554
+ if (Array.isArray(node.enum) && node.enum.length > 0) {
1555
+ return { label: `${base} enum`, kind: "primitive" };
1556
+ }
1557
+ if (node.format) {
1558
+ return { label: `${base} (${node.format})`, kind: "primitive" };
1559
+ }
1560
+ return { label: base, kind: "primitive" };
1561
+ }
1562
+ chunkWGEGR3DF_cjs.__name(describeType, "describeType");
1563
+ function resolveCombinators(node) {
1564
+ if (Array.isArray(node.allOf) && node.allOf.length > 0) {
1565
+ return { ...mergeAllOf(node.allOf), description: node.description };
1566
+ }
1567
+ if (Array.isArray(node.oneOf) && node.oneOf.length > 0) {
1568
+ return { ...node.oneOf[0], description: node.description ?? node.oneOf[0].description };
1569
+ }
1570
+ if (Array.isArray(node.anyOf) && node.anyOf.length > 0) {
1571
+ return { ...node.anyOf[0], description: node.description ?? node.anyOf[0].description };
1572
+ }
1573
+ return node;
1574
+ }
1575
+ chunkWGEGR3DF_cjs.__name(resolveCombinators, "resolveCombinators");
1576
+ function buildNode(name, schema, isRequired, depth) {
1577
+ const resolved = resolveCombinators(schema);
1578
+ const { label, kind } = describeType(resolved);
1579
+ const node = {
1580
+ name,
1581
+ type: label,
1582
+ kind,
1583
+ required: isRequired,
1584
+ description: resolved.description
1585
+ };
1586
+ if (Array.isArray(resolved.enum) && resolved.enum.length > 0) {
1587
+ node.enumValues = resolved.enum.map((v) => String(v));
1588
+ }
1589
+ if (depth >= MAX_DEPTH) return node;
1590
+ if (kind === "object" && resolved.properties) {
1591
+ const required = new Set(resolved.required ?? []);
1592
+ node.children = Object.entries(resolved.properties).map(
1593
+ ([key, child]) => buildNode(key, child, required.has(key), depth + 1)
1594
+ );
1595
+ } else if (kind === "array" && resolved.items) {
1596
+ node.children = [buildNode("[]", resolved.items, false, depth + 1)];
1597
+ }
1598
+ return node;
1599
+ }
1600
+ chunkWGEGR3DF_cjs.__name(buildNode, "buildNode");
1601
+ function buildSchemaTree(schema) {
1602
+ if (!schema) return [];
1603
+ const root = buildNode("", schema, false, 0);
1604
+ if (root.children && root.children.length > 0) return root.children;
1605
+ if (root.kind === "primitive" || !root.children && root.name === "") {
1606
+ return [{ ...root, name: root.name || "(body)" }];
1607
+ }
1608
+ return [];
1609
+ }
1610
+ chunkWGEGR3DF_cjs.__name(buildSchemaTree, "buildSchemaTree");
1611
+ function FieldRow({ field, depth, showTreeLine = true }) {
1612
+ const isExpandable = (field.kind === "object" || field.kind === "array") && Array.isArray(field.children) && field.children.length > 0;
1613
+ const [open, setOpen] = React12.useState(depth < 2);
1614
+ const padLeft = showTreeLine ? depth * 14 : 0;
1615
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background", children: [
1616
+ /* @__PURE__ */ jsxRuntime.jsxs(
1617
+ "div",
1618
+ {
1619
+ className: lib.cn(
1620
+ "grid grid-cols-[16px_minmax(0,1fr)] items-baseline gap-2 px-3 py-2",
1621
+ isExpandable && "cursor-pointer hover:bg-muted/30"
1622
+ ),
1623
+ style: { paddingLeft: 12 + padLeft },
1624
+ onClick: () => isExpandable && setOpen((v) => !v),
1625
+ role: isExpandable ? "button" : void 0,
1626
+ "aria-expanded": isExpandable ? open : void 0,
1627
+ children: [
1628
+ /* @__PURE__ */ jsxRuntime.jsx(
1629
+ lucideReact.ChevronRight,
1630
+ {
1631
+ className: lib.cn(
1632
+ "h-3.5 w-3.5 text-muted-foreground/50 shrink-0 transition-transform",
1633
+ !isExpandable && "opacity-0",
1634
+ open && "rotate-90"
1635
+ )
1636
+ }
1637
+ ),
1638
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
1639
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1640
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-xs font-medium text-foreground", children: field.name }),
1641
+ field.required && /* @__PURE__ */ jsxRuntime.jsx(
1642
+ "span",
1643
+ {
1644
+ title: "Required",
1645
+ className: "text-[9px] text-destructive font-bold leading-none",
1646
+ children: "*"
1647
+ }
1648
+ ),
1649
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground/70", children: field.type })
1650
+ ] }),
1651
+ field.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground leading-relaxed break-words", children: field.description }),
1652
+ field.enumValues && field.enumValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 pt-0.5", children: field.enumValues.map((v) => /* @__PURE__ */ jsxRuntime.jsx(
1653
+ "code",
1654
+ {
1655
+ className: "inline-flex items-center rounded border border-border/60 bg-muted/40 px-1.5 py-px font-mono text-[10px] text-muted-foreground",
1656
+ children: v
1657
+ },
1658
+ v
1659
+ )) })
1660
+ ] })
1661
+ ]
1662
+ }
1663
+ ),
1664
+ isExpandable && open && /* @__PURE__ */ jsxRuntime.jsx("div", { children: field.children.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx(
1665
+ FieldRow,
1666
+ {
1667
+ field: child,
1668
+ depth: depth + 1
1669
+ },
1670
+ `${child.name}-${i}`
1671
+ )) })
1672
+ ] });
1673
+ }
1674
+ chunkWGEGR3DF_cjs.__name(FieldRow, "FieldRow");
1675
+ function SchemaFields({ schema }) {
1676
+ const tree = React12.useMemo(() => buildSchemaTree(schema), [schema]);
1677
+ if (tree.length === 0) return null;
1678
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y border rounded-md overflow-hidden", children: tree.map((node, i) => /* @__PURE__ */ jsxRuntime.jsx(FieldRow, { field: node, depth: 0 }, `${node.name}-${i}`)) });
1679
+ }
1680
+ chunkWGEGR3DF_cjs.__name(SchemaFields, "SchemaFields");
1681
+ function RequestBody({ body }) {
1682
+ const typeLabel = body.schema ? body.type === "array" ? `array<${body.schema.items?.type ?? "object"}>` : body.type : body.type;
1683
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
1684
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1685
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground/80", children: typeLabel }),
1686
+ body.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: body.description })
1687
+ ] }),
1688
+ body.schema && /* @__PURE__ */ jsxRuntime.jsx(SchemaFields, { schema: body.schema })
1689
+ ] });
1690
+ }
1691
+ chunkWGEGR3DF_cjs.__name(RequestBody, "RequestBody");
1692
+ var EXAMPLE_JSON_TREE_CONFIG = {
1693
+ maxAutoExpandDepth: 2,
1694
+ maxAutoExpandArrayItems: 5,
1695
+ maxAutoExpandObjectKeys: 8,
1696
+ maxStringLength: 160,
1697
+ collectionLimit: 25,
1698
+ showCollectionInfo: true,
1699
+ showExpandControls: false,
1700
+ showActionButtons: false,
1701
+ preserveKeyOrder: true,
1702
+ className: "border-0 rounded-none"
1703
+ };
1704
+ function ResponseBody({ example, contentType }) {
1705
+ const parsed = React12.useMemo(() => {
1706
+ try {
1707
+ return JSON.parse(example);
1708
+ } catch {
1709
+ return null;
1710
+ }
1711
+ }, [example]);
1712
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t bg-muted/20", children: [
1713
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 py-1.5 border-b border-border/50", children: [
1714
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70", children: contentType ?? "application/json" }),
1715
+ /* @__PURE__ */ jsxRuntime.jsx(
1716
+ components.CopyButton,
1717
+ {
1718
+ value: example,
1719
+ variant: "ghost",
1720
+ size: "sm",
1721
+ className: "h-6 px-2 text-[10px] text-muted-foreground",
1722
+ children: "Copy"
1723
+ }
1724
+ )
1725
+ ] }),
1726
+ parsed != null ? /* @__PURE__ */ jsxRuntime.jsx(
1727
+ chunk33AMWFBZ_cjs.JsonTree_default,
1728
+ {
1729
+ title: "",
1730
+ data: parsed,
1731
+ mode: "compact",
1732
+ config: EXAMPLE_JSON_TREE_CONFIG
1733
+ }
1734
+ ) : /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-3 text-[11px] font-mono text-foreground/70 whitespace-pre-wrap break-all leading-relaxed", children: example })
1735
+ ] });
1736
+ }
1737
+ chunkWGEGR3DF_cjs.__name(ResponseBody, "ResponseBody");
1738
+ function StatusTag({ code }) {
1739
+ const numeric = Number.parseInt(code, 10);
1740
+ const cls = !Number.isFinite(numeric) ? "bg-muted text-muted-foreground border-border" : numeric >= 500 ? "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/25" : numeric >= 400 ? "bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/25" : numeric >= 300 ? "bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/25" : "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/25";
1741
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn(
1742
+ "inline-flex items-center justify-center rounded border px-2 py-0.5 font-mono text-[11px] font-bold leading-none shrink-0 tabular-nums",
1743
+ cls
1744
+ ), children: code });
1745
+ }
1746
+ chunkWGEGR3DF_cjs.__name(StatusTag, "StatusTag");
1747
+ function ResponseRow({ response }) {
1748
+ const hasExample = Boolean(response.example);
1749
+ const numeric = Number.parseInt(response.code, 10);
1750
+ const isSuccess = Number.isFinite(numeric) && numeric >= 200 && numeric < 300;
1751
+ const [open, setOpen] = React12.useState(hasExample && isSuccess);
1752
+ if (!hasExample) {
1753
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 px-3 py-2 bg-background", children: [
1754
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 shrink-0 flex justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(StatusTag, { code: response.code }) }),
1755
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground leading-relaxed break-words min-w-0", children: response.description })
1756
+ ] });
1757
+ }
1758
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background", children: [
1759
+ /* @__PURE__ */ jsxRuntime.jsxs(
1760
+ "button",
1761
+ {
1762
+ type: "button",
1763
+ onClick: () => setOpen((v) => !v),
1764
+ className: "w-full flex items-center gap-3 px-3 py-2 text-left hover:bg-muted/40 cursor-pointer transition-colors",
1765
+ "aria-expanded": open,
1766
+ children: [
1767
+ /* @__PURE__ */ jsxRuntime.jsx(
1768
+ lucideReact.ChevronRight,
1769
+ {
1770
+ className: lib.cn(
1771
+ "h-3.5 w-3.5 text-muted-foreground/60 transition-transform shrink-0",
1772
+ open && "rotate-90"
1773
+ )
1774
+ }
1775
+ ),
1776
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 shrink-0 flex justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(StatusTag, { code: response.code }) }),
1777
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground leading-relaxed break-words min-w-0 flex-1", children: response.description })
1778
+ ]
1779
+ }
1780
+ ),
1781
+ open && /* @__PURE__ */ jsxRuntime.jsx(
1782
+ ResponseBody,
1783
+ {
1784
+ example: response.example,
1785
+ contentType: response.contentType
1786
+ }
1787
+ )
1788
+ ] });
1789
+ }
1790
+ chunkWGEGR3DF_cjs.__name(ResponseRow, "ResponseRow");
1791
+ function Responses({ responses }) {
1792
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y border rounded-md overflow-hidden", children: responses.map((r) => /* @__PURE__ */ jsxRuntime.jsx(ResponseRow, { response: r }, r.code)) });
1793
+ }
1794
+ chunkWGEGR3DF_cjs.__name(Responses, "Responses");
1795
+
1796
+ // src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/defaults.ts
1797
+ var DEFAULTS_BY_METHOD = {
1798
+ GET: { parameters: true, responses: true },
1799
+ DELETE: { parameters: true, responses: true },
1800
+ POST: { requestBody: true, responses: true },
1801
+ PUT: { requestBody: true, responses: true },
1802
+ PATCH: { requestBody: true, responses: true }
1803
+ };
1804
+ function defaultSectionOpen(method, sectionId) {
1805
+ return DEFAULTS_BY_METHOD[method.toUpperCase()]?.[sectionId] ?? false;
1806
+ }
1807
+ chunkWGEGR3DF_cjs.__name(defaultSectionOpen, "defaultSectionOpen");
1808
+
1809
+ // src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/types.ts
1810
+ var ALL_SECTION_IDS = [
1811
+ "parameters",
1812
+ "requestBody",
1813
+ "responses",
1814
+ "codeSamples"
1815
+ ];
1816
+
1817
+ // src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/hooks/useSectionHash.ts
1818
+ function parseSectionHash(hash) {
1819
+ const raw = hash.startsWith("#") ? hash.slice(1) : hash;
1820
+ if (!raw.startsWith("section=")) return null;
1821
+ const value = raw.slice("section=".length);
1822
+ const dot = value.lastIndexOf(".");
1823
+ if (dot <= 0 || dot === value.length - 1) return null;
1824
+ const endpointId = value.slice(0, dot);
1825
+ const sectionIdCandidate = value.slice(dot + 1);
1826
+ if (!ALL_SECTION_IDS.includes(sectionIdCandidate)) return null;
1827
+ return { endpointId, sectionId: sectionIdCandidate };
1828
+ }
1829
+ chunkWGEGR3DF_cjs.__name(parseSectionHash, "parseSectionHash");
1830
+ function buildSectionHash(endpointId, sectionId) {
1831
+ return `section=${endpointId}.${sectionId}`;
1832
+ }
1833
+ chunkWGEGR3DF_cjs.__name(buildSectionHash, "buildSectionHash");
1834
+ function useSectionHashRouter() {
1835
+ const setSectionOpen = useEndpointDocStore((s) => s.setSectionOpen);
1836
+ React12.useEffect(() => {
1837
+ if (typeof window === "undefined") return;
1838
+ function apply() {
1839
+ const parsed = parseSectionHash(window.location.hash);
1840
+ if (!parsed) return;
1841
+ setSectionOpen(parsed.endpointId, parsed.sectionId, true);
1842
+ requestAnimationFrame(() => {
1843
+ const el = document.getElementById(parsed.endpointId);
1844
+ el?.scrollIntoView({ behavior: "smooth", block: "start" });
1845
+ });
1846
+ }
1847
+ chunkWGEGR3DF_cjs.__name(apply, "apply");
1848
+ apply();
1849
+ window.addEventListener("hashchange", apply);
1850
+ return () => window.removeEventListener("hashchange", apply);
1851
+ }, [setSectionOpen]);
1852
+ }
1853
+ chunkWGEGR3DF_cjs.__name(useSectionHashRouter, "useSectionHashRouter");
1854
+ function SectionHeader({ sectionId, title, badge, open, onToggle }) {
1855
+ const { endpointId } = useEndpointDocContext();
1856
+ const [copied, setCopied] = React12.useState(false);
1857
+ const copyHash = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((e) => {
1858
+ e.stopPropagation();
1859
+ if (typeof window === "undefined") return;
1860
+ const hash = buildSectionHash(endpointId, sectionId);
1861
+ const url = `${window.location.origin}${window.location.pathname}#${hash}`;
1862
+ void navigator.clipboard?.writeText(url).then(() => {
1863
+ setCopied(true);
1864
+ setTimeout(() => setCopied(false), 1200);
1865
+ });
1866
+ }, "copyHash");
1867
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1868
+ "div",
1869
+ {
1870
+ className: lib.cn(
1871
+ "group/section w-full flex items-center gap-2 py-1.5 -ml-1 px-1 rounded cursor-pointer",
1872
+ "hover:bg-muted/30 transition-colors"
1873
+ ),
1874
+ onClick: onToggle,
1875
+ role: "button",
1876
+ "aria-expanded": open,
1877
+ tabIndex: 0,
1878
+ onKeyDown: (e) => {
1879
+ if (e.key === "Enter" || e.key === " ") {
1880
+ e.preventDefault();
1881
+ onToggle();
1882
+ }
1883
+ },
1884
+ children: [
1885
+ /* @__PURE__ */ jsxRuntime.jsx(
1886
+ lucideReact.ChevronDown,
1887
+ {
1888
+ className: lib.cn(
1889
+ "h-3.5 w-3.5 text-muted-foreground/50 transition-transform shrink-0",
1890
+ !open && "-rotate-90"
1891
+ )
1892
+ }
1893
+ ),
1894
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/80", children: title }),
1895
+ typeof badge === "number" && badge > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground/50 tabular-nums", children: badge }),
1896
+ /* @__PURE__ */ jsxRuntime.jsx(
1897
+ "button",
1898
+ {
1899
+ type: "button",
1900
+ onClick: copyHash,
1901
+ title: "Copy link to this section",
1902
+ className: lib.cn(
1903
+ "ml-auto shrink-0 p-1 rounded text-muted-foreground/40 hover:text-foreground hover:bg-muted transition-all",
1904
+ "opacity-0 group-hover/section:opacity-100 focus-visible:opacity-100",
1905
+ copied && "opacity-100 text-emerald-500"
1906
+ ),
1907
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { className: "h-3 w-3" })
1908
+ }
1909
+ )
1910
+ ]
1911
+ }
1912
+ );
1913
+ }
1914
+ chunkWGEGR3DF_cjs.__name(SectionHeader, "SectionHeader");
1915
+ function Section({ id, title, badge, children }) {
1916
+ const { endpointId, method } = useEndpointDocContext();
1917
+ const defaultOpen = defaultSectionOpen(method, id);
1918
+ const open = useIsSectionOpen(endpointId, id, defaultOpen);
1919
+ const toggleSection = useEndpointDocStore((s) => s.toggleSection);
1920
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2.5", children: [
1921
+ /* @__PURE__ */ jsxRuntime.jsx(
1922
+ SectionHeader,
1923
+ {
1924
+ sectionId: id,
1925
+ title,
1926
+ badge,
1927
+ open,
1928
+ onToggle: () => toggleSection(endpointId, id)
1929
+ }
1930
+ ),
1931
+ open && /* @__PURE__ */ jsxRuntime.jsx("div", { children })
1932
+ ] });
1933
+ }
1934
+ chunkWGEGR3DF_cjs.__name(Section, "Section");
1935
+ function EndpointDoc({ endpoint, isLoadedInPlayground, onTryIt, schemaId }) {
1936
+ const scopedSchemaId = schemaId ?? endpoint.schemaId ?? null;
1937
+ const anchor = endpointAnchor(endpoint, scopedSchemaId);
1938
+ const pathParams = endpoint.parameters?.filter((p) => endpoint.path.includes(`{${p.name}}`)) ?? [];
1939
+ const queryParams = endpoint.parameters?.filter((p) => !endpoint.path.includes(`{${p.name}}`)) ?? [];
1940
+ const hasParameters = pathParams.length > 0 || queryParams.length > 0;
1941
+ const hasResponses = (endpoint.responses?.length ?? 0) > 0;
1942
+ const presentSections = [];
1943
+ if (hasParameters) presentSections.push("parameters");
1944
+ if (endpoint.requestBody) presentSections.push("requestBody");
1945
+ presentSections.push("codeSamples");
1946
+ if (hasResponses) presentSections.push("responses");
1947
+ return /* @__PURE__ */ jsxRuntime.jsx(EndpointDocProvider, { endpointId: anchor, method: endpoint.method, children: /* @__PURE__ */ jsxRuntime.jsxs(
1948
+ "section",
1949
+ {
1950
+ id: anchor,
1951
+ "data-endpoint-anchor": anchor,
1952
+ "data-schema-id": scopedSchemaId ?? "",
1953
+ className: "scroll-mt-24 py-10 first:pt-0",
1954
+ children: [
1955
+ /* @__PURE__ */ jsxRuntime.jsx(
1956
+ EndpointHeader,
1957
+ {
1958
+ endpoint,
1959
+ anchor,
1960
+ isLoadedInPlayground,
1961
+ onTryIt,
1962
+ presentSections
1963
+ }
1964
+ ),
1965
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8 space-y-5", children: [
1966
+ hasParameters && /* @__PURE__ */ jsxRuntime.jsx(
1967
+ Section,
1968
+ {
1969
+ id: "parameters",
1970
+ title: "Parameters",
1971
+ badge: pathParams.length + queryParams.length,
1972
+ children: /* @__PURE__ */ jsxRuntime.jsx(Parameters, { pathParams, queryParams })
1973
+ }
1974
+ ),
1975
+ endpoint.requestBody && /* @__PURE__ */ jsxRuntime.jsx(Section, { id: "requestBody", title: "Request body", children: /* @__PURE__ */ jsxRuntime.jsx(RequestBody, { body: endpoint.requestBody }) }),
1976
+ /* @__PURE__ */ jsxRuntime.jsx(Section, { id: "codeSamples", title: "Code samples", children: /* @__PURE__ */ jsxRuntime.jsx(CodeSamples, { endpoint }) }),
1977
+ hasResponses && /* @__PURE__ */ jsxRuntime.jsx(
1978
+ Section,
1979
+ {
1980
+ id: "responses",
1981
+ title: "Responses",
1982
+ badge: endpoint.responses.length,
1983
+ children: /* @__PURE__ */ jsxRuntime.jsx(Responses, { responses: endpoint.responses })
1984
+ }
1985
+ )
1986
+ ] })
1987
+ ]
1988
+ }
1989
+ ) });
1990
+ }
1991
+ chunkWGEGR3DF_cjs.__name(EndpointDoc, "EndpointDoc");
1992
+ var readNavbarOffset = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
1993
+ if (typeof document === "undefined") return 0;
1994
+ const raw = getComputedStyle(document.documentElement).getPropertyValue("--navbar-height");
1995
+ const parsed = parseInt(raw || "", 10);
1996
+ return Number.isFinite(parsed) ? parsed : 0;
1997
+ }, "readNavbarOffset");
1998
+ var isSameEndpoint = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((a, b) => a !== null && a.method === b.method && a.path === b.path, "isSameEndpoint");
1999
+ function buildEndpointRow(ep, loadedEndpoint, schemaId) {
2000
+ const keySchema = schemaId ? `${schemaId}-` : "";
2001
+ return {
2002
+ key: `${keySchema}${ep.method}-${ep.path}`,
2003
+ endpoint: ep,
2004
+ isLoaded: isSameEndpoint(loadedEndpoint, ep),
2005
+ schemaId
2006
+ };
2007
+ }
2008
+ chunkWGEGR3DF_cjs.__name(buildEndpointRow, "buildEndpointRow");
2009
+ function buildSchemaSectionVM(entry, selectedVersion, loadedEndpoint) {
2010
+ const title = entry.info?.title ?? entry.source.name;
2011
+ const version = entry.info?.version ?? null;
2012
+ const description = entry.info?.description ?? null;
2013
+ let state;
2014
+ if (entry.loading) {
2015
+ state = { kind: "loading" };
2016
+ } else if (entry.error) {
2017
+ state = { kind: "error", message: entry.error };
2018
+ } else {
2019
+ const visible = chunk5Q4UMSWB_cjs.deduplicateEndpoints(entry.endpoints, selectedVersion);
2020
+ state = visible.length === 0 ? { kind: "empty" } : {
2021
+ kind: "ready",
2022
+ rows: visible.map((ep) => buildEndpointRow(ep, loadedEndpoint, entry.source.id))
2023
+ };
2024
+ }
2025
+ return {
2026
+ schemaId: entry.source.id,
2027
+ title,
2028
+ version,
2029
+ description,
2030
+ state,
2031
+ rawSchema: entry.rawSchema,
2032
+ baseUrl: entry.resolvedBaseUrl,
2033
+ allEndpoints: entry.endpoints
2034
+ };
2035
+ }
2036
+ chunkWGEGR3DF_cjs.__name(buildSchemaSectionVM, "buildSchemaSectionVM");
2037
+ var DocsView = React12__default.default.forwardRef(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function DocsView2(props, ref) {
2038
+ const scrollRef = React12.useRef(null);
2039
+ const scrollTargetRef = React12.useRef(null);
2040
+ const { onActiveChange } = props;
2041
+ useSectionHashRouter();
2042
+ const ensureScrollTarget = React12.useCallback(() => {
2043
+ if (scrollTargetRef.current) return scrollTargetRef.current;
2044
+ if (!scrollRef.current) return null;
2045
+ scrollTargetRef.current = getScrollParent(scrollRef.current);
2046
+ return scrollTargetRef.current;
2047
+ }, []);
2048
+ const scrollToAnchor = React12.useCallback(
2049
+ (anchor) => {
2050
+ const root = scrollRef.current;
2051
+ if (!root) return;
2052
+ const el = root.querySelector(`[data-endpoint-anchor="${anchor}"]`);
2053
+ if (!el) return;
2054
+ const target = ensureScrollTarget();
2055
+ if (!target) return;
2056
+ const navbar = readNavbarOffset();
2057
+ const top = el.getBoundingClientRect().top - getTargetTop(target) + getScrollTop(target) - navbar - 8;
2058
+ scrollTargetTo(target, top);
2059
+ },
2060
+ [ensureScrollTarget]
2061
+ );
2062
+ React12__default.default.useImperativeHandle(ref, () => ({ scrollToAnchor }), [scrollToAnchor]);
2063
+ React12.useEffect(() => {
2064
+ const root = scrollRef.current;
2065
+ if (!root) return;
2066
+ const target = ensureScrollTarget();
2067
+ if (!target) return;
2068
+ let rafId = 0;
2069
+ let lastActive = null;
2070
+ const compute = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
2071
+ rafId = 0;
2072
+ const sections = root.querySelectorAll("[data-endpoint-anchor]");
2073
+ if (sections.length === 0) return;
2074
+ const navbar = readNavbarOffset();
2075
+ const viewportTop = getTargetTop(target);
2076
+ const threshold = viewportTop + navbar + getViewportHeight(target) * 0.25;
2077
+ let active = null;
2078
+ for (const s of Array.from(sections)) {
2079
+ const top = s.getBoundingClientRect().top;
2080
+ if (top <= threshold) {
2081
+ active = s;
2082
+ } else {
2083
+ break;
2084
+ }
2085
+ }
2086
+ const anchor = active?.dataset.endpointAnchor ?? null;
2087
+ if (anchor !== lastActive) {
2088
+ lastActive = anchor;
2089
+ onActiveChange(anchor, active?.dataset.schemaId || null);
2090
+ }
2091
+ }, "compute");
2092
+ const onScroll = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
2093
+ if (rafId) return;
2094
+ rafId = requestAnimationFrame(compute);
2095
+ }, "onScroll");
2096
+ compute();
2097
+ target.addEventListener("scroll", onScroll, { passive: true });
2098
+ window.addEventListener("resize", onScroll, { passive: true });
2099
+ return () => {
2100
+ target.removeEventListener("scroll", onScroll);
2101
+ window.removeEventListener("resize", onScroll);
2102
+ if (rafId) cancelAnimationFrame(rafId);
2103
+ };
2104
+ }, [onActiveChange, ensureScrollTarget, props]);
2105
+ if (props.grouping === "sections") {
2106
+ return /* @__PURE__ */ jsxRuntime.jsx(SectionsBody, { scrollRef, ...props });
2107
+ }
2108
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectorBody, { scrollRef, ...props });
2109
+ }, "DocsView"));
2110
+ function SelectorBody({
2111
+ scrollRef,
2112
+ info,
2113
+ rawSchema,
2114
+ resolvedBaseUrl,
2115
+ endpoints,
2116
+ selectedVersion,
2117
+ loadedEndpoint,
2118
+ onTryEndpoint
2119
+ }) {
2120
+ const visibleEndpoints = React12.useMemo(
2121
+ () => chunk5Q4UMSWB_cjs.deduplicateEndpoints(endpoints, selectedVersion),
2122
+ [endpoints, selectedVersion]
2123
+ );
2124
+ const rows = React12.useMemo(
2125
+ () => visibleEndpoints.map((ep) => buildEndpointRow(ep, loadedEndpoint, ep.schemaId ?? null)),
2126
+ [visibleEndpoints, loadedEndpoint]
2127
+ );
2128
+ const isEmpty = rows.length === 0;
2129
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-[860px] px-6 md:px-10 lg:px-14 py-12", children: [
2130
+ info && /* @__PURE__ */ jsxRuntime.jsx(
2131
+ ApiIntroSection,
2132
+ {
2133
+ info,
2134
+ schema: rawSchema,
2135
+ endpoints: visibleEndpoints,
2136
+ resolvedBaseUrl
2137
+ }
2138
+ ),
2139
+ isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-16 text-center text-sm text-muted-foreground", children: "No endpoints to display." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/60", children: rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
2140
+ EndpointDoc,
2141
+ {
2142
+ endpoint: row.endpoint,
2143
+ isLoadedInPlayground: row.isLoaded,
2144
+ onTryIt: () => onTryEndpoint(row.endpoint),
2145
+ schemaId: row.schemaId
2146
+ },
2147
+ row.key
2148
+ )) })
2149
+ ] }) });
2150
+ }
2151
+ chunkWGEGR3DF_cjs.__name(SelectorBody, "SelectorBody");
2152
+ function SectionsBody({
2153
+ scrollRef,
2154
+ schemasData,
2155
+ selectedVersion,
2156
+ loadedEndpoint,
2157
+ onTryEndpoint
2158
+ }) {
2159
+ const sections = React12.useMemo(
2160
+ () => schemasData.map((e) => buildSchemaSectionVM(e, selectedVersion, loadedEndpoint)),
2161
+ [schemasData, selectedVersion, loadedEndpoint]
2162
+ );
2163
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-[860px] px-6 md:px-10 lg:px-14 py-12 space-y-16", children: sections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(SchemaSectionView, { section, onTryEndpoint }, section.schemaId)) }) });
2164
+ }
2165
+ chunkWGEGR3DF_cjs.__name(SectionsBody, "SectionsBody");
2166
+ var SchemaSectionView = React12__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function SchemaSectionView2({
2167
+ section,
2168
+ onTryEndpoint
2169
+ }) {
2170
+ const canCopy = section.rawSchema !== null && section.allEndpoints.length > 0;
2171
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { "data-schema-anchor": section.schemaId, className: "scroll-mt-20", children: [
2172
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "mb-8 pb-4 border-b", children: [
2173
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
2174
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-3 min-w-0", children: [
2175
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: section.title }),
2176
+ section.version && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-xs text-muted-foreground/70", children: [
2177
+ "v",
2178
+ section.version
2179
+ ] })
2180
+ ] }),
2181
+ canCopy && /* @__PURE__ */ jsxRuntime.jsx(
2182
+ SchemaCopyMenu,
2183
+ {
2184
+ schema: section.rawSchema,
2185
+ endpoints: section.allEndpoints,
2186
+ baseUrl: section.baseUrl
2187
+ }
2188
+ )
2189
+ ] }),
2190
+ section.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground whitespace-pre-wrap", children: section.description })
2191
+ ] }),
2192
+ /* @__PURE__ */ jsxRuntime.jsx(SchemaSectionStateView, { section, onTryEndpoint })
2193
+ ] });
2194
+ }, "SchemaSectionView"));
2195
+ function SchemaSectionStateView({
2196
+ section,
2197
+ onTryEndpoint
2198
+ }) {
2199
+ switch (section.state.kind) {
2200
+ case "loading":
2201
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-8 text-center text-sm text-muted-foreground", children: [
2202
+ "Loading ",
2203
+ section.title,
2204
+ "\u2026"
2205
+ ] });
2206
+ case "error":
2207
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-8 text-center text-sm text-destructive", children: [
2208
+ "Failed to load ",
2209
+ section.title,
2210
+ ": ",
2211
+ section.state.message
2212
+ ] });
2213
+ case "empty":
2214
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground", children: "No endpoints in this schema." });
2215
+ case "ready":
2216
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/60", children: section.state.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
2217
+ EndpointDoc,
2218
+ {
2219
+ endpoint: row.endpoint,
2220
+ isLoadedInPlayground: row.isLoaded,
2221
+ onTryIt: () => onTryEndpoint(row.endpoint),
2222
+ schemaId: row.schemaId
2223
+ },
2224
+ row.key
2225
+ )) });
2226
+ }
2227
+ }
2228
+ chunkWGEGR3DF_cjs.__name(SchemaSectionStateView, "SchemaSectionStateView");
2229
+ var MAX_DEPTH2 = 6;
2230
+ function defaultForSchema(schema) {
2231
+ if (!schema) return null;
2232
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum[0];
2233
+ switch (schema.type) {
2234
+ case "object": {
2235
+ const out = {};
2236
+ for (const [k, v] of Object.entries(schema.properties ?? {})) {
2237
+ out[k] = defaultForSchema(v);
2238
+ }
2239
+ return out;
2240
+ }
2241
+ case "array":
2242
+ return [];
2243
+ case "integer":
2244
+ case "number":
2245
+ return 0;
2246
+ case "boolean":
2247
+ return false;
2248
+ case "string":
2249
+ return "";
2250
+ default:
2251
+ if (schema.properties) {
2252
+ const out = {};
2253
+ for (const [k, v] of Object.entries(schema.properties)) {
2254
+ out[k] = defaultForSchema(v);
2255
+ }
2256
+ return out;
2257
+ }
2258
+ return "";
2259
+ }
2260
+ }
2261
+ chunkWGEGR3DF_cjs.__name(defaultForSchema, "defaultForSchema");
2262
+ function BodyFormEditor({ schema, value, onChange }) {
2263
+ return /* @__PURE__ */ jsxRuntime.jsx(
2264
+ SchemaField,
2265
+ {
2266
+ schema,
2267
+ value,
2268
+ onChange,
2269
+ depth: 0,
2270
+ required: false
2271
+ }
2272
+ );
2273
+ }
2274
+ chunkWGEGR3DF_cjs.__name(BodyFormEditor, "BodyFormEditor");
2275
+ function SchemaField({ schema, value, onChange, depth, required, label }) {
2276
+ if (depth > MAX_DEPTH2) {
2277
+ return /* @__PURE__ */ jsxRuntime.jsx(RawJsonField, { label, value, onChange });
2278
+ }
2279
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) {
2280
+ return /* @__PURE__ */ jsxRuntime.jsx(EnumField, { schema, value, onChange, label, required });
2281
+ }
2282
+ switch (schema.type) {
2283
+ case "object":
2284
+ return /* @__PURE__ */ jsxRuntime.jsx(ObjectField, { schema, value, onChange, depth, label });
2285
+ case "array":
2286
+ return /* @__PURE__ */ jsxRuntime.jsx(ArrayField, { schema, value, onChange, depth, label, required });
2287
+ case "boolean":
2288
+ return /* @__PURE__ */ jsxRuntime.jsx(BooleanField, { value, onChange, label, schema, required });
2289
+ case "integer":
2290
+ case "number":
2291
+ return /* @__PURE__ */ jsxRuntime.jsx(NumberField, { value, onChange, label, schema, required });
2292
+ case "string":
2293
+ default:
2294
+ if (!schema.type && schema.properties) {
2295
+ return /* @__PURE__ */ jsxRuntime.jsx(ObjectField, { schema, value, onChange, depth, label });
2296
+ }
2297
+ return /* @__PURE__ */ jsxRuntime.jsx(StringField, { value, onChange, label, schema, required });
2298
+ }
2299
+ }
2300
+ chunkWGEGR3DF_cjs.__name(SchemaField, "SchemaField");
2301
+ function FieldHeader({
2302
+ label,
2303
+ type,
2304
+ required,
2305
+ description
2306
+ }) {
2307
+ if (!label) return null;
2308
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2309
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5", children: [
2310
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px] text-foreground/80", children: label }),
2311
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-destructive font-bold leading-none", children: "*" }),
2312
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground/50", children: type })
2313
+ ] }),
2314
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground/70 leading-snug", children: description })
2315
+ ] });
2316
+ }
2317
+ chunkWGEGR3DF_cjs.__name(FieldHeader, "FieldHeader");
2318
+ function StringField({
2319
+ value,
2320
+ onChange,
2321
+ label,
2322
+ schema,
2323
+ required
2324
+ }) {
2325
+ const stringValue = typeof value === "string" ? value : value == null ? "" : String(value);
2326
+ const placeholder = schema.format ? `${schema.type ?? "string"} (${schema.format})` : schema.description || schema.type || "string";
2327
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2328
+ /* @__PURE__ */ jsxRuntime.jsx(FieldHeader, { label, type: schema.format ? `string (${schema.format})` : "string", required, description: schema.description }),
2329
+ /* @__PURE__ */ jsxRuntime.jsx(
2330
+ components.Input,
2331
+ {
2332
+ value: stringValue,
2333
+ onChange: (e) => onChange(e.target.value),
2334
+ placeholder,
2335
+ className: "h-8 text-xs font-mono"
2336
+ }
2337
+ )
2338
+ ] });
2339
+ }
2340
+ chunkWGEGR3DF_cjs.__name(StringField, "StringField");
2341
+ function NumberField({
2342
+ value,
2343
+ onChange,
2344
+ label,
2345
+ schema,
2346
+ required
2347
+ }) {
2348
+ const raw = value == null ? "" : String(value);
2349
+ const type = schema.type === "integer" ? "integer" : "number";
2350
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2351
+ /* @__PURE__ */ jsxRuntime.jsx(FieldHeader, { label, type: schema.format ? `${type} (${schema.format})` : type, required, description: schema.description }),
2352
+ /* @__PURE__ */ jsxRuntime.jsx(
2353
+ components.Input,
2354
+ {
2355
+ type: "number",
2356
+ value: raw,
2357
+ onChange: (e) => {
2358
+ const v = e.target.value;
2359
+ if (v === "") return onChange(null);
2360
+ const n = schema.type === "integer" ? parseInt(v, 10) : parseFloat(v);
2361
+ onChange(Number.isNaN(n) ? null : n);
2362
+ },
2363
+ placeholder: type,
2364
+ className: "h-8 text-xs font-mono"
2365
+ }
2366
+ )
2367
+ ] });
2368
+ }
2369
+ chunkWGEGR3DF_cjs.__name(NumberField, "NumberField");
2370
+ function BooleanField({
2371
+ value,
2372
+ onChange,
2373
+ label,
2374
+ schema,
2375
+ required
2376
+ }) {
2377
+ const bool = value === true;
2378
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
2379
+ /* @__PURE__ */ jsxRuntime.jsx(FieldHeader, { label, type: "boolean", required, description: schema.description }),
2380
+ /* @__PURE__ */ jsxRuntime.jsx(components.Switch, { checked: bool, onCheckedChange: onChange, className: "mt-0.5 shrink-0" })
2381
+ ] });
2382
+ }
2383
+ chunkWGEGR3DF_cjs.__name(BooleanField, "BooleanField");
2384
+ function EnumField({
2385
+ schema,
2386
+ value,
2387
+ onChange,
2388
+ label,
2389
+ required
2390
+ }) {
2391
+ const options = (schema.enum ?? []).map((v) => ({
2392
+ value: String(v),
2393
+ label: String(v)
2394
+ }));
2395
+ const strValue = value == null ? "" : String(value);
2396
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2397
+ /* @__PURE__ */ jsxRuntime.jsx(FieldHeader, { label, type: `${schema.type ?? "enum"} enum`, required, description: schema.description }),
2398
+ /* @__PURE__ */ jsxRuntime.jsx(
2399
+ components.Combobox,
2400
+ {
2401
+ options,
2402
+ value: strValue,
2403
+ onValueChange: (v) => {
2404
+ if (schema.type === "integer") onChange(parseInt(v, 10));
2405
+ else if (schema.type === "number") onChange(parseFloat(v));
2406
+ else onChange(v);
2407
+ },
2408
+ placeholder: "Select\u2026",
2409
+ searchPlaceholder: "Search\u2026",
2410
+ className: "h-8 text-xs"
2411
+ }
2412
+ )
2413
+ ] });
2414
+ }
2415
+ chunkWGEGR3DF_cjs.__name(EnumField, "EnumField");
2416
+ function RawJsonField({
2417
+ label,
2418
+ value,
2419
+ onChange
2420
+ }) {
2421
+ const [text, setText] = React12__default.default.useState(() => JSON.stringify(value ?? null, null, 2));
2422
+ React12__default.default.useEffect(() => {
2423
+ setText(JSON.stringify(value ?? null, null, 2));
2424
+ }, [value]);
2425
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2426
+ label && /* @__PURE__ */ jsxRuntime.jsxs(SectionLabel, { children: [
2427
+ label,
2428
+ " (raw)"
2429
+ ] }),
2430
+ /* @__PURE__ */ jsxRuntime.jsx(
2431
+ components.Textarea,
2432
+ {
2433
+ value: text,
2434
+ onChange: (e) => {
2435
+ setText(e.target.value);
2436
+ try {
2437
+ onChange(JSON.parse(e.target.value));
2438
+ } catch {
2439
+ }
2440
+ },
2441
+ className: "font-mono text-[11px] min-h-[80px]",
2442
+ rows: 4
2443
+ }
2444
+ )
2445
+ ] });
2446
+ }
2447
+ chunkWGEGR3DF_cjs.__name(RawJsonField, "RawJsonField");
2448
+ function ObjectField({
2449
+ schema,
2450
+ value,
2451
+ onChange,
2452
+ depth,
2453
+ label
2454
+ }) {
2455
+ const obj = value && typeof value === "object" && !Array.isArray(value) ? value : {};
2456
+ const required = new Set(schema.required ?? []);
2457
+ const entries = Object.entries(schema.properties ?? {});
2458
+ const setKey = React12.useCallback(
2459
+ (key) => (next) => {
2460
+ onChange({ ...obj, [key]: next });
2461
+ },
2462
+ [obj, onChange]
2463
+ );
2464
+ if (entries.length === 0) {
2465
+ return /* @__PURE__ */ jsxRuntime.jsx(RawJsonField, { label, value: obj, onChange });
2466
+ }
2467
+ const wrapperClass = depth === 0 ? "space-y-3" : "space-y-2 border-l-2 border-border/60 pl-3 ml-px";
2468
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2469
+ label && depth > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5", children: [
2470
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px] text-foreground/80", children: label }),
2471
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground/50", children: "object" })
2472
+ ] }),
2473
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: lib.cn(wrapperClass), children: entries.map(([key, subSchema]) => /* @__PURE__ */ jsxRuntime.jsx(
2474
+ SchemaField,
2475
+ {
2476
+ schema: subSchema,
2477
+ value: obj[key],
2478
+ onChange: setKey(key),
2479
+ depth: depth + 1,
2480
+ required: required.has(key),
2481
+ label: key
2482
+ },
2483
+ key
2484
+ )) })
2485
+ ] });
2486
+ }
2487
+ chunkWGEGR3DF_cjs.__name(ObjectField, "ObjectField");
2488
+ function ArrayField({
2489
+ schema,
2490
+ value,
2491
+ onChange,
2492
+ depth,
2493
+ label,
2494
+ required
2495
+ }) {
2496
+ const arr = Array.isArray(value) ? value : [];
2497
+ const items = schema.items ?? { type: "string" };
2498
+ const addItem = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => onChange([...arr, defaultForSchema(items)]), "addItem");
2499
+ const removeAt = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((i) => onChange(arr.filter((_, idx) => idx !== i)), "removeAt");
2500
+ const setAt = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((i) => (next) => onChange(arr.map((v, idx) => idx === i ? next : v)), "setAt");
2501
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2502
+ label && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5", children: [
2503
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px] text-foreground/80", children: label }),
2504
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-destructive font-bold leading-none", children: "*" }),
2505
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground/50", children: `array<${items.type ?? "any"}>` })
2506
+ ] }),
2507
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 border-l-2 border-border/60 pl-3 ml-px", children: [
2508
+ arr.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground/50 italic", children: "Empty array" }),
2509
+ arr.map((v, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
2510
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
2511
+ SchemaField,
2512
+ {
2513
+ schema: items,
2514
+ value: v,
2515
+ onChange: setAt(i),
2516
+ depth: depth + 1,
2517
+ required: false,
2518
+ label: `${label ?? ""}[${i}]`
2519
+ }
2520
+ ) }),
2521
+ /* @__PURE__ */ jsxRuntime.jsx(
2522
+ "button",
2523
+ {
2524
+ type: "button",
2525
+ onClick: () => removeAt(i),
2526
+ title: "Remove item",
2527
+ className: "shrink-0 h-7 w-7 inline-flex items-center justify-center rounded-md text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors",
2528
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "h-3.5 w-3.5" })
2529
+ }
2530
+ )
2531
+ ] }, i)),
2532
+ /* @__PURE__ */ jsxRuntime.jsxs(
2533
+ "button",
2534
+ {
2535
+ type: "button",
2536
+ onClick: addItem,
2537
+ className: "inline-flex items-center gap-1.5 text-[10px] text-muted-foreground hover:text-foreground transition-colors py-1",
2538
+ children: [
2539
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3 w-3" }),
2540
+ "Add item"
2541
+ ]
2542
+ }
2543
+ )
2544
+ ] })
2545
+ ] });
2546
+ }
2547
+ chunkWGEGR3DF_cjs.__name(ArrayField, "ArrayField");
2548
+ function EndpointResetButton() {
2549
+ const { state, setParameters, setRequestBody } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2550
+ const ep = state.selectedEndpoint;
2551
+ const { reset } = useEndpointDraft(state.activeSchemaId, ep);
2552
+ const hasDraft = Object.keys(state.parameters).length > 0 || state.requestBody.length > 0;
2553
+ const onClick = React12.useCallback(() => {
2554
+ setParameters({});
2555
+ setRequestBody("");
2556
+ reset();
2557
+ }, [setParameters, setRequestBody, reset]);
2558
+ if (!ep || !hasDraft) return null;
2559
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2560
+ "button",
2561
+ {
2562
+ type: "button",
2563
+ onClick,
2564
+ title: "Reset parameters & body (keeps auth)",
2565
+ className: lib.cn(
2566
+ "inline-flex items-center gap-1 text-[10px] text-muted-foreground",
2567
+ "hover:text-foreground transition-colors"
2568
+ ),
2569
+ children: [
2570
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "h-2.5 w-2.5" }),
2571
+ "Reset"
2572
+ ]
2573
+ }
2574
+ );
2575
+ }
2576
+ chunkWGEGR3DF_cjs.__name(EndpointResetButton, "EndpointResetButton");
2577
+ function ParamFields({ label, params }) {
2578
+ const { state, setParameters } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2579
+ function handleChange(name, value) {
2580
+ setParameters({ ...state.parameters, [name]: value });
2581
+ }
2582
+ chunkWGEGR3DF_cjs.__name(handleChange, "handleChange");
2583
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2584
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: label }),
2585
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: params.map((p) => {
2586
+ const value = state.parameters[p.name] ?? "";
2587
+ const placeholder = p.description || p.name;
2588
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2589
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
2590
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px] text-foreground/80", children: p.name }),
2591
+ p.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-destructive font-bold leading-none", children: "*" }),
2592
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground/50", children: p.type })
2593
+ ] }),
2594
+ /* @__PURE__ */ jsxRuntime.jsx(
2595
+ components.Input,
2596
+ {
2597
+ value,
2598
+ onChange: (e) => handleChange(p.name, e.target.value),
2599
+ placeholder,
2600
+ className: "h-8 text-xs font-mono"
2601
+ }
2602
+ )
2603
+ ] }, p.name);
2604
+ }) })
2605
+ ] });
2606
+ }
2607
+ chunkWGEGR3DF_cjs.__name(ParamFields, "ParamFields");
2608
+ function RequestPanel() {
2609
+ const {
2610
+ state,
2611
+ apiKeys,
2612
+ apiKeysLoading,
2613
+ setRequestBody,
2614
+ setRequestHeaders,
2615
+ setSelectedApiKey,
2616
+ setManualApiToken,
2617
+ sendRequest
2618
+ } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2619
+ const apiKeyOptions = React12.useMemo(
2620
+ () => apiKeys.map((k) => ({
2621
+ value: k.id,
2622
+ label: k.name || "Unnamed key",
2623
+ // Surface the first 8 chars of the secret so the user
2624
+ // can tell two similarly-named keys apart at a glance.
2625
+ description: k.secret ? `${k.secret.slice(0, 8)}\u2026` : void 0
2626
+ })),
2627
+ [apiKeys]
2628
+ );
2629
+ const hasApiKeys = apiKeyOptions.length > 0;
2630
+ const ep = state.selectedEndpoint;
2631
+ const isJsonValid = state.requestBody ? chunk5Q4UMSWB_cjs.isValidJson(state.requestBody) : true;
2632
+ const curlCommand = React12.useMemo(() => {
2633
+ if (!state.requestUrl) return "";
2634
+ const absoluteUrl = chunk5Q4UMSWB_cjs.resolveAbsolute(state.requestUrl);
2635
+ const apiKey = state.selectedApiKey ? chunk5Q4UMSWB_cjs.findApiKeyById(apiKeys, state.selectedApiKey) : null;
2636
+ const hdrs = chunk5Q4UMSWB_cjs.parseRequestHeaders(state.requestHeaders);
2637
+ if (apiKey) hdrs["X-API-Key"] = apiKey.secret || apiKey.id;
2638
+ let cmd = `curl -X ${state.requestMethod} "${absoluteUrl}"`;
2639
+ Object.entries(hdrs).forEach(([k, v]) => {
2640
+ cmd += ` \\
2641
+ -H "${k}: ${v}"`;
2642
+ });
2643
+ if (state.requestBody && state.requestMethod !== "GET" && isJsonValid) {
2644
+ cmd += ` \\
2645
+ -d '${state.requestBody}'`;
2646
+ }
2647
+ return cmd;
2648
+ }, [state, apiKeys, isJsonValid]);
2649
+ const pathParams = React12.useMemo(
2650
+ () => ep?.parameters?.filter((p) => ep.path.includes(`{${p.name}}`)) ?? [],
2651
+ [ep]
2652
+ );
2653
+ const queryParams = React12.useMemo(
2654
+ () => ep?.parameters?.filter((p) => !ep.path.includes(`{${p.name}}`)) ?? [],
2655
+ [ep]
2656
+ );
2657
+ state.loading || !state.requestUrl || !isJsonValid;
2658
+ const displayUrl = chunk5Q4UMSWB_cjs.resolveAbsolute(state.requestUrl || ep?.path || "");
2659
+ const hasBody = ep?.method !== "GET";
2660
+ const bodyType = ep?.requestBody?.type ?? "";
2661
+ const hasPathParams = pathParams.length > 0;
2662
+ const hasQueryParams = queryParams.length > 0;
2663
+ const hasCurl = Boolean(curlCommand);
2664
+ const epPath = ep ? chunk5Q4UMSWB_cjs.relativePath(ep.path) : "";
2665
+ const urlChanged = displayUrl !== "" && displayUrl !== epPath;
2666
+ if (!ep) {
2667
+ return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { icon: lucideReact.Send, text: "Select an endpoint to build a request" });
2668
+ }
2669
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2670
+ (urlChanged || ep) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-4 py-2 bg-muted/10 flex items-center gap-2 min-h-[28px]", children: [
2671
+ urlChanged ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground/60 break-all leading-snug truncate min-w-0 flex-1", children: displayUrl }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1" }),
2672
+ /* @__PURE__ */ jsxRuntime.jsx(EndpointResetButton, {})
2673
+ ] }),
2674
+ /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: "px-4 py-3 space-y-3", children: [
2675
+ hasPathParams && /* @__PURE__ */ jsxRuntime.jsx(ParamFields, { label: "Path Parameters", params: pathParams }),
2676
+ hasQueryParams && /* @__PURE__ */ jsxRuntime.jsx(ParamFields, { label: "Query Parameters", params: queryParams }),
2677
+ hasBody && /* @__PURE__ */ jsxRuntime.jsx(
2678
+ BodySection,
2679
+ {
2680
+ schema: ep.requestBody?.schema,
2681
+ bodyType,
2682
+ bodyDescription: ep.requestBody?.description,
2683
+ value: state.requestBody,
2684
+ onChange: setRequestBody,
2685
+ isJsonValid
2686
+ }
2687
+ ),
2688
+ /* @__PURE__ */ jsxRuntime.jsx(
2689
+ CollapsibleSection,
2690
+ {
2691
+ label: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
2692
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Key, { className: "h-2.5 w-2.5" }),
2693
+ "Auth & Headers"
2694
+ ] }),
2695
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 pt-2", children: [
2696
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2697
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "API Key" }),
2698
+ /* @__PURE__ */ jsxRuntime.jsx(
2699
+ components.Combobox,
2700
+ {
2701
+ options: apiKeyOptions,
2702
+ value: state.selectedApiKey ?? "",
2703
+ onValueChange: (v) => setSelectedApiKey(v || null),
2704
+ placeholder: apiKeysLoading ? "Loading keys\u2026" : hasApiKeys ? "Select an API key" : "No API keys yet",
2705
+ searchPlaceholder: "Search keys\u2026",
2706
+ emptyText: "No matching key",
2707
+ disabled: apiKeysLoading || !hasApiKeys,
2708
+ className: "h-8"
2709
+ }
2710
+ ),
2711
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[10px] text-muted-foreground", children: [
2712
+ "Picks are sent via the",
2713
+ " ",
2714
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: "X-API-Key" }),
2715
+ " header."
2716
+ ] })
2717
+ ] }),
2718
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2719
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Bearer Token" }),
2720
+ /* @__PURE__ */ jsxRuntime.jsx(
2721
+ components.Input,
2722
+ {
2723
+ type: "password",
2724
+ placeholder: "Leave empty to use JWT from localStorage",
2725
+ value: state.manualApiToken,
2726
+ onChange: (e) => setManualApiToken(e.target.value),
2727
+ className: "font-mono text-xs h-8"
2728
+ }
2729
+ )
2730
+ ] }),
2731
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2732
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Headers" }),
2733
+ /* @__PURE__ */ jsxRuntime.jsx(
2734
+ components.Textarea,
2735
+ {
2736
+ value: state.requestHeaders,
2737
+ onChange: (e) => setRequestHeaders(e.target.value),
2738
+ className: "font-mono text-[11px] min-h-[60px] resize-y",
2739
+ rows: 3
2740
+ }
2741
+ )
2742
+ ] })
2743
+ ] })
2744
+ }
2745
+ ),
2746
+ hasCurl && /* @__PURE__ */ jsxRuntime.jsx(
2747
+ CollapsibleSection,
2748
+ {
2749
+ label: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
2750
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Terminal, { className: "h-2.5 w-2.5" }),
2751
+ "cURL"
2752
+ ] }),
2753
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
2754
+ chunk5Q4UMSWB_cjs.PrettyCode_default,
2755
+ {
2756
+ data: curlCommand,
2757
+ language: "bash",
2758
+ isCompact: true,
2759
+ maxLines: 50
2760
+ }
2761
+ ) })
2762
+ }
2763
+ ),
2764
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4" })
2765
+ ] })
2766
+ ] });
2767
+ }
2768
+ chunkWGEGR3DF_cjs.__name(RequestPanel, "RequestPanel");
2769
+ function BodySection({ schema, bodyType, bodyDescription, value, onChange, isJsonValid }) {
2770
+ const hasSchema = !!schema;
2771
+ const [mode, setMode] = React12__default.default.useState(hasSchema ? "form" : "json");
2772
+ const parsed = React12__default.default.useMemo(() => {
2773
+ if (!value) return null;
2774
+ try {
2775
+ return JSON.parse(value);
2776
+ } catch {
2777
+ return null;
2778
+ }
2779
+ }, [value]);
2780
+ const handleFormChange = React12.useCallback(
2781
+ (next) => {
2782
+ onChange(JSON.stringify(next, null, 2));
2783
+ },
2784
+ [onChange]
2785
+ );
2786
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
2787
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
2788
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 min-w-0", children: [
2789
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Body" }),
2790
+ bodyType && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/40 font-mono", children: bodyType }),
2791
+ bodyDescription && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/60 truncate", children: bodyDescription })
2792
+ ] }),
2793
+ hasSchema && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex rounded-md border overflow-hidden text-[10px]", children: [
2794
+ /* @__PURE__ */ jsxRuntime.jsx(ModeButton, { active: mode === "form", onClick: () => setMode("form"), children: "Form" }),
2795
+ /* @__PURE__ */ jsxRuntime.jsx(ModeButton, { active: mode === "json", onClick: () => setMode("json"), children: "JSON" })
2796
+ ] }),
2797
+ mode === "json" && isJsonValid && value && /* @__PURE__ */ jsxRuntime.jsxs(
2798
+ "button",
2799
+ {
2800
+ type: "button",
2801
+ onClick: () => {
2802
+ try {
2803
+ onChange(JSON.stringify(JSON.parse(value), null, 2));
2804
+ } catch {
2805
+ }
2806
+ },
2807
+ className: "inline-flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground transition-colors",
2808
+ children: [
2809
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-2.5 w-2.5" }),
2810
+ "Format"
2811
+ ]
2812
+ }
2813
+ )
2814
+ ] }),
2815
+ mode === "form" && hasSchema ? /* @__PURE__ */ jsxRuntime.jsx(
2816
+ BodyFormEditor,
2817
+ {
2818
+ schema,
2819
+ value: parsed,
2820
+ onChange: handleFormChange
2821
+ }
2822
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2823
+ /* @__PURE__ */ jsxRuntime.jsx(
2824
+ components.Textarea,
2825
+ {
2826
+ placeholder: '{\n "key": "value"\n}',
2827
+ value,
2828
+ onChange: (e) => onChange(e.target.value),
2829
+ className: lib.cn(
2830
+ "font-mono text-[11px] min-h-[90px] resize-y",
2831
+ !isJsonValid && "border-destructive focus-visible:ring-destructive/30"
2832
+ ),
2833
+ rows: 4
2834
+ }
2835
+ ),
2836
+ !isJsonValid && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-destructive", children: "Invalid JSON" })
2837
+ ] })
2838
+ ] });
2839
+ }
2840
+ chunkWGEGR3DF_cjs.__name(BodySection, "BodySection");
2841
+ function ModeButton({
2842
+ active,
2843
+ onClick,
2844
+ children
2845
+ }) {
2846
+ return /* @__PURE__ */ jsxRuntime.jsx(
2847
+ "button",
2848
+ {
2849
+ type: "button",
2850
+ onClick,
2851
+ className: lib.cn(
2852
+ "px-2 py-0.5 font-medium transition-colors",
2853
+ active ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:text-foreground"
2854
+ ),
2855
+ children
2856
+ }
2857
+ );
2858
+ }
2859
+ chunkWGEGR3DF_cjs.__name(ModeButton, "ModeButton");
2860
+ function looksLikeSpaShell(html) {
2861
+ const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
2862
+ const bodyContent = (bodyMatch?.[1] ?? html).replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<!--[\s\S]*?-->/g, "").trim();
2863
+ if (bodyContent.length === 0) return true;
2864
+ const singleEmptyContainer = /^<(div|main|section)[^>]*>\s*<\/\1>$/i;
2865
+ if (singleEmptyContainer.test(bodyContent)) return true;
2866
+ return false;
2867
+ }
2868
+ chunkWGEGR3DF_cjs.__name(looksLikeSpaShell, "looksLikeSpaShell");
2869
+ function PreviewView({ html }) {
2870
+ const isSpaShell = React12.useMemo(() => looksLikeSpaShell(html), [html]);
2871
+ if (!html) {
2872
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 text-center text-xs text-muted-foreground", children: "Empty response body" });
2873
+ }
2874
+ if (isSpaShell) {
2875
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center gap-3 min-h-[400px]", children: [
2876
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center justify-center h-10 w-10 rounded-full bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "h-5 w-5 text-muted-foreground" }) }),
2877
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-sm space-y-1.5", children: [
2878
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: "Looks like a single-page app shell" }),
2879
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground leading-relaxed", children: [
2880
+ "This page renders its content with JavaScript at runtime. Scripts are disabled in the sandbox, so Preview would show a blank page. Switch to ",
2881
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Pretty" }),
2882
+ " or",
2883
+ " ",
2884
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Raw" }),
2885
+ " to inspect the HTML source."
2886
+ ] })
2887
+ ] })
2888
+ ] });
2889
+ }
2890
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full min-h-[400px]", children: [
2891
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 flex items-center gap-1.5 px-3 py-1.5 bg-muted/30 border-b text-[10px] text-muted-foreground/70", children: [
2892
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "h-3 w-3" }),
2893
+ "Sandboxed preview \u2014 scripts, forms and popups are disabled"
2894
+ ] }),
2895
+ /* @__PURE__ */ jsxRuntime.jsx(
2896
+ "div",
2897
+ {
2898
+ className: "flex-1 min-h-[360px] p-2",
2899
+ style: {
2900
+ backgroundColor: "#fff",
2901
+ backgroundImage: "linear-gradient(45deg, #f3f4f6 25%, transparent 25%), linear-gradient(-45deg, #f3f4f6 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f3f4f6 75%), linear-gradient(-45deg, transparent 75%, #f3f4f6 75%)",
2902
+ backgroundSize: "16px 16px",
2903
+ backgroundPosition: "0 0, 0 8px, 8px -8px, -8px 0px"
2904
+ },
2905
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2906
+ "iframe",
2907
+ {
2908
+ title: "Response preview",
2909
+ srcDoc: html,
2910
+ sandbox: "",
2911
+ className: "w-full h-full min-h-[360px] bg-white border-0 rounded shadow-sm"
2912
+ }
2913
+ )
2914
+ }
2915
+ )
2916
+ ] });
2917
+ }
2918
+ chunkWGEGR3DF_cjs.__name(PreviewView, "PreviewView");
2919
+ var JSON_TREE_CONFIG = {
2920
+ maxAutoExpandDepth: 2,
2921
+ maxAutoExpandArrayItems: 10,
2922
+ maxAutoExpandObjectKeys: 5,
2923
+ maxStringLength: 200,
2924
+ collectionLimit: 50,
2925
+ showCollectionInfo: true,
2926
+ showExpandControls: true,
2927
+ showActionButtons: false,
2928
+ preserveKeyOrder: true,
2929
+ className: "border-0 rounded-none"
2930
+ };
2931
+ function PrettyView({ treeData, rawText, detected }) {
2932
+ if (detected.kind === "json" && treeData != null) {
2933
+ return /* @__PURE__ */ jsxRuntime.jsx(chunk33AMWFBZ_cjs.JsonTree_default, { title: "Response Body", data: treeData, config: JSON_TREE_CONFIG });
2934
+ }
2935
+ if (!rawText) {
2936
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 text-center text-xs text-muted-foreground", children: "Empty response body" });
2937
+ }
2938
+ return /* @__PURE__ */ jsxRuntime.jsx(
2939
+ chunk5Q4UMSWB_cjs.PrettyCode_default,
2940
+ {
2941
+ data: rawText,
2942
+ language: detected.prism,
2943
+ variant: "plain",
2944
+ isCompact: true
2945
+ }
2946
+ );
2947
+ }
2948
+ chunkWGEGR3DF_cjs.__name(PrettyView, "PrettyView");
2949
+ function RawView({ rawText }) {
2950
+ if (!rawText) {
2951
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 text-center text-xs text-muted-foreground", children: "Empty response body" });
2952
+ }
2953
+ return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-4 text-[11px] font-mono text-foreground/70 whitespace-pre-wrap break-all leading-relaxed", children: rawText });
2954
+ }
2955
+ chunkWGEGR3DF_cjs.__name(RawView, "RawView");
2956
+ function StatusBar({ response, rawText, contentType }) {
2957
+ const sizeKb = rawText ? `${(rawText.length / 1024).toFixed(1)} KB` : "";
2958
+ const duration = response.duration != null ? `${response.duration}ms` : "";
2959
+ const hasStatus = response.status != null;
2960
+ const hasCopy = Boolean(rawText);
2961
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-4 py-2 flex items-center justify-between gap-3 bg-muted/20", children: [
2962
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
2963
+ hasStatus && /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: response.status }),
2964
+ response.statusText && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground truncate", children: response.statusText }),
2965
+ sizeKb && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/50 tabular-nums shrink-0", children: sizeKb }),
2966
+ duration && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/50 tabular-nums shrink-0", children: duration }),
2967
+ contentType && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/50 font-mono truncate", children: contentType })
2968
+ ] }),
2969
+ hasCopy && /* @__PURE__ */ jsxRuntime.jsx(
2970
+ components.CopyButton,
2971
+ {
2972
+ value: rawText,
2973
+ variant: "ghost",
2974
+ size: "sm",
2975
+ className: "h-6 px-2 text-[10px] text-muted-foreground shrink-0",
2976
+ children: "Copy"
2977
+ }
2978
+ )
2979
+ ] });
2980
+ }
2981
+ chunkWGEGR3DF_cjs.__name(StatusBar, "StatusBar");
2982
+
2983
+ // src/tools/OpenapiViewer/components/shared/ResponsePanel/detectContent.ts
2984
+ function normaliseContentType(raw) {
2985
+ if (!raw) return null;
2986
+ const semi = raw.indexOf(";");
2987
+ return (semi === -1 ? raw : raw.slice(0, semi)).trim().toLowerCase();
2988
+ }
2989
+ chunkWGEGR3DF_cjs.__name(normaliseContentType, "normaliseContentType");
2990
+ function readContentType(headers) {
2991
+ if (!headers) return null;
2992
+ if (typeof headers.get === "function") {
2993
+ return headers.get("content-type");
2994
+ }
2995
+ if (typeof headers === "object") {
2996
+ for (const [k, v] of Object.entries(headers)) {
2997
+ if (k.toLowerCase() === "content-type") {
2998
+ return typeof v === "string" ? v : null;
2999
+ }
3000
+ }
3001
+ }
3002
+ return null;
3003
+ }
3004
+ chunkWGEGR3DF_cjs.__name(readContentType, "readContentType");
3005
+ function kindFromContentType(mime) {
3006
+ if (!mime) return "text";
3007
+ if (mime === "application/json" || mime.endsWith("+json")) return "json";
3008
+ if (mime === "text/html" || mime === "application/xhtml+xml") return "html";
3009
+ if (mime === "application/xml" || mime === "text/xml" || mime.endsWith("+xml")) return "xml";
3010
+ if (mime === "text/css") return "css";
3011
+ if (mime === "application/javascript" || mime === "text/javascript" || mime === "application/x-javascript") return "javascript";
3012
+ return "text";
3013
+ }
3014
+ chunkWGEGR3DF_cjs.__name(kindFromContentType, "kindFromContentType");
3015
+ function kindFromBody(body) {
3016
+ const trimmed = body.trimStart();
3017
+ if (!trimmed) return null;
3018
+ if (trimmed.startsWith("<!DOCTYPE") || /^<html[\s>]/i.test(trimmed)) return "html";
3019
+ if (trimmed.startsWith("<?xml")) return "xml";
3020
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
3021
+ try {
3022
+ JSON.parse(trimmed);
3023
+ return "json";
3024
+ } catch {
3025
+ }
3026
+ }
3027
+ return null;
3028
+ }
3029
+ chunkWGEGR3DF_cjs.__name(kindFromBody, "kindFromBody");
3030
+ var PRISM_BY_KIND = {
3031
+ json: "json",
3032
+ // ``markup`` is Prism's HTML/XML grammar — there isn't a separate
3033
+ // ``html`` language. XML piggy-backs on the same tokeniser.
3034
+ html: "markup",
3035
+ xml: "markup",
3036
+ css: "css",
3037
+ javascript: "javascript",
3038
+ text: "markup"
3039
+ };
3040
+ function detectContent(headers, rawBody) {
3041
+ const contentType = normaliseContentType(readContentType(headers));
3042
+ const headerKind = kindFromContentType(contentType);
3043
+ const kind = headerKind === "text" ? kindFromBody(rawBody) ?? "text" : headerKind;
3044
+ return {
3045
+ kind,
3046
+ prism: PRISM_BY_KIND[kind],
3047
+ contentType
3048
+ };
3049
+ }
3050
+ chunkWGEGR3DF_cjs.__name(detectContent, "detectContent");
3051
+
3052
+ // src/tools/OpenapiViewer/components/shared/ResponsePanel/useResponseView.ts
3053
+ function useResponseView(data, headers) {
3054
+ return React12.useMemo(() => {
3055
+ if (data == null) {
3056
+ return {
3057
+ treeData: null,
3058
+ rawText: "",
3059
+ detected: detectContent(headers, "")
3060
+ };
3061
+ }
3062
+ if (typeof data === "string") {
3063
+ try {
3064
+ return {
3065
+ treeData: JSON.parse(data),
3066
+ rawText: data,
3067
+ detected: detectContent(headers, data)
3068
+ };
3069
+ } catch {
3070
+ return {
3071
+ treeData: null,
3072
+ rawText: data,
3073
+ detected: detectContent(headers, data)
3074
+ };
3075
+ }
3076
+ }
3077
+ const stringified = (() => {
3078
+ try {
3079
+ return JSON.stringify(data, null, 2);
3080
+ } catch {
3081
+ return String(data);
3082
+ }
3083
+ })();
3084
+ return {
3085
+ treeData: data,
3086
+ rawText: stringified,
3087
+ detected: detectContent(headers, stringified)
3088
+ };
3089
+ }, [data, headers]);
3090
+ }
3091
+ chunkWGEGR3DF_cjs.__name(useResponseView, "useResponseView");
3092
+ var LABELS = {
3093
+ pretty: "Pretty",
3094
+ raw: "Raw",
3095
+ preview: "Preview"
3096
+ };
3097
+ function ViewTabs({ active, onChange, showPreview }) {
3098
+ const tabs = showPreview ? ["pretty", "raw", "preview"] : ["pretty", "raw"];
3099
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-b px-3 py-1.5 flex items-center gap-1", children: tabs.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
3100
+ "button",
3101
+ {
3102
+ type: "button",
3103
+ onClick: () => onChange(t),
3104
+ className: lib.cn(
3105
+ "h-6 px-2.5 rounded text-[11px] font-medium transition-colors",
3106
+ active === t ? "bg-muted text-foreground" : "text-muted-foreground/70 hover:text-foreground hover:bg-muted/50"
3107
+ ),
3108
+ children: LABELS[t]
3109
+ },
3110
+ t
3111
+ )) });
3112
+ }
3113
+ chunkWGEGR3DF_cjs.__name(ViewTabs, "ViewTabs");
3114
+ function ResponsePanel() {
3115
+ const { state } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
3116
+ const { response, loading, selectedEndpoint } = state;
3117
+ const { treeData, rawText, detected } = useResponseView(response?.data, response?.headers);
3118
+ const showPreview = detected.kind === "html";
3119
+ const [mode, setMode] = React12.useState(showPreview ? "preview" : "pretty");
3120
+ React12.useEffect(() => {
3121
+ setMode(showPreview ? "preview" : "pretty");
3122
+ }, [selectedEndpoint, response, showPreview]);
3123
+ if (loading) {
3124
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center h-full gap-2", children: [
3125
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }),
3126
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Sending\u2026" })
3127
+ ] });
3128
+ }
3129
+ if (!selectedEndpoint) return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { icon: lucideReact.Terminal, text: "Response will appear here" });
3130
+ if (!response) return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { icon: lucideReact.Send, text: 'Press "Send Request" to see the response' });
3131
+ const hasError = Boolean(response.error);
3132
+ const hasStatus = response.status != null;
3133
+ if (hasError && !hasStatus) {
3134
+ return /* @__PURE__ */ jsxRuntime.jsx(
3135
+ EmptyState,
3136
+ {
3137
+ icon: lucideReact.WifiOff,
3138
+ text: response.error,
3139
+ className: "text-destructive [&_svg]:text-destructive"
3140
+ }
3141
+ );
3142
+ }
3143
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3144
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBar, { response, rawText, contentType: detected.contentType }),
3145
+ hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 mx-4 mt-3 rounded border border-destructive/20 bg-destructive/5 px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: response.error }) }),
3146
+ /* @__PURE__ */ jsxRuntime.jsx(ViewTabs, { active: mode, onChange: setMode, showPreview }),
3147
+ /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { children: [
3148
+ mode === "pretty" && /* @__PURE__ */ jsxRuntime.jsx(PrettyView, { treeData, rawText, detected }),
3149
+ mode === "raw" && /* @__PURE__ */ jsxRuntime.jsx(RawView, { rawText }),
3150
+ mode === "preview" && /* @__PURE__ */ jsxRuntime.jsx(PreviewView, { html: rawText })
3151
+ ] })
3152
+ ] });
3153
+ }
3154
+ chunkWGEGR3DF_cjs.__name(ResponsePanel, "ResponsePanel");
3155
+ function SendButton({ className }) {
3156
+ const { state, sendRequest } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
3157
+ const ep = state.selectedEndpoint;
3158
+ const builder = React12.useMemo(
3159
+ () => ep ? new chunk5Q4UMSWB_cjs.UrlBuilder(ep, state.parameters) : null,
3160
+ [ep, state.parameters]
3161
+ );
3162
+ const missingRequired = builder?.missingRequired() ?? [];
3163
+ const unsubstituted = builder?.unfilledPlaceholders() ?? [];
3164
+ const isJsonValid = state.requestBody ? chunk5Q4UMSWB_cjs.isValidJson(state.requestBody) : true;
3165
+ const blockers = [];
3166
+ if (missingRequired.length > 0) {
3167
+ blockers.push(
3168
+ `Fill required parameter${missingRequired.length > 1 ? "s" : ""}: ${missingRequired.join(", ")}`
3169
+ );
3170
+ } else if (unsubstituted.length > 0) {
3171
+ blockers.push(`URL still has unfilled placeholder${unsubstituted.length > 1 ? "s" : ""}: ${unsubstituted.map((n) => `{${n}}`).join(", ")}`);
3172
+ }
3173
+ if (!isJsonValid) blockers.push("Request body is not valid JSON");
3174
+ const disabled = state.loading || !state.requestUrl || blockers.length > 0;
3175
+ const tooltip = blockers.length > 0 ? blockers.join("\n") : void 0;
3176
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: lib.cn("space-y-2", className), children: [
3177
+ blockers.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 rounded-md border border-amber-500/25 bg-amber-500/[0.06] px-3 py-2 text-[11px] text-amber-600 dark:text-amber-400", children: [
3178
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-3.5 w-3.5 shrink-0 mt-px" }),
3179
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "leading-snug", children: blockers[0] })
3180
+ ] }),
3181
+ /* @__PURE__ */ jsxRuntime.jsx(
3182
+ components.Button,
3183
+ {
3184
+ onClick: sendRequest,
3185
+ disabled,
3186
+ size: "sm",
3187
+ title: tooltip,
3188
+ className: "w-full gap-2 h-9",
3189
+ children: state.loading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3190
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
3191
+ "Sending\u2026"
3192
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3193
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3.5 w-3.5" }),
3194
+ "Send Request"
3195
+ ] })
3196
+ }
3197
+ )
3198
+ ] });
3199
+ }
3200
+ chunkWGEGR3DF_cjs.__name(SendButton, "SendButton");
3201
+ var WIDTH_NARROW = "clamp(380px, 30vw, 480px)";
3202
+ var WIDTH_WIDE = "clamp(720px, 60vw, 1280px)";
3203
+ function SlideInPlayground({ open, onClose }) {
3204
+ const { state } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
3205
+ const ep = state.selectedEndpoint;
3206
+ const showResponse = state.response !== null || state.loading;
3207
+ const width = showResponse ? WIDTH_WIDE : WIDTH_NARROW;
3208
+ return /* @__PURE__ */ jsxRuntime.jsx(components.SidePanel, { open, onOpenChange: (v) => !v && onClose(), side: "right", children: /* @__PURE__ */ jsxRuntime.jsxs(components.SidePanel.Content, { width, className: "max-w-[95vw]", children: [
3209
+ /* @__PURE__ */ jsxRuntime.jsxs(components.SidePanel.Header, { children: [
3210
+ /* @__PURE__ */ jsxRuntime.jsx(components.SidePanel.Title, { children: "Playground" }),
3211
+ ep && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
3212
+ /* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: ep.method }),
3213
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground truncate", children: chunk5Q4UMSWB_cjs.relativePath(ep.path) })
3214
+ ] }),
3215
+ /* @__PURE__ */ jsxRuntime.jsx(components.SidePanel.Close, { className: "ml-auto" })
3216
+ ] }),
3217
+ /* @__PURE__ */ jsxRuntime.jsxs(
3218
+ components.SidePanel.Body,
3219
+ {
3220
+ className: lib.cn(
3221
+ "overflow-hidden grid divide-x transition-[grid-template-columns] duration-250",
3222
+ showResponse ? "grid-cols-[minmax(0,1fr)_minmax(0,1fr)]" : "grid-cols-1"
3223
+ ),
3224
+ children: [
3225
+ /* @__PURE__ */ jsxRuntime.jsxs(Panel, { children: [
3226
+ /* @__PURE__ */ jsxRuntime.jsx(RequestPanel, {}),
3227
+ ep && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-t px-4 py-3 bg-background", children: /* @__PURE__ */ jsxRuntime.jsx(SendButton, {}) })
3228
+ ] }),
3229
+ showResponse && /* @__PURE__ */ jsxRuntime.jsx(Panel, { children: /* @__PURE__ */ jsxRuntime.jsx(ResponsePanel, {}) })
3230
+ ]
3231
+ }
3232
+ )
3233
+ ] }) });
3234
+ }
3235
+ chunkWGEGR3DF_cjs.__name(SlideInPlayground, "SlideInPlayground");
3236
+ function TryItSheet({ open, onOpenChange }) {
3237
+ const { state } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
3238
+ const showResponse = state.response !== null || state.loading;
3239
+ return /* @__PURE__ */ jsxRuntime.jsx(components.ResponsiveSheet, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(components.ResponsiveSheetContent, { className: "sm:max-w-xl flex flex-col h-full p-0", children: [
3240
+ /* @__PURE__ */ jsxRuntime.jsx(components.ResponsiveSheetHeader, { className: "px-4 py-3 border-b shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(components.ResponsiveSheetTitle, { className: "text-sm", children: "Playground" }) }),
3241
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-h-0 flex flex-col divide-y", children: [
3242
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-h-0 flex flex-col", children: [
3243
+ /* @__PURE__ */ jsxRuntime.jsx(RequestPanel, {}),
3244
+ state.selectedEndpoint && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-t px-4 py-3 bg-background", children: /* @__PURE__ */ jsxRuntime.jsx(SendButton, {}) })
3245
+ ] }),
3246
+ showResponse && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx(ResponsePanel, {}) })
3247
+ ] })
3248
+ ] }) });
3249
+ }
3250
+ chunkWGEGR3DF_cjs.__name(TryItSheet, "TryItSheet");
3251
+ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
3252
+ const { state, config, setSelectedEndpoint } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
3253
+ const isDesktop = hooks.useMediaQuery("(min-width: 1024px)");
3254
+ const isMobile = !isDesktop;
3255
+ const grouping = config.schemaGrouping ?? "selector";
3256
+ const preloadAll = grouping === "sections";
3257
+ const urlSyncEnabled = typeof config.urlSync === "boolean" ? config.urlSync : Boolean(config.urlSync?.enabled);
3258
+ const {
3259
+ endpoints,
3260
+ schemaInfo,
3261
+ rawSchema,
3262
+ resolvedBaseUrl,
3263
+ loading,
3264
+ error,
3265
+ schemas,
3266
+ currentSchema,
3267
+ setCurrentSchema,
3268
+ schemasData
3269
+ } = useOpenApiSchema({
3270
+ schemas: config.schemas,
3271
+ defaultSchemaId: config.defaultSchemaId,
3272
+ baseUrl: config.baseUrl,
3273
+ preloadAll
3274
+ });
3275
+ const [activeAnchor, setActiveAnchor] = React12.useState(null);
3276
+ const [activeSchemaId, setActiveSchemaId] = React12.useState(null);
3277
+ const [sheetOpen, setSheetOpen] = React12.useState(false);
3278
+ const docsRef = React12.useRef(null);
3279
+ const slideOpen = !isMobile && state.selectedEndpoint !== null;
3280
+ const endpointsBySchema = React12.useMemo(() => {
3281
+ if (grouping !== "sections") return {};
3282
+ const byId = lodashEs.keyBy(schemasData, (e) => e.source.id);
3283
+ const out = {};
3284
+ for (const src of schemas) out[src.id] = byId[src.id]?.endpoints ?? [];
3285
+ return out;
3286
+ }, [grouping, schemasData, schemas]);
3287
+ const handleTry = React12.useCallback(
3288
+ (ep) => {
3289
+ setSelectedEndpoint(ep);
3290
+ if (isMobile) setSheetOpen(true);
3291
+ },
3292
+ [isMobile, setSelectedEndpoint]
3293
+ );
3294
+ const handleCloseSlide = React12.useCallback(() => {
3295
+ setSelectedEndpoint(null);
3296
+ }, [setSelectedEndpoint]);
3297
+ const handleNavigate = React12.useCallback(
3298
+ (anchor, schemaId) => {
3299
+ if (schemaId && schemaId !== currentSchema?.id && grouping === "selector") {
3300
+ setCurrentSchema(schemaId);
3301
+ requestAnimationFrame(() => {
3302
+ docsRef.current?.scrollToAnchor(anchor);
3303
+ });
3304
+ return;
3305
+ }
3306
+ docsRef.current?.scrollToAnchor(anchor);
3307
+ },
3308
+ [currentSchema?.id, grouping, setCurrentSchema]
3309
+ );
3310
+ const handleActiveChange = React12.useCallback((anchor, schemaId) => {
3311
+ setActiveAnchor(anchor);
3312
+ setActiveSchemaId(schemaId);
3313
+ }, []);
3314
+ const effectiveSchemaId = grouping === "sections" ? activeSchemaId : currentSchema?.id ?? null;
3315
+ const handleHashTarget = React12.useCallback(
3316
+ (target) => {
3317
+ if (!target.schemaId && !target.anchor) return;
3318
+ const matched = target.schemaId ? schemas.find((s) => s.id === target.schemaId || slugifySchemaId(s.id) === target.schemaId) : null;
3319
+ const needsSchemaSwitch = matched && grouping === "selector" && matched.id !== currentSchema?.id;
3320
+ if (needsSchemaSwitch) {
3321
+ setCurrentSchema(matched.id);
3322
+ }
3323
+ if (target.anchor) {
3324
+ const anchor = target.anchor;
3325
+ if (needsSchemaSwitch) {
3326
+ requestAnimationFrame(() => {
3327
+ docsRef.current?.scrollToAnchor(anchor);
3328
+ });
3329
+ } else {
3330
+ docsRef.current?.scrollToAnchor(anchor);
3331
+ }
3332
+ }
3333
+ },
3334
+ [schemas, grouping, currentSchema?.id, setCurrentSchema]
3335
+ );
3336
+ useDocsUrlSync({
3337
+ enabled: urlSyncEnabled,
3338
+ currentSchemaId: effectiveSchemaId,
3339
+ activeAnchor,
3340
+ onHashTarget: handleHashTarget
3341
+ });
3342
+ if (loading) {
3343
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[260px_1fr] items-start", children: [
3344
+ /* @__PURE__ */ jsxRuntime.jsx(
3345
+ "div",
3346
+ {
3347
+ className: "sticky top-[var(--navbar-height,64px)] border-r p-3 space-y-1.5 overflow-y-auto",
3348
+ style: { height: "calc(100dvh - var(--navbar-height, 64px))" },
3349
+ children: Array.from({ length: 12 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-8 w-full rounded" }, i))
3350
+ }
3351
+ ),
3352
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-8 space-y-4", children: [
3353
+ /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-8 w-1/2" }),
3354
+ /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-4 w-full" }),
3355
+ /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-4 w-3/4" }),
3356
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 space-y-6", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
3357
+ /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-6 w-1/3" }),
3358
+ /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-20 w-full" })
3359
+ ] }, i)) })
3360
+ ] })
3361
+ ] });
3362
+ }
3363
+ if (error) {
3364
+ return /* @__PURE__ */ jsxRuntime.jsx(
3365
+ "div",
3366
+ {
3367
+ className: "flex items-center justify-center p-8",
3368
+ style: { height: "calc(100dvh - var(--navbar-height, 64px))" },
3369
+ children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-destructive", children: [
3370
+ "Failed to load schema: ",
3371
+ error
3372
+ ] })
3373
+ }
3374
+ );
3375
+ }
3376
+ if (isMobile) {
3377
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
3378
+ /* @__PURE__ */ jsxRuntime.jsx(EndpointDraftSync, { schemaId: currentSchema?.id ?? null }),
3379
+ grouping === "sections" ? /* @__PURE__ */ jsxRuntime.jsx(
3380
+ DocsView,
3381
+ {
3382
+ ref: docsRef,
3383
+ grouping: "sections",
3384
+ schemasData,
3385
+ selectedVersion: state.selectedVersion,
3386
+ loadedEndpoint: state.selectedEndpoint,
3387
+ onTryEndpoint: handleTry,
3388
+ onActiveChange: handleActiveChange
3389
+ }
3390
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
3391
+ DocsView,
3392
+ {
3393
+ ref: docsRef,
3394
+ info: schemaInfo,
3395
+ rawSchema,
3396
+ resolvedBaseUrl,
3397
+ endpoints,
3398
+ selectedVersion: state.selectedVersion,
3399
+ loadedEndpoint: state.selectedEndpoint,
3400
+ onTryEndpoint: handleTry,
3401
+ onActiveChange: handleActiveChange
3402
+ }
3403
+ ),
3404
+ /* @__PURE__ */ jsxRuntime.jsx(TryItSheet, { open: sheetOpen, onOpenChange: setSheetOpen })
3405
+ ] });
3406
+ }
3407
+ return /* @__PURE__ */ jsxRuntime.jsx(components.TooltipProvider, { delayDuration: 350, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[260px_minmax(0,1fr)] items-start", children: [
3408
+ /* @__PURE__ */ jsxRuntime.jsx(EndpointDraftSync, { schemaId: currentSchema?.id ?? null }),
3409
+ /* @__PURE__ */ jsxRuntime.jsx(
3410
+ "div",
3411
+ {
3412
+ className: "sticky top-[var(--navbar-height,64px)]",
3413
+ style: { height: "calc(100dvh - var(--navbar-height, 64px))" },
3414
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3415
+ DocsSidebar,
3416
+ {
3417
+ info: schemaInfo,
3418
+ endpoints,
3419
+ schemas,
3420
+ currentSchemaId: currentSchema?.id ?? null,
3421
+ onSchemaChange: setCurrentSchema,
3422
+ activeEndpointId: activeAnchor,
3423
+ selectedVersion: state.selectedVersion,
3424
+ onNavigate: handleNavigate,
3425
+ grouping,
3426
+ endpointsBySchema,
3427
+ rawSchema,
3428
+ resolvedBaseUrl
3429
+ }
3430
+ )
3431
+ }
3432
+ ),
3433
+ grouping === "sections" ? /* @__PURE__ */ jsxRuntime.jsx(
3434
+ DocsView,
3435
+ {
3436
+ ref: docsRef,
3437
+ grouping: "sections",
3438
+ schemasData,
3439
+ selectedVersion: state.selectedVersion,
3440
+ loadedEndpoint: state.selectedEndpoint,
3441
+ onTryEndpoint: handleTry,
3442
+ onActiveChange: handleActiveChange
3443
+ }
3444
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
3445
+ DocsView,
3446
+ {
3447
+ ref: docsRef,
3448
+ info: schemaInfo,
3449
+ rawSchema,
3450
+ resolvedBaseUrl,
3451
+ endpoints,
3452
+ selectedVersion: state.selectedVersion,
3453
+ loadedEndpoint: state.selectedEndpoint,
3454
+ onTryEndpoint: handleTry,
3455
+ onActiveChange: handleActiveChange
3456
+ }
3457
+ ),
3458
+ /* @__PURE__ */ jsxRuntime.jsx(SlideInPlayground, { open: slideOpen, onClose: handleCloseSlide })
3459
+ ] }) });
3460
+ }, "DocsLayout");
3461
+
3462
+ exports.DocsLayout = DocsLayout;
3463
+ //# sourceMappingURL=DocsLayout-IKH7BLSU.cjs.map
3464
+ //# sourceMappingURL=DocsLayout-IKH7BLSU.cjs.map