@djangocfg/ui-tools 2.1.289 → 2.1.291

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 (98) hide show
  1. package/README.md +14 -3
  2. package/dist/{DocsLayout-YDR7DSMM.cjs → DocsLayout-IKH7BLSU.cjs} +1537 -682
  3. package/dist/DocsLayout-IKH7BLSU.cjs.map +1 -0
  4. package/dist/{DocsLayout-TKJQ5W5E.mjs → DocsLayout-JPXFUKAR.mjs} +1429 -574
  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 +18 -10
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +35 -1
  17. package/dist/index.d.ts +35 -1
  18. package/dist/index.mjs +13 -5
  19. package/dist/index.mjs.map +1 -1
  20. package/package.json +20 -15
  21. package/src/components/markdown/MarkdownMessage.tsx +46 -0
  22. package/src/tools/MarkdownEditor/MarkdownEditor.tsx +42 -1
  23. package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +87 -178
  24. package/src/tools/OpenapiViewer/README.md +114 -6
  25. package/src/tools/OpenapiViewer/components/DocsLayout/ApiIntroSection.tsx +20 -6
  26. package/src/tools/OpenapiViewer/components/DocsLayout/DocsView.tsx +6 -0
  27. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/CodeSamples/LanguageTabs.tsx +36 -0
  28. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/CodeSamples/index.tsx +56 -0
  29. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/CodeSamples/useCodeSnippet.ts +77 -0
  30. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/MetaActions.tsx +146 -0
  31. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/MethodBadge.tsx +6 -0
  32. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/PathDisplay.tsx +26 -0
  33. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Header/index.tsx +87 -0
  34. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Parameters/ParamGroup.tsx +30 -0
  35. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Parameters/ParamRow.tsx +36 -0
  36. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Parameters/index.tsx +22 -0
  37. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/RequestBody/index.tsx +33 -0
  38. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/ResponseBody.tsx +76 -0
  39. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/ResponseRow.tsx +80 -0
  40. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/StatusTag.tsx +32 -0
  41. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Responses/index.tsx +21 -0
  42. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/FieldRow.tsx +106 -0
  43. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/buildTree.ts +127 -0
  44. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/index.tsx +31 -0
  45. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/SchemaFields/types.ts +28 -0
  46. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/SectionHeader.tsx +87 -0
  47. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/defaults.ts +27 -0
  48. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/Section/index.tsx +45 -0
  49. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/context.tsx +56 -0
  50. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/hooks/useSectionHash.ts +63 -0
  51. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/index.tsx +96 -0
  52. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/store/index.ts +133 -0
  53. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/store/selectors.ts +40 -0
  54. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc/types.ts +17 -0
  55. package/src/tools/OpenapiViewer/components/DocsLayout/SchemaCopyMenu.tsx +8 -2
  56. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/BrandHeader.tsx +48 -0
  57. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/CategoryBlock.tsx +33 -0
  58. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/EndpointRow.tsx +73 -0
  59. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/MethodChips.tsx +43 -0
  60. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/SchemaSection.tsx +27 -0
  61. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/SearchInput.tsx +45 -0
  62. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/SidebarBody.tsx +50 -0
  63. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/Toolbar.tsx +64 -0
  64. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/buildVM.ts +126 -0
  65. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/index.tsx +112 -0
  66. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/types.ts +42 -0
  67. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar/useDebouncedValue.ts +14 -0
  68. package/src/tools/OpenapiViewer/components/DocsLayout/SlideInPlayground.tsx +10 -7
  69. package/src/tools/OpenapiViewer/components/DocsLayout/TryItSheet.tsx +9 -6
  70. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/PrettyView.tsx +55 -0
  71. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/PreviewView.tsx +115 -0
  72. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/RawView.tsx +24 -0
  73. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/StatusBar.tsx +63 -0
  74. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/ViewTabs.tsx +45 -0
  75. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/detectContent.ts +97 -0
  76. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/index.tsx +93 -0
  77. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/types.ts +26 -0
  78. package/src/tools/OpenapiViewer/components/shared/ResponsePanel/useResponseView.ts +62 -0
  79. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +41 -71
  80. package/src/tools/OpenapiViewer/types.ts +10 -0
  81. package/src/tools/OpenapiViewer/utils/codeSamples.ts +287 -0
  82. package/src/tools/OpenapiViewer/utils/index.ts +3 -0
  83. package/src/tools/OpenapiViewer/utils/operationToHar.ts +119 -0
  84. package/src/tools/OpenapiViewer/utils/sampler.ts +72 -0
  85. package/src/tools/PrettyCode/PrettyCode.client.tsx +88 -1
  86. package/src/tools/PrettyCode/PrettyCode.story.tsx +114 -361
  87. package/src/tools/PrettyCode/index.tsx +13 -0
  88. package/src/tools/PrettyCode/lazy.tsx +5 -0
  89. package/src/tools/PrettyCode/registerPrismLanguages.ts +111 -0
  90. package/dist/DocsLayout-TKJQ5W5E.mjs.map +0 -1
  91. package/dist/DocsLayout-YDR7DSMM.cjs.map +0 -1
  92. package/dist/PrettyCode.client-5GABIN2I.cjs.map +0 -1
  93. package/dist/PrettyCode.client-IZTXXYHG.mjs.map +0 -1
  94. package/dist/chunk-IULI4XII.cjs.map +0 -1
  95. package/dist/chunk-VZGQC3NG.mjs.map +0 -1
  96. package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc.tsx +0 -273
  97. package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar.tsx +0 -439
  98. package/src/tools/OpenapiViewer/components/shared/ResponsePanel.tsx +0 -127
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkIULI4XII_cjs = require('./chunk-IULI4XII.cjs');
3
+ var chunk5Q4UMSWB_cjs = require('./chunk-5Q4UMSWB.cjs');
4
4
  var chunk33AMWFBZ_cjs = require('./chunk-33AMWFBZ.cjs');
5
5
  require('./chunk-2SMCH62O.cjs');
6
6
  var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
7
- var React6 = require('react');
7
+ var React12 = require('react');
8
8
  var lodashEs = require('lodash-es');
9
9
  var components = require('@djangocfg/ui-core/components');
10
10
  var hooks = require('@djangocfg/ui-core/hooks');
@@ -12,54 +12,16 @@ var consola = require('consola');
12
12
  var lucideReact = require('lucide-react');
13
13
  var lib = require('@djangocfg/ui-core/lib');
14
14
  var jsxRuntime = require('react/jsx-runtime');
15
+ var zustand = require('zustand');
16
+ var middleware = require('zustand/middleware');
15
17
 
16
18
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
19
 
18
- var React6__default = /*#__PURE__*/_interopDefault(React6);
20
+ var React12__default = /*#__PURE__*/_interopDefault(React12);
19
21
  var consola__default = /*#__PURE__*/_interopDefault(consola);
20
22
 
21
- function exampleFromSchema(schema, depth = 0) {
22
- if (!schema || depth > 8) return null;
23
- if (schema.example !== void 0) return schema.example;
24
- if (schema.default !== void 0) return schema.default;
25
- if (Array.isArray(schema.enum) && schema.enum.length > 0) return schema.enum[0];
26
- switch (schema.type) {
27
- case "object": {
28
- const out = {};
29
- const props = schema.properties ?? {};
30
- for (const [k, v] of Object.entries(props)) {
31
- out[k] = exampleFromSchema(v, depth + 1);
32
- }
33
- return out;
34
- }
35
- case "array":
36
- return [exampleFromSchema(schema.items, depth + 1)];
37
- case "integer":
38
- case "number":
39
- return 0;
40
- case "boolean":
41
- return false;
42
- case "string":
43
- if (schema.format === "date-time") return (/* @__PURE__ */ new Date()).toISOString();
44
- if (schema.format === "date") return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
45
- if (schema.format === "email") return "user@example.com";
46
- if (schema.format === "uri" || schema.format === "url") return "https://example.com";
47
- if (schema.format === "uuid") return "00000000-0000-0000-0000-000000000000";
48
- return "";
49
- default:
50
- if (schema.properties) {
51
- const out = {};
52
- for (const [k, v] of Object.entries(schema.properties)) {
53
- out[k] = exampleFromSchema(v, depth + 1);
54
- }
55
- return out;
56
- }
57
- return null;
58
- }
59
- }
60
- chunkWGEGR3DF_cjs.__name(exampleFromSchema, "exampleFromSchema");
61
23
  var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
62
- var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl, schemaId) => {
24
+ var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl, schemaId, specRoot) => {
63
25
  const endpoints = [];
64
26
  if (!schema.paths) return [];
65
27
  for (const [path, methods] of Object.entries(schema.paths)) {
@@ -83,9 +45,17 @@ var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl
83
45
  const responses = [];
84
46
  if (op.responses) {
85
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;
86
53
  responses.push({
87
54
  code,
88
- description: response.description || `Response ${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
89
59
  });
90
60
  }
91
61
  }
@@ -98,13 +68,13 @@ var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl
98
68
  type: rawSchema?.type || "object",
99
69
  description: op.requestBody.description,
100
70
  schema: rawSchema,
101
- example: rawSchema ? JSON.stringify(exampleFromSchema(rawSchema), null, 2) : void 0
71
+ example: rawSchema ? chunk5Q4UMSWB_cjs.sampleSchemaJson(rawSchema, { skipReadOnly: true }, specRoot) : void 0
102
72
  };
103
73
  }
104
74
  const endpoint = {
105
75
  name: path.split("/").pop() || path,
106
76
  method: methodUpper,
107
- path: baseUrl ? chunkIULI4XII_cjs.joinUrl(baseUrl, path) : path,
77
+ path: baseUrl ? chunk5Q4UMSWB_cjs.joinUrl(baseUrl, path) : path,
108
78
  summary,
109
79
  description,
110
80
  category,
@@ -140,41 +110,41 @@ function useOpenApiSchema({
140
110
  baseUrl: configBaseUrl,
141
111
  preloadAll = false
142
112
  }) {
143
- const [loading, setLoading] = React6.useState(true);
144
- const [error, setError] = React6.useState(null);
145
- const [currentSchemaId, setCurrentSchemaId] = React6.useState(
113
+ const [loading, setLoading] = React12.useState(true);
114
+ const [error, setError] = React12.useState(null);
115
+ const [currentSchemaId, setCurrentSchemaId] = React12.useState(
146
116
  defaultSchemaId || schemas[0]?.id
147
117
  );
148
- const [loadedSchemas, setLoadedSchemas] = React6.useState(
118
+ const [loadedSchemas, setLoadedSchemas] = React12.useState(
149
119
  /* @__PURE__ */ new Map()
150
120
  );
151
- const [loadStates, setLoadStates] = React6.useState(/* @__PURE__ */ new Map());
152
- const currentSchema = React6.useMemo(
121
+ const [loadStates, setLoadStates] = React12.useState(/* @__PURE__ */ new Map());
122
+ const currentSchema = React12.useMemo(
153
123
  () => schemas.find((s) => s.id === currentSchemaId) || null,
154
124
  [schemas, currentSchemaId]
155
125
  );
156
- const currentOpenApiSchema = React6.useMemo(
126
+ const currentOpenApiSchema = React12.useMemo(
157
127
  () => currentSchemaId ? loadedSchemas.get(currentSchemaId) : null,
158
128
  [loadedSchemas, currentSchemaId]
159
129
  );
160
- const dereferencedSchema = React6.useMemo(
161
- () => currentOpenApiSchema ? chunkIULI4XII_cjs.dereferenceSchema(currentOpenApiSchema) : null,
130
+ const dereferencedSchema = React12.useMemo(
131
+ () => currentOpenApiSchema ? chunk5Q4UMSWB_cjs.dereferenceSchema(currentOpenApiSchema) : null,
162
132
  [currentOpenApiSchema]
163
133
  );
164
- const resolvedBaseUrl = React6.useMemo(
165
- () => chunkIULI4XII_cjs.resolveBaseUrl({
134
+ const resolvedBaseUrl = React12.useMemo(
135
+ () => chunk5Q4UMSWB_cjs.resolveBaseUrl({
166
136
  schemaSource: currentSchema?.baseUrl,
167
137
  config: configBaseUrl,
168
138
  fromServers: currentOpenApiSchema?.servers?.[0]?.url
169
139
  }),
170
140
  [currentSchema?.baseUrl, configBaseUrl, currentOpenApiSchema]
171
141
  );
172
- const endpoints = React6.useMemo(
173
- () => dereferencedSchema ? extractEndpoints(dereferencedSchema, resolvedBaseUrl, currentSchemaId) : [],
174
- [dereferencedSchema, resolvedBaseUrl, currentSchemaId]
142
+ const endpoints = React12.useMemo(
143
+ () => dereferencedSchema ? extractEndpoints(dereferencedSchema, resolvedBaseUrl, currentSchemaId, currentOpenApiSchema ?? void 0) : [],
144
+ [dereferencedSchema, resolvedBaseUrl, currentSchemaId, currentOpenApiSchema]
175
145
  );
176
- const categories = React6.useMemo(() => getCategories(endpoints), [endpoints]);
177
- const schemaInfo = React6.useMemo(() => {
146
+ const categories = React12.useMemo(() => getCategories(endpoints), [endpoints]);
147
+ const schemaInfo = React12.useMemo(() => {
178
148
  if (!currentOpenApiSchema?.info) return null;
179
149
  const { title, version, description } = currentOpenApiSchema.info;
180
150
  return {
@@ -184,7 +154,7 @@ function useOpenApiSchema({
184
154
  servers: currentOpenApiSchema.servers
185
155
  };
186
156
  }, [currentOpenApiSchema]);
187
- React6.useEffect(() => {
157
+ React12.useEffect(() => {
188
158
  if (preloadAll) return;
189
159
  if (!currentSchema) return;
190
160
  if (loadedSchemas.has(currentSchema.id)) {
@@ -203,7 +173,7 @@ function useOpenApiSchema({
203
173
  setLoading(false);
204
174
  });
205
175
  }, [currentSchema, loadedSchemas, preloadAll]);
206
- React6.useEffect(() => {
176
+ React12.useEffect(() => {
207
177
  if (!preloadAll) return;
208
178
  if (schemas.length === 0) {
209
179
  setLoading(false);
@@ -257,12 +227,12 @@ function useOpenApiSchema({
257
227
  cancelled = true;
258
228
  };
259
229
  }, [preloadAll, schemas, loadedSchemas]);
260
- const schemasData = React6.useMemo(() => {
230
+ const schemasData = React12.useMemo(() => {
261
231
  if (!preloadAll) return [];
262
232
  return schemas.map((src) => {
263
233
  const raw = loadedSchemas.get(src.id) ?? null;
264
- const deref = raw ? chunkIULI4XII_cjs.dereferenceSchema(raw) : null;
265
- const resolved = chunkIULI4XII_cjs.resolveBaseUrl({
234
+ const deref = raw ? chunk5Q4UMSWB_cjs.dereferenceSchema(raw) : null;
235
+ const resolved = chunk5Q4UMSWB_cjs.resolveBaseUrl({
266
236
  schemaSource: src.baseUrl,
267
237
  config: configBaseUrl,
268
238
  fromServers: raw?.servers?.[0]?.url
@@ -273,7 +243,7 @@ function useOpenApiSchema({
273
243
  description: raw.info.description,
274
244
  servers: raw.servers
275
245
  } : null;
276
- const eps = deref ? extractEndpoints(deref, resolved, src.id) : [];
246
+ const eps = deref ? extractEndpoints(deref, resolved, src.id, raw ?? void 0) : [];
277
247
  const state = loadStates.get(src.id) ?? { loading: !raw, error: null };
278
248
  return {
279
249
  source: src,
@@ -286,10 +256,10 @@ function useOpenApiSchema({
286
256
  };
287
257
  });
288
258
  }, [preloadAll, schemas, loadedSchemas, loadStates, configBaseUrl]);
289
- const setCurrentSchema = React6.useCallback((schemaId) => {
259
+ const setCurrentSchema = React12.useCallback((schemaId) => {
290
260
  setCurrentSchemaId(schemaId);
291
261
  }, []);
292
- const refresh = React6.useCallback(() => {
262
+ const refresh = React12.useCallback(() => {
293
263
  if (!currentSchema) return;
294
264
  setLoading(true);
295
265
  setError(null);
@@ -351,12 +321,12 @@ function useDocsUrlSync({
351
321
  activeAnchor,
352
322
  onHashTarget
353
323
  }) {
354
- const primedRef = React6.useRef(false);
355
- const onHashTargetRef = React6.useRef(onHashTarget);
356
- React6.useEffect(() => {
324
+ const primedRef = React12.useRef(false);
325
+ const onHashTargetRef = React12.useRef(onHashTarget);
326
+ React12.useEffect(() => {
357
327
  onHashTargetRef.current = onHashTarget;
358
328
  }, [onHashTarget]);
359
- React6.useEffect(() => {
329
+ React12.useEffect(() => {
360
330
  if (!enabled || typeof window === "undefined") return;
361
331
  const apply = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
362
332
  onHashTargetRef.current(parseDocsHash(window.location.hash));
@@ -370,7 +340,7 @@ function useDocsUrlSync({
370
340
  window.removeEventListener("popstate", apply);
371
341
  };
372
342
  }, [enabled]);
373
- React6.useEffect(() => {
343
+ React12.useEffect(() => {
374
344
  if (!enabled || typeof window === "undefined") return;
375
345
  if (!primedRef.current) return;
376
346
  const next = buildDocsHash(currentSchemaId, activeAnchor);
@@ -379,7 +349,7 @@ function useDocsUrlSync({
379
349
  const url = next ? `${window.location.pathname}${window.location.search}${next}` : `${window.location.pathname}${window.location.search}`;
380
350
  window.history.replaceState(window.history.state, "", url);
381
351
  }, [enabled, currentSchemaId, activeAnchor]);
382
- const pushTarget = React6.useCallback(
352
+ const pushTarget = React12.useCallback(
383
353
  (schemaId, anchor) => {
384
354
  if (!enabled || typeof window === "undefined") return;
385
355
  const next = buildDocsHash(schemaId, anchor);
@@ -426,22 +396,22 @@ function writeDraft(key, value) {
426
396
  chunkWGEGR3DF_cjs.__name(writeDraft, "writeDraft");
427
397
  function useEndpointDraft(schemaId, endpoint) {
428
398
  const key = storageKey(schemaId, endpoint);
429
- const [draft, setDraftSnapshot] = React6.useState(() => readDraft(key));
430
- const loadedKeyRef = React6.useRef(key);
431
- React6.useEffect(() => {
399
+ const [draft, setDraftSnapshot] = React12.useState(() => readDraft(key));
400
+ const loadedKeyRef = React12.useRef(key);
401
+ React12.useEffect(() => {
432
402
  if (loadedKeyRef.current === key) return;
433
403
  loadedKeyRef.current = key;
434
404
  setDraftSnapshot(readDraft(key));
435
405
  }, [key]);
436
- const keyRef = React6.useRef(key);
437
- React6.useEffect(() => {
406
+ const keyRef = React12.useRef(key);
407
+ React12.useEffect(() => {
438
408
  keyRef.current = key;
439
409
  }, [key]);
440
- const latestRef = React6.useRef(draft);
441
- React6.useEffect(() => {
410
+ const latestRef = React12.useRef(draft);
411
+ React12.useEffect(() => {
442
412
  latestRef.current = draft;
443
413
  }, [draft]);
444
- const setParameters = React6.useCallback((params) => {
414
+ const setParameters = React12.useCallback((params) => {
445
415
  const next = {
446
416
  parameters: params,
447
417
  requestBody: latestRef.current.requestBody
@@ -449,7 +419,7 @@ function useEndpointDraft(schemaId, endpoint) {
449
419
  latestRef.current = next;
450
420
  writeDraft(keyRef.current, next);
451
421
  }, []);
452
- const setRequestBody = React6.useCallback((body) => {
422
+ const setRequestBody = React12.useCallback((body) => {
453
423
  const next = {
454
424
  parameters: latestRef.current.parameters,
455
425
  requestBody: body
@@ -457,7 +427,7 @@ function useEndpointDraft(schemaId, endpoint) {
457
427
  latestRef.current = next;
458
428
  writeDraft(keyRef.current, next);
459
429
  }, []);
460
- const reset = React6.useCallback(() => {
430
+ const reset = React12.useCallback(() => {
461
431
  latestRef.current = EMPTY_DRAFT;
462
432
  if (keyRef.current && typeof window !== "undefined") {
463
433
  try {
@@ -473,17 +443,17 @@ chunkWGEGR3DF_cjs.__name(useEndpointDraft, "useEndpointDraft");
473
443
 
474
444
  // src/tools/OpenapiViewer/components/shared/EndpointDraftSync.tsx
475
445
  function EndpointDraftSync({ schemaId }) {
476
- const { state, setParameters, setRequestBody, setActiveSchemaId } = chunkIULI4XII_cjs.usePlaygroundContext();
446
+ const { state, setParameters, setRequestBody, setActiveSchemaId } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
477
447
  const ep = state.selectedEndpoint;
478
- React6.useEffect(() => {
448
+ React12.useEffect(() => {
479
449
  setActiveSchemaId(schemaId);
480
450
  }, [schemaId, setActiveSchemaId]);
481
451
  const { draft, setParameters: persistParams, setRequestBody: persistBody } = useEndpointDraft(schemaId, ep);
482
- const lastLoadedKeyRef = React6.useRef(null);
483
- const lastPersistedParamsRef = React6.useRef("");
484
- const lastPersistedBodyRef = React6.useRef("");
452
+ const lastLoadedKeyRef = React12.useRef(null);
453
+ const lastPersistedParamsRef = React12.useRef("");
454
+ const lastPersistedBodyRef = React12.useRef("");
485
455
  const currentKey = ep ? `${ep.method}|${ep.path}` : null;
486
- React6.useEffect(() => {
456
+ React12.useEffect(() => {
487
457
  if (!ep || !currentKey) {
488
458
  lastLoadedKeyRef.current = null;
489
459
  return;
@@ -505,14 +475,14 @@ function EndpointDraftSync({ schemaId }) {
505
475
  lastPersistedBodyRef.current = state.requestBody;
506
476
  }
507
477
  }, [currentKey]);
508
- React6.useEffect(() => {
478
+ React12.useEffect(() => {
509
479
  if (!ep || lastLoadedKeyRef.current !== currentKey) return;
510
480
  const serialised = JSON.stringify(state.parameters);
511
481
  if (serialised === lastPersistedParamsRef.current) return;
512
482
  lastPersistedParamsRef.current = serialised;
513
483
  persistParams(state.parameters);
514
484
  }, [state.parameters, ep, currentKey, persistParams]);
515
- React6.useEffect(() => {
485
+ React12.useEffect(() => {
516
486
  if (!ep || lastLoadedKeyRef.current !== currentKey) return;
517
487
  if (state.requestBody === lastPersistedBodyRef.current) return;
518
488
  lastPersistedBodyRef.current = state.requestBody;
@@ -606,7 +576,7 @@ function CollapsibleSection({
606
576
  children,
607
577
  defaultOpen = false
608
578
  }) {
609
- const [open, setOpen] = React6__default.default.useState(defaultOpen);
579
+ const [open, setOpen] = React12__default.default.useState(defaultOpen);
610
580
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0", children: [
611
581
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
612
582
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -627,6 +597,145 @@ function CollapsibleSection({
627
597
  ] });
628
598
  }
629
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");
630
739
 
631
740
  // src/tools/OpenapiViewer/components/DocsLayout/sidebarLabel.ts
632
741
  function longestCommonPrefix(paths) {
@@ -696,106 +805,8 @@ function buildSchemaSections(sources, endpointsBySchema) {
696
805
  }));
697
806
  }
698
807
  chunkWGEGR3DF_cjs.__name(buildSchemaSections, "buildSchemaSections");
699
- var FLAVOUR_LABELS = {
700
- markdown: {
701
- title: "Markdown for LLM",
702
- hint: "Endpoints + params as prose. Smallest."
703
- },
704
- compact: {
705
- title: "Compact JSON",
706
- hint: "Dereferenced, no examples, minified."
707
- },
708
- raw: {
709
- title: "Raw JSON",
710
- hint: "Full OpenAPI document with $refs."
711
- }
712
- };
713
- function SchemaCopyMenu({ schema, endpoints, baseUrl, variant = "button" }) {
714
- const [sizeCache, setSizeCache] = React6.useState({});
715
- const [justCopied, setJustCopied] = React6.useState(null);
716
- const [open, setOpen] = React6.useState(false);
717
- const isReady = schema !== null && endpoints.length > 0;
718
- const build = React6.useCallback(
719
- (flavour) => {
720
- if (!schema) return "";
721
- if (flavour === "markdown") return chunkIULI4XII_cjs.toMarkdown(schema, endpoints, baseUrl);
722
- if (flavour === "compact") return chunkIULI4XII_cjs.toCompactJson(schema, baseUrl);
723
- return chunkIULI4XII_cjs.toRawJson(schema, baseUrl);
724
- },
725
- [schema, endpoints, baseUrl]
726
- );
727
- const handleCopy = React6.useCallback(
728
- async (flavour) => {
729
- if (!isReady) return;
730
- const text = build(flavour);
731
- const label = FLAVOUR_LABELS[flavour].title;
732
- try {
733
- await navigator.clipboard.writeText(text);
734
- const size = chunkIULI4XII_cjs.formatBytes(text);
735
- setSizeCache((prev) => ({ ...prev, [flavour]: size }));
736
- setJustCopied(flavour);
737
- setTimeout(() => setJustCopied(null), 1500);
738
- setOpen(false);
739
- hooks.toast.success(`Copied ${label}`, { description: size });
740
- } catch (err) {
741
- const message = err instanceof Error ? err.message : "Clipboard permission denied";
742
- hooks.toast.error("Copy failed", { description: message });
743
- }
744
- },
745
- [build, isReady]
746
- );
747
- const flavours = React6.useMemo(() => ["markdown", "compact", "raw"], []);
748
- return /* @__PURE__ */ jsxRuntime.jsxs(components.DropdownMenu, { open, onOpenChange: setOpen, children: [
749
- /* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuTrigger, { asChild: true, children: variant === "icon" ? /* @__PURE__ */ jsxRuntime.jsx(
750
- components.Button,
751
- {
752
- variant: "ghost",
753
- size: "icon",
754
- className: "h-7 w-7 shrink-0",
755
- disabled: !isReady,
756
- title: "Copy schema for AI",
757
- "aria-label": "Copy schema for AI",
758
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" })
759
- }
760
- ) : /* @__PURE__ */ jsxRuntime.jsxs(components.Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5 text-xs", disabled: !isReady, children: [
761
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3 w-3" }),
762
- "Copy for AI",
763
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3 w-3 opacity-60" })
764
- ] }) }),
765
- /* @__PURE__ */ jsxRuntime.jsxs(components.DropdownMenuContent, { align: "end", className: "w-72", children: [
766
- /* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuLabel, { className: "text-[10px] uppercase tracking-wider text-muted-foreground/70", children: "Copy schema" }),
767
- /* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuSeparator, {}),
768
- flavours.map((f) => {
769
- const label = FLAVOUR_LABELS[f];
770
- const size = sizeCache[f];
771
- const isDone = justCopied === f;
772
- return /* @__PURE__ */ jsxRuntime.jsxs(
773
- components.DropdownMenuItem,
774
- {
775
- onClick: (e) => {
776
- e.preventDefault();
777
- void handleCopy(f);
778
- },
779
- className: "flex flex-col items-start gap-0.5 py-2 cursor-pointer",
780
- children: [
781
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2", children: [
782
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium flex-1", children: label.title }),
783
- isDone ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 text-[10px] text-emerald-500", children: [
784
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" }),
785
- " Copied"
786
- ] }) : size ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-mono text-muted-foreground/70 tabular-nums", children: size }) : null
787
- ] }),
788
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/70 leading-snug", children: label.hint })
789
- ]
790
- },
791
- f
792
- );
793
- })
794
- ] })
795
- ] });
796
- }
797
- chunkWGEGR3DF_cjs.__name(SchemaCopyMenu, "SchemaCopyMenu");
798
- var METHOD_FILTERS = ["ALL", "GET", "POST", "PUT", "PATCH", "DELETE"];
808
+
809
+ // src/tools/OpenapiViewer/components/DocsLayout/Sidebar/buildVM.ts
799
810
  function filterEndpoints(list, query, method) {
800
811
  let out = list;
801
812
  if (method !== "ALL") {
@@ -831,14 +842,19 @@ function buildCategory(group, activeEndpointId, schemaId, keyPrefix) {
831
842
  };
832
843
  }
833
844
  chunkWGEGR3DF_cjs.__name(buildCategory, "buildCategory");
834
- var emptyTextFor = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((query, method, defaultText) => {
845
+ function emptyTextFor(query, method, defaultText) {
835
846
  if (query && method !== "ALL") return `No ${method} endpoints match "${query}"`;
836
847
  if (query) return `No endpoints match "${query}"`;
837
848
  if (method !== "ALL") return `No ${method} endpoints`;
838
849
  return defaultText;
839
- }, "emptyTextFor");
850
+ }
851
+ chunkWGEGR3DF_cjs.__name(emptyTextFor, "emptyTextFor");
840
852
  function buildFlatVM(endpoints, selectedVersion, query, method, activeEndpointId) {
841
- const filtered = filterEndpoints(chunkIULI4XII_cjs.deduplicateEndpoints(endpoints, selectedVersion), query, method);
853
+ const filtered = filterEndpoints(
854
+ chunk5Q4UMSWB_cjs.deduplicateEndpoints(endpoints, selectedVersion),
855
+ query,
856
+ method
857
+ );
842
858
  const groups = groupEndpoints(filtered);
843
859
  return {
844
860
  kind: "flat",
@@ -851,13 +867,19 @@ function buildSectionsVM(schemas, endpointsBySchema, selectedVersion, query, met
851
867
  const filteredMap = {};
852
868
  for (const src of schemas) {
853
869
  const raw = endpointsBySchema[src.id] ?? [];
854
- filteredMap[src.id] = filterEndpoints(chunkIULI4XII_cjs.deduplicateEndpoints(raw, selectedVersion), query, method);
870
+ filteredMap[src.id] = filterEndpoints(
871
+ chunk5Q4UMSWB_cjs.deduplicateEndpoints(raw, selectedVersion),
872
+ query,
873
+ method
874
+ );
855
875
  }
856
876
  const rawSections = buildSchemaSections(schemas, filteredMap);
857
877
  const sections = rawSections.filter((s) => s.groups.length > 0).map((s) => ({
858
878
  sourceId: s.source.id,
859
879
  sourceName: s.source.name,
860
- categories: s.groups.map((g) => buildCategory(g, activeEndpointId, s.source.id, `${s.source.id}-`))
880
+ categories: s.groups.map(
881
+ (g) => buildCategory(g, activeEndpointId, s.source.id, `${s.source.id}-`)
882
+ )
861
883
  }));
862
884
  return {
863
885
  kind: "sections",
@@ -866,189 +888,237 @@ function buildSectionsVM(schemas, endpointsBySchema, selectedVersion, query, met
866
888
  };
867
889
  }
868
890
  chunkWGEGR3DF_cjs.__name(buildSectionsVM, "buildSectionsVM");
869
- function DocsSidebar({
870
- info,
871
- endpoints,
872
- schemas,
873
- currentSchemaId,
874
- onSchemaChange,
875
- activeEndpointId,
876
- selectedVersion,
877
- onNavigate,
878
- grouping = "selector",
879
- endpointsBySchema,
880
- rawSchema,
881
- resolvedBaseUrl
882
- }) {
883
- const [search, setSearch] = React6.useState("");
884
- const [debounced, setDebounced] = React6.useState("");
885
- const [methodFilter, setMethodFilter] = React6.useState("ALL");
886
- React6.useEffect(() => {
887
- const id = setTimeout(() => setDebounced(search), 120);
888
- return () => clearTimeout(id);
889
- }, [search]);
890
- const body = React6.useMemo(() => {
891
- if (grouping === "sections") {
892
- return buildSectionsVM(
893
- schemas,
894
- endpointsBySchema ?? {},
895
- selectedVersion,
896
- debounced,
897
- methodFilter,
898
- activeEndpointId
899
- );
900
- }
901
- return buildFlatVM(endpoints, selectedVersion, debounced, methodFilter, activeEndpointId);
902
- }, [
903
- grouping,
904
- schemas,
905
- endpointsBySchema,
906
- endpoints,
907
- selectedVersion,
908
- debounced,
909
- methodFilter,
910
- activeEndpointId
911
- ]);
912
- const schemaOptions = React6.useMemo(
913
- () => schemas.map((s) => ({ value: s.id, label: s.name })),
914
- [schemas]
915
- );
916
- const hasMultipleSchemas = schemas.length > 1;
917
- const apiTitle = info?.title ?? "API Reference";
918
- const showCombobox = grouping === "selector" && hasMultipleSchemas;
919
- const copyReady = rawSchema !== null && rawSchema !== void 0 && endpoints.length > 0;
920
- return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "flex flex-col h-full min-h-0 border-r bg-muted/10", children: [
921
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-3 h-12 flex items-center gap-2", children: [
922
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: [
923
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[13px] font-semibold text-foreground truncate", children: apiTitle }),
924
- info?.version && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-[10px] text-muted-foreground/70 shrink-0", children: [
925
- "v",
926
- info.version
927
- ] })
928
- ] }),
929
- copyReady && /* @__PURE__ */ jsxRuntime.jsx(
930
- SchemaCopyMenu,
931
- {
932
- schema: rawSchema ?? null,
933
- endpoints,
934
- baseUrl: resolvedBaseUrl,
935
- variant: "icon"
936
- }
937
- )
938
- ] }),
939
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-3 py-3 space-y-2", children: [
940
- showCombobox && /* @__PURE__ */ jsxRuntime.jsx(
941
- components.Combobox,
942
- {
943
- options: schemaOptions,
944
- value: currentSchemaId ?? "",
945
- onValueChange: (id) => id && onSchemaChange(id),
946
- placeholder: "Select API",
947
- searchPlaceholder: "Search APIs\u2026",
948
- emptyText: "No APIs found",
949
- className: "w-full h-8 text-xs"
950
- }
951
- ),
952
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
953
- /* @__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" }),
954
- /* @__PURE__ */ jsxRuntime.jsx(
955
- components.Input,
956
- {
957
- placeholder: "Search endpoints\u2026",
958
- value: search,
959
- onChange: (e) => setSearch(e.target.value),
960
- className: "pl-8 h-8 text-xs"
961
- }
962
- )
963
- ] }),
964
- /* @__PURE__ */ jsxRuntime.jsx(MethodChips, { value: methodFilter, onChange: setMethodFilter })
965
- ] }),
966
- /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { children: /* @__PURE__ */ jsxRuntime.jsx(SidebarBody, { body, onNavigate }) })
967
- ] });
968
- }
969
- chunkWGEGR3DF_cjs.__name(DocsSidebar, "DocsSidebar");
970
- function MethodChips({
971
- value,
972
- onChange
891
+ var EndpointRow = React12__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function EndpointRow2({
892
+ row,
893
+ onNavigate
973
894
  }) {
974
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 flex-wrap", children: METHOD_FILTERS.map((m) => {
975
- const active = value === m;
976
- return /* @__PURE__ */ jsxRuntime.jsx(
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(
977
898
  "button",
978
899
  {
979
- type: "button",
980
- onClick: () => onChange(m),
981
- "aria-pressed": active,
900
+ onClick: () => onNavigate(row.anchor, row.schemaId),
901
+ "aria-current": row.isActive ? "location" : void 0,
982
902
  className: lib.cn(
983
- "px-2 py-0.5 rounded font-mono text-[10px] font-semibold tracking-wide transition-colors border",
984
- active ? "bg-primary/15 border-primary/40 text-foreground" : "bg-transparent border-border/40 text-muted-foreground hover:text-foreground hover:border-border"
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"
985
905
  ),
986
- children: m
987
- },
988
- m
989
- );
990
- }) });
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
+ ] });
991
940
  }
992
- chunkWGEGR3DF_cjs.__name(MethodChips, "MethodChips");
941
+ chunkWGEGR3DF_cjs.__name(SchemaSection, "SchemaSection");
993
942
  function SidebarBody({ body, onNavigate }) {
994
943
  if (body.kind === "flat") {
995
944
  if (body.categories.length === 0) {
996
945
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: body.emptyText });
997
946
  }
998
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-2", children: body.categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBlock, { category: cat, onNavigate }, cat.key)) });
947
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-1.5", children: body.categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBlock, { category: cat, onNavigate }, cat.key)) });
999
948
  }
1000
949
  if (body.sections.length === 0) {
1001
950
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: body.emptyText });
1002
951
  }
1003
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-2", children: body.sections.map((section) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-5 last:mb-2", children: [
1004
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-2 sticky top-0 z-[1] bg-muted/30 backdrop-blur-[2px] border-b border-border/30", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold uppercase tracking-[0.12em] text-foreground/80", children: section.sourceName }) }),
1005
- section.categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBlock, { category: cat, onNavigate }, cat.key))
1006
- ] }, section.sourceId)) });
952
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-1.5", children: body.sections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(SchemaSection, { section, onNavigate }, section.sourceId)) });
1007
953
  }
1008
954
  chunkWGEGR3DF_cjs.__name(SidebarBody, "SidebarBody");
1009
- var CategoryBlock = React6__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function CategoryBlock2({
1010
- category,
1011
- onNavigate
1012
- }) {
1013
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 last:mb-2", children: [
1014
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-1.5 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/50 select-none", children: category.category }),
1015
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: category.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(EndpointRow, { row, onNavigate }, row.key)) })
1016
- ] });
1017
- }, "CategoryBlock"));
1018
- var EndpointRow = React6__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function EndpointRow2({
1019
- row,
1020
- onNavigate
1021
- }) {
1022
- return /* @__PURE__ */ jsxRuntime.jsxs(components.Tooltip, { delayDuration: 350, children: [
1023
- /* @__PURE__ */ jsxRuntime.jsx(components.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
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(
1024
962
  "button",
1025
963
  {
1026
- onClick: () => onNavigate(row.anchor, row.schemaId),
1027
- "aria-current": row.isActive ? "location" : void 0,
964
+ type: "button",
965
+ onClick: () => onChange(m),
966
+ "aria-pressed": active,
1028
967
  className: lib.cn(
1029
- "relative group w-full text-left flex items-start gap-2 pl-4 pr-3 py-1.5 transition-colors",
1030
- row.isActive ? "bg-primary/10 text-foreground" : "hover:bg-muted/40 text-foreground/75 hover:text-foreground"
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"
1031
970
  ),
1032
- children: [
1033
- row.isActive && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded-r bg-primary" }),
1034
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 mt-[1px]", children: /* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: row.method }) }),
1035
- /* @__PURE__ */ jsxRuntime.jsx(
1036
- "span",
1037
- {
1038
- className: lib.cn(
1039
- "line-clamp-2 leading-snug flex-1 min-w-0",
1040
- row.useMono ? "font-mono text-[11px] break-all" : "text-[12px]",
1041
- row.isActive && "text-foreground font-medium"
1042
- ),
1043
- children: row.label
1044
- }
1045
- )
1046
- ]
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"
1047
988
  }
1048
- ) }),
1049
- /* @__PURE__ */ jsxRuntime.jsx(components.TooltipContent, { side: "right", align: "center", className: "font-mono text-[11px]", children: row.tooltip })
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
+ )
1050
1004
  ] });
1051
- }, "EndpointRow"));
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");
1052
1122
 
1053
1123
  // src/tools/OpenapiViewer/utils/scrollParent.ts
1054
1124
  function getScrollParent(el) {
@@ -1086,6 +1156,7 @@ function scrollTargetTo(target, top) {
1086
1156
  }
1087
1157
  chunkWGEGR3DF_cjs.__name(scrollTargetTo, "scrollTargetTo");
1088
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 }));
1089
1160
  return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pb-10 mb-10 border-b", children: [
1090
1161
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 flex-wrap", children: [
1091
1162
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap min-w-0", children: [
@@ -1104,106 +1175,776 @@ function ApiIntroSection({ info, schema, endpoints, resolvedBaseUrl }) {
1104
1175
  }
1105
1176
  )
1106
1177
  ] }),
1107
- info.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(chunkIULI4XII_cjs.MarkdownMessage, { content: info.description }) }),
1108
- info.servers && info.servers.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-2", children: [
1109
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60", children: "Base URL" }),
1110
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: info.servers.map((s, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1111
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-xs px-2 py-1 rounded bg-muted border", children: s.url }),
1112
- s.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: s.description })
1113
- ] }, `${s.url}-${i}`)) })
1114
- ] })
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 })
1115
1735
  ] });
1116
1736
  }
1117
- chunkWGEGR3DF_cjs.__name(ApiIntroSection, "ApiIntroSection");
1118
-
1119
- // src/tools/OpenapiViewer/components/DocsLayout/schemaFields.ts
1120
- var MAX_DEPTH = 2;
1121
- function describeType(node) {
1122
- if (!node.type && node.properties) return "object";
1123
- const base = node.type || "any";
1124
- if (base === "array") {
1125
- const itemType = node.items ? describeType(node.items) : "any";
1126
- return `array<${itemType}>`;
1127
- }
1128
- if (Array.isArray(node.enum) && node.enum.length > 0) {
1129
- return `${base} enum`;
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
+ ] });
1130
1757
  }
1131
- if (node.format) return `${base} (${node.format})`;
1132
- return base;
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
+ ] });
1133
1789
  }
1134
- chunkWGEGR3DF_cjs.__name(describeType, "describeType");
1135
- function schemaToFields(schema, prefix = "", depth = 0) {
1136
- if (!schema || depth > MAX_DEPTH) return [];
1137
- if (schema.type === "array") {
1138
- if (!schema.items) {
1139
- return [{ name: prefix || "[]", type: "array", required: false }];
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
+ });
1140
1846
  }
1141
- const inner = schemaToFields(schema.items, prefix ? `${prefix}[]` : "[]", depth);
1142
- if (inner.length === 0) {
1143
- return [
1144
- {
1145
- name: prefix || "[]",
1146
- type: describeType(schema),
1147
- required: false,
1148
- description: schema.description
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();
1149
1882
  }
1150
- ];
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
+ ]
1151
1911
  }
1152
- return inner;
1153
- }
1154
- if (schema.type !== "object" && !schema.properties) {
1155
- return [
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,
1156
1923
  {
1157
- name: prefix || "(body)",
1158
- type: describeType(schema),
1159
- required: false,
1160
- description: schema.description
1924
+ sectionId: id,
1925
+ title,
1926
+ badge,
1927
+ open,
1928
+ onToggle: () => toggleSection(endpointId, id)
1161
1929
  }
1162
- ];
1163
- }
1164
- const required = new Set(schema.required ?? []);
1165
- const rows = [];
1166
- const props = schema.properties ?? {};
1167
- for (const [key, node] of Object.entries(props)) {
1168
- const fullName = prefix ? `${prefix}.${key}` : key;
1169
- const isRequired = required.has(key);
1170
- const isNestedExpandable = node.type === "object" && node.properties || node.type === "array" && node.items;
1171
- if (isNestedExpandable && depth < MAX_DEPTH) {
1172
- rows.push({
1173
- name: fullName,
1174
- type: describeType(node),
1175
- required: isRequired,
1176
- description: node.description
1177
- });
1178
- rows.push(...schemaToFields(node, fullName, depth + 1));
1179
- } else {
1180
- rows.push({
1181
- name: fullName,
1182
- type: describeType(node),
1183
- required: isRequired,
1184
- description: node.description
1185
- });
1186
- }
1187
- }
1188
- return rows;
1930
+ ),
1931
+ open && /* @__PURE__ */ jsxRuntime.jsx("div", { children })
1932
+ ] });
1189
1933
  }
1190
- chunkWGEGR3DF_cjs.__name(schemaToFields, "schemaToFields");
1934
+ chunkWGEGR3DF_cjs.__name(Section, "Section");
1191
1935
  function EndpointDoc({ endpoint, isLoadedInPlayground, onTryIt, schemaId }) {
1192
1936
  const scopedSchemaId = schemaId ?? endpoint.schemaId ?? null;
1193
1937
  const anchor = endpointAnchor(endpoint, scopedSchemaId);
1194
1938
  const pathParams = endpoint.parameters?.filter((p) => endpoint.path.includes(`{${p.name}}`)) ?? [];
1195
1939
  const queryParams = endpoint.parameters?.filter((p) => !endpoint.path.includes(`{${p.name}}`)) ?? [];
1196
- const [copied, setCopied] = React6.useState(false);
1197
- const copyAnchor = React6.useCallback(() => {
1198
- if (typeof window === "undefined") return;
1199
- const url = `${window.location.origin}${window.location.pathname}#${anchor}`;
1200
- void navigator.clipboard?.writeText(url).then(() => {
1201
- setCopied(true);
1202
- setTimeout(() => setCopied(false), 1200);
1203
- });
1204
- }, [anchor]);
1205
- const endpointMd = React6.useMemo(() => chunkIULI4XII_cjs.endpointToMarkdown(endpoint), [endpoint]);
1206
- return /* @__PURE__ */ jsxRuntime.jsxs(
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(
1207
1948
  "section",
1208
1949
  {
1209
1950
  id: anchor,
@@ -1211,164 +1952,43 @@ function EndpointDoc({ endpoint, isLoadedInPlayground, onTryIt, schemaId }) {
1211
1952
  "data-schema-id": scopedSchemaId ?? "",
1212
1953
  className: "scroll-mt-24 py-10 first:pt-0",
1213
1954
  children: [
1214
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "space-y-4", children: [
1215
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 flex-wrap", children: [
1216
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2.5 min-w-0 flex-1 group/header", children: [
1217
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 translate-y-[2px]", children: /* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: endpoint.method }) }),
1218
- /* @__PURE__ */ jsxRuntime.jsx(
1219
- "code",
1220
- {
1221
- className: "font-mono text-sm md:text-[15px] font-medium text-foreground leading-snug min-w-0",
1222
- style: { overflowWrap: "anywhere", wordBreak: "break-word" },
1223
- children: chunkIULI4XII_cjs.relativePath(endpoint.path)
1224
- }
1225
- ),
1226
- /* @__PURE__ */ jsxRuntime.jsx(
1227
- "button",
1228
- {
1229
- type: "button",
1230
- onClick: copyAnchor,
1231
- title: "Copy link to this section",
1232
- className: lib.cn(
1233
- "shrink-0 p-1 rounded text-muted-foreground/40 hover:text-foreground hover:bg-muted transition-all",
1234
- "opacity-0 group-hover/header:opacity-100",
1235
- copied && "opacity-100 text-emerald-500"
1236
- ),
1237
- children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, { className: "h-3.5 w-3.5" })
1238
- }
1239
- ),
1240
- /* @__PURE__ */ jsxRuntime.jsx(
1241
- components.CopyButton,
1242
- {
1243
- value: endpointMd,
1244
- title: "Copy endpoint as markdown (for AI)",
1245
- variant: "ghost",
1246
- size: "icon",
1247
- iconClassName: "h-3.5 w-3.5",
1248
- className: lib.cn(
1249
- "shrink-0 h-6 w-6 text-muted-foreground/40 hover:text-foreground",
1250
- "opacity-0 group-hover/header:opacity-100 focus-visible:opacity-100"
1251
- )
1252
- }
1253
- )
1254
- ] }),
1255
- /* @__PURE__ */ jsxRuntime.jsxs(
1256
- components.Button,
1257
- {
1258
- size: "sm",
1259
- variant: isLoadedInPlayground ? "secondary" : "default",
1260
- onClick: onTryIt,
1261
- className: "shrink-0 h-8 text-xs gap-1.5 lg:flex hidden",
1262
- children: [
1263
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-3 w-3" }),
1264
- isLoadedInPlayground ? "Loaded" : "Try it"
1265
- ]
1266
- }
1267
- )
1268
- ] }),
1269
- endpoint.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(chunkIULI4XII_cjs.MarkdownMessage, { content: endpoint.description }) }),
1270
- /* @__PURE__ */ jsxRuntime.jsxs(
1271
- components.Button,
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,
1272
1968
  {
1273
- size: "sm",
1274
- variant: isLoadedInPlayground ? "secondary" : "default",
1275
- onClick: onTryIt,
1276
- className: "lg:hidden h-8 text-xs gap-1.5",
1277
- children: [
1278
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-3 w-3" }),
1279
- isLoadedInPlayground ? "Loaded in playground" : "Try it"
1280
- ]
1969
+ id: "parameters",
1970
+ title: "Parameters",
1971
+ badge: pathParams.length + queryParams.length,
1972
+ children: /* @__PURE__ */ jsxRuntime.jsx(Parameters, { pathParams, queryParams })
1281
1973
  }
1282
- )
1283
- ] }),
1284
- (pathParams.length > 0 || queryParams.length > 0 || endpoint.requestBody || endpoint.responses?.length) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8 space-y-8", children: [
1285
- pathParams.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ParamTable, { title: "Path parameters", params: pathParams }),
1286
- queryParams.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ParamTable, { title: "Query parameters", params: queryParams }),
1287
- endpoint.requestBody && /* @__PURE__ */ jsxRuntime.jsx(RequestBodySection, { body: endpoint.requestBody }),
1288
- endpoint.responses && endpoint.responses.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Subsection, { title: "Responses", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y border rounded-md overflow-hidden", children: endpoint.responses.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
1289
- "div",
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,
1290
1979
  {
1291
- className: "grid grid-cols-[72px_minmax(0,1fr)] items-center gap-3 px-3 py-2.5 bg-background",
1292
- children: [
1293
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(StatusTag, { code: r.code }) }),
1294
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground leading-relaxed break-words", children: r.description })
1295
- ]
1296
- },
1297
- r.code
1298
- )) }) })
1980
+ id: "responses",
1981
+ title: "Responses",
1982
+ badge: endpoint.responses.length,
1983
+ children: /* @__PURE__ */ jsxRuntime.jsx(Responses, { responses: endpoint.responses })
1984
+ }
1985
+ )
1299
1986
  ] })
1300
1987
  ]
1301
1988
  }
1302
- );
1989
+ ) });
1303
1990
  }
1304
1991
  chunkWGEGR3DF_cjs.__name(EndpointDoc, "EndpointDoc");
1305
- function RequestBodySection({ body }) {
1306
- const fields = React6.useMemo(() => schemaToFields(body.schema), [body.schema]);
1307
- const typeLabel = body.schema ? body.type === "array" ? `array<${body.schema.items?.type ?? "object"}>` : body.type : body.type;
1308
- return /* @__PURE__ */ jsxRuntime.jsx(Subsection, { title: "Request body", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1309
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1310
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground/80", children: typeLabel }),
1311
- body.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: body.description })
1312
- ] }),
1313
- fields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(FieldsTable, { fields })
1314
- ] }) });
1315
- }
1316
- chunkWGEGR3DF_cjs.__name(RequestBodySection, "RequestBodySection");
1317
- function FieldsTable({ fields }) {
1318
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y border rounded-md overflow-hidden", children: fields.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2.5 bg-background space-y-1", children: [
1319
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1320
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-xs font-medium text-foreground", children: f.name }),
1321
- f.required && /* @__PURE__ */ jsxRuntime.jsx(
1322
- "span",
1323
- {
1324
- title: "Required",
1325
- className: "text-[9px] text-destructive font-bold leading-none",
1326
- children: "*"
1327
- }
1328
- ),
1329
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground/70", children: f.type })
1330
- ] }),
1331
- f.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground leading-relaxed break-words", children: f.description })
1332
- ] }, f.name)) });
1333
- }
1334
- chunkWGEGR3DF_cjs.__name(FieldsTable, "FieldsTable");
1335
- function Subsection({ title, children }) {
1336
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2.5", children: [
1337
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/70", children: title }),
1338
- children
1339
- ] });
1340
- }
1341
- chunkWGEGR3DF_cjs.__name(Subsection, "Subsection");
1342
- function ParamTable({
1343
- title,
1344
- params
1345
- }) {
1346
- return /* @__PURE__ */ jsxRuntime.jsx(Subsection, { title, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y border rounded-md overflow-hidden", children: params.map((p) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2.5 bg-background space-y-1", children: [
1347
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2 flex-wrap", children: [
1348
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-xs font-medium text-foreground", children: p.name }),
1349
- p.required && /* @__PURE__ */ jsxRuntime.jsx(
1350
- "span",
1351
- {
1352
- title: "Required",
1353
- className: "text-[9px] text-destructive font-bold leading-none",
1354
- children: "*"
1355
- }
1356
- ),
1357
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground/70", children: p.type })
1358
- ] }),
1359
- p.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground leading-relaxed break-words", children: p.description }) : null
1360
- ] }, p.name)) }) });
1361
- }
1362
- chunkWGEGR3DF_cjs.__name(ParamTable, "ParamTable");
1363
- function StatusTag({ code }) {
1364
- const numeric = Number.parseInt(code, 10);
1365
- 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";
1366
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: lib.cn(
1367
- "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",
1368
- cls
1369
- ), children: code });
1370
- }
1371
- chunkWGEGR3DF_cjs.__name(StatusTag, "StatusTag");
1372
1992
  var readNavbarOffset = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
1373
1993
  if (typeof document === "undefined") return 0;
1374
1994
  const raw = getComputedStyle(document.documentElement).getPropertyValue("--navbar-height");
@@ -1396,7 +2016,7 @@ function buildSchemaSectionVM(entry, selectedVersion, loadedEndpoint) {
1396
2016
  } else if (entry.error) {
1397
2017
  state = { kind: "error", message: entry.error };
1398
2018
  } else {
1399
- const visible = chunkIULI4XII_cjs.deduplicateEndpoints(entry.endpoints, selectedVersion);
2019
+ const visible = chunk5Q4UMSWB_cjs.deduplicateEndpoints(entry.endpoints, selectedVersion);
1400
2020
  state = visible.length === 0 ? { kind: "empty" } : {
1401
2021
  kind: "ready",
1402
2022
  rows: visible.map((ep) => buildEndpointRow(ep, loadedEndpoint, entry.source.id))
@@ -1414,17 +2034,18 @@ function buildSchemaSectionVM(entry, selectedVersion, loadedEndpoint) {
1414
2034
  };
1415
2035
  }
1416
2036
  chunkWGEGR3DF_cjs.__name(buildSchemaSectionVM, "buildSchemaSectionVM");
1417
- var DocsView = React6__default.default.forwardRef(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function DocsView2(props, ref) {
1418
- const scrollRef = React6.useRef(null);
1419
- const scrollTargetRef = React6.useRef(null);
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);
1420
2040
  const { onActiveChange } = props;
1421
- const ensureScrollTarget = React6.useCallback(() => {
2041
+ useSectionHashRouter();
2042
+ const ensureScrollTarget = React12.useCallback(() => {
1422
2043
  if (scrollTargetRef.current) return scrollTargetRef.current;
1423
2044
  if (!scrollRef.current) return null;
1424
2045
  scrollTargetRef.current = getScrollParent(scrollRef.current);
1425
2046
  return scrollTargetRef.current;
1426
2047
  }, []);
1427
- const scrollToAnchor = React6.useCallback(
2048
+ const scrollToAnchor = React12.useCallback(
1428
2049
  (anchor) => {
1429
2050
  const root = scrollRef.current;
1430
2051
  if (!root) return;
@@ -1438,8 +2059,8 @@ var DocsView = React6__default.default.forwardRef(/* @__PURE__ */ chunkWGEGR3DF_
1438
2059
  },
1439
2060
  [ensureScrollTarget]
1440
2061
  );
1441
- React6__default.default.useImperativeHandle(ref, () => ({ scrollToAnchor }), [scrollToAnchor]);
1442
- React6.useEffect(() => {
2062
+ React12__default.default.useImperativeHandle(ref, () => ({ scrollToAnchor }), [scrollToAnchor]);
2063
+ React12.useEffect(() => {
1443
2064
  const root = scrollRef.current;
1444
2065
  if (!root) return;
1445
2066
  const target = ensureScrollTarget();
@@ -1496,11 +2117,11 @@ function SelectorBody({
1496
2117
  loadedEndpoint,
1497
2118
  onTryEndpoint
1498
2119
  }) {
1499
- const visibleEndpoints = React6.useMemo(
1500
- () => chunkIULI4XII_cjs.deduplicateEndpoints(endpoints, selectedVersion),
2120
+ const visibleEndpoints = React12.useMemo(
2121
+ () => chunk5Q4UMSWB_cjs.deduplicateEndpoints(endpoints, selectedVersion),
1501
2122
  [endpoints, selectedVersion]
1502
2123
  );
1503
- const rows = React6.useMemo(
2124
+ const rows = React12.useMemo(
1504
2125
  () => visibleEndpoints.map((ep) => buildEndpointRow(ep, loadedEndpoint, ep.schemaId ?? null)),
1505
2126
  [visibleEndpoints, loadedEndpoint]
1506
2127
  );
@@ -1535,14 +2156,14 @@ function SectionsBody({
1535
2156
  loadedEndpoint,
1536
2157
  onTryEndpoint
1537
2158
  }) {
1538
- const sections = React6.useMemo(
2159
+ const sections = React12.useMemo(
1539
2160
  () => schemasData.map((e) => buildSchemaSectionVM(e, selectedVersion, loadedEndpoint)),
1540
2161
  [schemasData, selectedVersion, loadedEndpoint]
1541
2162
  );
1542
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)) }) });
1543
2164
  }
1544
2165
  chunkWGEGR3DF_cjs.__name(SectionsBody, "SectionsBody");
1545
- var SchemaSectionView = React6__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function SchemaSectionView2({
2166
+ var SchemaSectionView = React12__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function SchemaSectionView2({
1546
2167
  section,
1547
2168
  onTryEndpoint
1548
2169
  }) {
@@ -1797,8 +2418,8 @@ function RawJsonField({
1797
2418
  value,
1798
2419
  onChange
1799
2420
  }) {
1800
- const [text, setText] = React6__default.default.useState(() => JSON.stringify(value ?? null, null, 2));
1801
- React6__default.default.useEffect(() => {
2421
+ const [text, setText] = React12__default.default.useState(() => JSON.stringify(value ?? null, null, 2));
2422
+ React12__default.default.useEffect(() => {
1802
2423
  setText(JSON.stringify(value ?? null, null, 2));
1803
2424
  }, [value]);
1804
2425
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
@@ -1834,7 +2455,7 @@ function ObjectField({
1834
2455
  const obj = value && typeof value === "object" && !Array.isArray(value) ? value : {};
1835
2456
  const required = new Set(schema.required ?? []);
1836
2457
  const entries = Object.entries(schema.properties ?? {});
1837
- const setKey = React6.useCallback(
2458
+ const setKey = React12.useCallback(
1838
2459
  (key) => (next) => {
1839
2460
  onChange({ ...obj, [key]: next });
1840
2461
  },
@@ -1925,11 +2546,11 @@ function ArrayField({
1925
2546
  }
1926
2547
  chunkWGEGR3DF_cjs.__name(ArrayField, "ArrayField");
1927
2548
  function EndpointResetButton() {
1928
- const { state, setParameters, setRequestBody } = chunkIULI4XII_cjs.usePlaygroundContext();
2549
+ const { state, setParameters, setRequestBody } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
1929
2550
  const ep = state.selectedEndpoint;
1930
2551
  const { reset } = useEndpointDraft(state.activeSchemaId, ep);
1931
2552
  const hasDraft = Object.keys(state.parameters).length > 0 || state.requestBody.length > 0;
1932
- const onClick = React6.useCallback(() => {
2553
+ const onClick = React12.useCallback(() => {
1933
2554
  setParameters({});
1934
2555
  setRequestBody("");
1935
2556
  reset();
@@ -1954,7 +2575,7 @@ function EndpointResetButton() {
1954
2575
  }
1955
2576
  chunkWGEGR3DF_cjs.__name(EndpointResetButton, "EndpointResetButton");
1956
2577
  function ParamFields({ label, params }) {
1957
- const { state, setParameters } = chunkIULI4XII_cjs.usePlaygroundContext();
2578
+ const { state, setParameters } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
1958
2579
  function handleChange(name, value) {
1959
2580
  setParameters({ ...state.parameters, [name]: value });
1960
2581
  }
@@ -1994,8 +2615,8 @@ function RequestPanel() {
1994
2615
  setSelectedApiKey,
1995
2616
  setManualApiToken,
1996
2617
  sendRequest
1997
- } = chunkIULI4XII_cjs.usePlaygroundContext();
1998
- const apiKeyOptions = React6.useMemo(
2618
+ } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2619
+ const apiKeyOptions = React12.useMemo(
1999
2620
  () => apiKeys.map((k) => ({
2000
2621
  value: k.id,
2001
2622
  label: k.name || "Unnamed key",
@@ -2007,12 +2628,12 @@ function RequestPanel() {
2007
2628
  );
2008
2629
  const hasApiKeys = apiKeyOptions.length > 0;
2009
2630
  const ep = state.selectedEndpoint;
2010
- const isJsonValid = state.requestBody ? chunkIULI4XII_cjs.isValidJson(state.requestBody) : true;
2011
- const curlCommand = React6.useMemo(() => {
2631
+ const isJsonValid = state.requestBody ? chunk5Q4UMSWB_cjs.isValidJson(state.requestBody) : true;
2632
+ const curlCommand = React12.useMemo(() => {
2012
2633
  if (!state.requestUrl) return "";
2013
- const absoluteUrl = chunkIULI4XII_cjs.resolveAbsolute(state.requestUrl);
2014
- const apiKey = state.selectedApiKey ? chunkIULI4XII_cjs.findApiKeyById(apiKeys, state.selectedApiKey) : null;
2015
- const hdrs = chunkIULI4XII_cjs.parseRequestHeaders(state.requestHeaders);
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);
2016
2637
  if (apiKey) hdrs["X-API-Key"] = apiKey.secret || apiKey.id;
2017
2638
  let cmd = `curl -X ${state.requestMethod} "${absoluteUrl}"`;
2018
2639
  Object.entries(hdrs).forEach(([k, v]) => {
@@ -2025,22 +2646,22 @@ function RequestPanel() {
2025
2646
  }
2026
2647
  return cmd;
2027
2648
  }, [state, apiKeys, isJsonValid]);
2028
- const pathParams = React6.useMemo(
2649
+ const pathParams = React12.useMemo(
2029
2650
  () => ep?.parameters?.filter((p) => ep.path.includes(`{${p.name}}`)) ?? [],
2030
2651
  [ep]
2031
2652
  );
2032
- const queryParams = React6.useMemo(
2653
+ const queryParams = React12.useMemo(
2033
2654
  () => ep?.parameters?.filter((p) => !ep.path.includes(`{${p.name}}`)) ?? [],
2034
2655
  [ep]
2035
2656
  );
2036
2657
  state.loading || !state.requestUrl || !isJsonValid;
2037
- const displayUrl = chunkIULI4XII_cjs.resolveAbsolute(state.requestUrl || ep?.path || "");
2658
+ const displayUrl = chunk5Q4UMSWB_cjs.resolveAbsolute(state.requestUrl || ep?.path || "");
2038
2659
  const hasBody = ep?.method !== "GET";
2039
2660
  const bodyType = ep?.requestBody?.type ?? "";
2040
2661
  const hasPathParams = pathParams.length > 0;
2041
2662
  const hasQueryParams = queryParams.length > 0;
2042
2663
  const hasCurl = Boolean(curlCommand);
2043
- const epPath = ep ? chunkIULI4XII_cjs.relativePath(ep.path) : "";
2664
+ const epPath = ep ? chunk5Q4UMSWB_cjs.relativePath(ep.path) : "";
2044
2665
  const urlChanged = displayUrl !== "" && displayUrl !== epPath;
2045
2666
  if (!ep) {
2046
2667
  return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { icon: lucideReact.Send, text: "Select an endpoint to build a request" });
@@ -2130,7 +2751,7 @@ function RequestPanel() {
2130
2751
  "cURL"
2131
2752
  ] }),
2132
2753
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
2133
- chunkIULI4XII_cjs.PrettyCode_default,
2754
+ chunk5Q4UMSWB_cjs.PrettyCode_default,
2134
2755
  {
2135
2756
  data: curlCommand,
2136
2757
  language: "bash",
@@ -2147,8 +2768,8 @@ function RequestPanel() {
2147
2768
  chunkWGEGR3DF_cjs.__name(RequestPanel, "RequestPanel");
2148
2769
  function BodySection({ schema, bodyType, bodyDescription, value, onChange, isJsonValid }) {
2149
2770
  const hasSchema = !!schema;
2150
- const [mode, setMode] = React6__default.default.useState(hasSchema ? "form" : "json");
2151
- const parsed = React6__default.default.useMemo(() => {
2771
+ const [mode, setMode] = React12__default.default.useState(hasSchema ? "form" : "json");
2772
+ const parsed = React12__default.default.useMemo(() => {
2152
2773
  if (!value) return null;
2153
2774
  try {
2154
2775
  return JSON.parse(value);
@@ -2156,7 +2777,7 @@ function BodySection({ schema, bodyType, bodyDescription, value, onChange, isJso
2156
2777
  return null;
2157
2778
  }
2158
2779
  }, [value]);
2159
- const handleFormChange = React6.useCallback(
2780
+ const handleFormChange = React12.useCallback(
2160
2781
  (next) => {
2161
2782
  onChange(JSON.stringify(next, null, 2));
2162
2783
  },
@@ -2236,6 +2857,65 @@ function ModeButton({
2236
2857
  );
2237
2858
  }
2238
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");
2239
2919
  var JSON_TREE_CONFIG = {
2240
2920
  maxAutoExpandDepth: 2,
2241
2921
  maxAutoExpandArrayItems: 10,
@@ -2248,26 +2928,198 @@ var JSON_TREE_CONFIG = {
2248
2928
  preserveKeyOrder: true,
2249
2929
  className: "border-0 rounded-none"
2250
2930
  };
2251
- function ResponsePanel() {
2252
- const { state } = chunkIULI4XII_cjs.usePlaygroundContext();
2253
- const { response, loading, selectedEndpoint } = state;
2254
- const { treeData, rawText } = React6.useMemo(() => {
2255
- const d = response?.data;
2256
- if (d == null) return { treeData: null, rawText: "" };
2257
- if (typeof d === "string") {
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") {
2258
3063
  try {
2259
- return { treeData: JSON.parse(d), rawText: d };
3064
+ return {
3065
+ treeData: JSON.parse(data),
3066
+ rawText: data,
3067
+ detected: detectContent(headers, data)
3068
+ };
2260
3069
  } catch {
2261
- return { treeData: null, rawText: d };
3070
+ return {
3071
+ treeData: null,
3072
+ rawText: data,
3073
+ detected: detectContent(headers, data)
3074
+ };
2262
3075
  }
2263
3076
  }
2264
- return { treeData: d, rawText: JSON.stringify(d, null, 2) };
2265
- }, [response?.data]);
2266
- const sizeKb = rawText ? `${(rawText.length / 1024).toFixed(1)} KB` : "";
2267
- const duration = response?.duration != null ? `${response.duration}ms` : "";
2268
- const hasError = Boolean(response?.error);
2269
- const hasStatus = response?.status != null;
2270
- const hasCopy = Boolean(rawText);
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]);
2271
3123
  if (loading) {
2272
3124
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center h-full gap-2", children: [
2273
3125
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }),
@@ -2276,6 +3128,8 @@ function ResponsePanel() {
2276
3128
  }
2277
3129
  if (!selectedEndpoint) return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { icon: lucideReact.Terminal, text: "Response will appear here" });
2278
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;
2279
3133
  if (hasError && !hasStatus) {
2280
3134
  return /* @__PURE__ */ jsxRuntime.jsx(
2281
3135
  EmptyState,
@@ -2287,30 +3141,27 @@ function ResponsePanel() {
2287
3141
  );
2288
3142
  }
2289
3143
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2290
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-4 py-2 flex items-center justify-between gap-3 bg-muted/20", children: [
2291
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
2292
- hasStatus && /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: response.status }),
2293
- response.statusText && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground truncate", children: response.statusText }),
2294
- sizeKb && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/50 tabular-nums shrink-0", children: sizeKb }),
2295
- duration && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/50 tabular-nums shrink-0", children: duration })
2296
- ] }),
2297
- hasCopy && /* @__PURE__ */ jsxRuntime.jsx(components.CopyButton, { value: rawText, variant: "ghost", size: "sm", className: "h-6 px-2 text-[10px] text-muted-foreground shrink-0", children: "Copy" })
2298
- ] }),
3144
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBar, { response, rawText, contentType: detected.contentType }),
2299
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 }) }),
2300
- /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { children: treeData != null ? /* @__PURE__ */ jsxRuntime.jsx(chunk33AMWFBZ_cjs.JsonTree_default, { title: "Response Body", data: treeData, config: JSON_TREE_CONFIG }) : rawText ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-4 text-[11px] font-mono text-foreground/70 whitespace-pre-wrap break-all leading-relaxed", children: rawText }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 text-center text-xs text-muted-foreground", children: "Empty response body" }) })
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
+ ] })
2301
3152
  ] });
2302
3153
  }
2303
3154
  chunkWGEGR3DF_cjs.__name(ResponsePanel, "ResponsePanel");
2304
3155
  function SendButton({ className }) {
2305
- const { state, sendRequest } = chunkIULI4XII_cjs.usePlaygroundContext();
3156
+ const { state, sendRequest } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2306
3157
  const ep = state.selectedEndpoint;
2307
- const builder = React6.useMemo(
2308
- () => ep ? new chunkIULI4XII_cjs.UrlBuilder(ep, state.parameters) : null,
3158
+ const builder = React12.useMemo(
3159
+ () => ep ? new chunk5Q4UMSWB_cjs.UrlBuilder(ep, state.parameters) : null,
2309
3160
  [ep, state.parameters]
2310
3161
  );
2311
3162
  const missingRequired = builder?.missingRequired() ?? [];
2312
3163
  const unsubstituted = builder?.unfilledPlaceholders() ?? [];
2313
- const isJsonValid = state.requestBody ? chunkIULI4XII_cjs.isValidJson(state.requestBody) : true;
3164
+ const isJsonValid = state.requestBody ? chunk5Q4UMSWB_cjs.isValidJson(state.requestBody) : true;
2314
3165
  const blockers = [];
2315
3166
  if (missingRequired.length > 0) {
2316
3167
  blockers.push(
@@ -2350,7 +3201,7 @@ chunkWGEGR3DF_cjs.__name(SendButton, "SendButton");
2350
3201
  var WIDTH_NARROW = "clamp(380px, 30vw, 480px)";
2351
3202
  var WIDTH_WIDE = "clamp(720px, 60vw, 1280px)";
2352
3203
  function SlideInPlayground({ open, onClose }) {
2353
- const { state } = chunkIULI4XII_cjs.usePlaygroundContext();
3204
+ const { state } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2354
3205
  const ep = state.selectedEndpoint;
2355
3206
  const showResponse = state.response !== null || state.loading;
2356
3207
  const width = showResponse ? WIDTH_WIDE : WIDTH_NARROW;
@@ -2359,7 +3210,7 @@ function SlideInPlayground({ open, onClose }) {
2359
3210
  /* @__PURE__ */ jsxRuntime.jsx(components.SidePanel.Title, { children: "Playground" }),
2360
3211
  ep && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [
2361
3212
  /* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: ep.method }),
2362
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground truncate", children: chunkIULI4XII_cjs.relativePath(ep.path) })
3213
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-[11px] text-muted-foreground truncate", children: chunk5Q4UMSWB_cjs.relativePath(ep.path) })
2363
3214
  ] }),
2364
3215
  /* @__PURE__ */ jsxRuntime.jsx(components.SidePanel.Close, { className: "ml-auto" })
2365
3216
  ] }),
@@ -2371,30 +3222,34 @@ function SlideInPlayground({ open, onClose }) {
2371
3222
  showResponse ? "grid-cols-[minmax(0,1fr)_minmax(0,1fr)]" : "grid-cols-1"
2372
3223
  ),
2373
3224
  children: [
2374
- /* @__PURE__ */ jsxRuntime.jsx(Panel, { children: /* @__PURE__ */ jsxRuntime.jsx(RequestPanel, {}) }),
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
+ ] }),
2375
3229
  showResponse && /* @__PURE__ */ jsxRuntime.jsx(Panel, { children: /* @__PURE__ */ jsxRuntime.jsx(ResponsePanel, {}) })
2376
3230
  ]
2377
3231
  }
2378
- ),
2379
- ep && /* @__PURE__ */ jsxRuntime.jsx(components.SidePanel.Footer, { className: "px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(SendButton, {}) })
3232
+ )
2380
3233
  ] }) });
2381
3234
  }
2382
3235
  chunkWGEGR3DF_cjs.__name(SlideInPlayground, "SlideInPlayground");
2383
3236
  function TryItSheet({ open, onOpenChange }) {
2384
- const { state } = chunkIULI4XII_cjs.usePlaygroundContext();
3237
+ const { state } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2385
3238
  const showResponse = state.response !== null || state.loading;
2386
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: [
2387
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" }) }),
2388
3241
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-h-0 flex flex-col divide-y", children: [
2389
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: showResponse ? "flex-1 min-h-0 flex flex-col" : "flex-1 min-h-0 flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx(RequestPanel, {}) }),
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
+ ] }),
2390
3246
  showResponse && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx(ResponsePanel, {}) })
2391
- ] }),
2392
- state.selectedEndpoint && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-t px-4 py-3 bg-background/95 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsx(SendButton, {}) })
3247
+ ] })
2393
3248
  ] }) });
2394
3249
  }
2395
3250
  chunkWGEGR3DF_cjs.__name(TryItSheet, "TryItSheet");
2396
3251
  var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
2397
- const { state, config, setSelectedEndpoint } = chunkIULI4XII_cjs.usePlaygroundContext();
3252
+ const { state, config, setSelectedEndpoint } = chunk5Q4UMSWB_cjs.usePlaygroundContext();
2398
3253
  const isDesktop = hooks.useMediaQuery("(min-width: 1024px)");
2399
3254
  const isMobile = !isDesktop;
2400
3255
  const grouping = config.schemaGrouping ?? "selector";
@@ -2417,29 +3272,29 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
2417
3272
  baseUrl: config.baseUrl,
2418
3273
  preloadAll
2419
3274
  });
2420
- const [activeAnchor, setActiveAnchor] = React6.useState(null);
2421
- const [activeSchemaId, setActiveSchemaId] = React6.useState(null);
2422
- const [sheetOpen, setSheetOpen] = React6.useState(false);
2423
- const docsRef = React6.useRef(null);
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);
2424
3279
  const slideOpen = !isMobile && state.selectedEndpoint !== null;
2425
- const endpointsBySchema = React6.useMemo(() => {
3280
+ const endpointsBySchema = React12.useMemo(() => {
2426
3281
  if (grouping !== "sections") return {};
2427
3282
  const byId = lodashEs.keyBy(schemasData, (e) => e.source.id);
2428
3283
  const out = {};
2429
3284
  for (const src of schemas) out[src.id] = byId[src.id]?.endpoints ?? [];
2430
3285
  return out;
2431
3286
  }, [grouping, schemasData, schemas]);
2432
- const handleTry = React6.useCallback(
3287
+ const handleTry = React12.useCallback(
2433
3288
  (ep) => {
2434
3289
  setSelectedEndpoint(ep);
2435
3290
  if (isMobile) setSheetOpen(true);
2436
3291
  },
2437
3292
  [isMobile, setSelectedEndpoint]
2438
3293
  );
2439
- const handleCloseSlide = React6.useCallback(() => {
3294
+ const handleCloseSlide = React12.useCallback(() => {
2440
3295
  setSelectedEndpoint(null);
2441
3296
  }, [setSelectedEndpoint]);
2442
- const handleNavigate = React6.useCallback(
3297
+ const handleNavigate = React12.useCallback(
2443
3298
  (anchor, schemaId) => {
2444
3299
  if (schemaId && schemaId !== currentSchema?.id && grouping === "selector") {
2445
3300
  setCurrentSchema(schemaId);
@@ -2452,12 +3307,12 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
2452
3307
  },
2453
3308
  [currentSchema?.id, grouping, setCurrentSchema]
2454
3309
  );
2455
- const handleActiveChange = React6.useCallback((anchor, schemaId) => {
3310
+ const handleActiveChange = React12.useCallback((anchor, schemaId) => {
2456
3311
  setActiveAnchor(anchor);
2457
3312
  setActiveSchemaId(schemaId);
2458
3313
  }, []);
2459
3314
  const effectiveSchemaId = grouping === "sections" ? activeSchemaId : currentSchema?.id ?? null;
2460
- const handleHashTarget = React6.useCallback(
3315
+ const handleHashTarget = React12.useCallback(
2461
3316
  (target) => {
2462
3317
  if (!target.schemaId && !target.anchor) return;
2463
3318
  const matched = target.schemaId ? schemas.find((s) => s.id === target.schemaId || slugifySchemaId(s.id) === target.schemaId) : null;
@@ -2605,5 +3460,5 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
2605
3460
  }, "DocsLayout");
2606
3461
 
2607
3462
  exports.DocsLayout = DocsLayout;
2608
- //# sourceMappingURL=DocsLayout-YDR7DSMM.cjs.map
2609
- //# sourceMappingURL=DocsLayout-YDR7DSMM.cjs.map
3463
+ //# sourceMappingURL=DocsLayout-IKH7BLSU.cjs.map
3464
+ //# sourceMappingURL=DocsLayout-IKH7BLSU.cjs.map