@djangocfg/ui-tools 2.1.286 → 2.1.289
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.
- package/dist/{DocsLayout-ERETJLLV.mjs → DocsLayout-TKJQ5W5E.mjs} +848 -266
- package/dist/DocsLayout-TKJQ5W5E.mjs.map +1 -0
- package/dist/{DocsLayout-BCVU6TTX.cjs → DocsLayout-YDR7DSMM.cjs} +843 -261
- package/dist/DocsLayout-YDR7DSMM.cjs.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.mjs +2 -2
- package/package.json +9 -6
- package/src/tools/OpenapiViewer/.claude/.sidecar/activity.jsonl +2 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/history/2026-04-22.md +35 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/review.md +35 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/scan.log +3 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-001.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-002.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-003.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-004.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-005.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/usage.json +2 -2
- package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +27 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/DocsView.tsx +326 -54
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc.tsx +7 -2
- package/src/tools/OpenapiViewer/components/DocsLayout/SchemaCopyMenu.tsx +32 -9
- package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar.tsx +348 -120
- package/src/tools/OpenapiViewer/components/DocsLayout/anchor.ts +19 -2
- package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +38 -21
- package/src/tools/OpenapiViewer/components/DocsLayout/index.tsx +168 -50
- package/src/tools/OpenapiViewer/hooks/index.ts +3 -1
- package/src/tools/OpenapiViewer/hooks/useDocsUrlSync.ts +119 -0
- package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +127 -7
- package/src/tools/OpenapiViewer/types.ts +36 -1
- package/src/tools/OpenapiViewer/utils/scrollParent.ts +68 -0
- package/dist/DocsLayout-BCVU6TTX.cjs.map +0 -1
- package/dist/DocsLayout-ERETJLLV.mjs.map +0 -1
|
@@ -5,6 +5,7 @@ var chunk33AMWFBZ_cjs = require('./chunk-33AMWFBZ.cjs');
|
|
|
5
5
|
require('./chunk-2SMCH62O.cjs');
|
|
6
6
|
var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
|
|
7
7
|
var React6 = require('react');
|
|
8
|
+
var lodashEs = require('lodash-es');
|
|
8
9
|
var components = require('@djangocfg/ui-core/components');
|
|
9
10
|
var hooks = require('@djangocfg/ui-core/hooks');
|
|
10
11
|
var consola = require('consola');
|
|
@@ -58,7 +59,7 @@ function exampleFromSchema(schema, depth = 0) {
|
|
|
58
59
|
}
|
|
59
60
|
chunkWGEGR3DF_cjs.__name(exampleFromSchema, "exampleFromSchema");
|
|
60
61
|
var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
|
|
61
|
-
var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl) => {
|
|
62
|
+
var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl, schemaId) => {
|
|
62
63
|
const endpoints = [];
|
|
63
64
|
if (!schema.paths) return [];
|
|
64
65
|
for (const [path, methods] of Object.entries(schema.paths)) {
|
|
@@ -109,7 +110,8 @@ var extractEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((schema, baseUrl
|
|
|
109
110
|
category,
|
|
110
111
|
parameters: parameters.length > 0 ? parameters : void 0,
|
|
111
112
|
requestBody,
|
|
112
|
-
responses: responses.length > 0 ? responses : void 0
|
|
113
|
+
responses: responses.length > 0 ? responses : void 0,
|
|
114
|
+
schemaId
|
|
113
115
|
};
|
|
114
116
|
endpoints.push(endpoint);
|
|
115
117
|
}
|
|
@@ -135,7 +137,8 @@ var fetchSchema = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(async (url) => {
|
|
|
135
137
|
function useOpenApiSchema({
|
|
136
138
|
schemas,
|
|
137
139
|
defaultSchemaId,
|
|
138
|
-
baseUrl: configBaseUrl
|
|
140
|
+
baseUrl: configBaseUrl,
|
|
141
|
+
preloadAll = false
|
|
139
142
|
}) {
|
|
140
143
|
const [loading, setLoading] = React6.useState(true);
|
|
141
144
|
const [error, setError] = React6.useState(null);
|
|
@@ -145,6 +148,7 @@ function useOpenApiSchema({
|
|
|
145
148
|
const [loadedSchemas, setLoadedSchemas] = React6.useState(
|
|
146
149
|
/* @__PURE__ */ new Map()
|
|
147
150
|
);
|
|
151
|
+
const [loadStates, setLoadStates] = React6.useState(/* @__PURE__ */ new Map());
|
|
148
152
|
const currentSchema = React6.useMemo(
|
|
149
153
|
() => schemas.find((s) => s.id === currentSchemaId) || null,
|
|
150
154
|
[schemas, currentSchemaId]
|
|
@@ -166,8 +170,8 @@ function useOpenApiSchema({
|
|
|
166
170
|
[currentSchema?.baseUrl, configBaseUrl, currentOpenApiSchema]
|
|
167
171
|
);
|
|
168
172
|
const endpoints = React6.useMemo(
|
|
169
|
-
() => dereferencedSchema ? extractEndpoints(dereferencedSchema, resolvedBaseUrl) : [],
|
|
170
|
-
[dereferencedSchema, resolvedBaseUrl]
|
|
173
|
+
() => dereferencedSchema ? extractEndpoints(dereferencedSchema, resolvedBaseUrl, currentSchemaId) : [],
|
|
174
|
+
[dereferencedSchema, resolvedBaseUrl, currentSchemaId]
|
|
171
175
|
);
|
|
172
176
|
const categories = React6.useMemo(() => getCategories(endpoints), [endpoints]);
|
|
173
177
|
const schemaInfo = React6.useMemo(() => {
|
|
@@ -181,6 +185,7 @@ function useOpenApiSchema({
|
|
|
181
185
|
};
|
|
182
186
|
}, [currentOpenApiSchema]);
|
|
183
187
|
React6.useEffect(() => {
|
|
188
|
+
if (preloadAll) return;
|
|
184
189
|
if (!currentSchema) return;
|
|
185
190
|
if (loadedSchemas.has(currentSchema.id)) {
|
|
186
191
|
setLoading(false);
|
|
@@ -197,7 +202,90 @@ function useOpenApiSchema({
|
|
|
197
202
|
setError(err instanceof Error ? err.message : "Failed to load schema");
|
|
198
203
|
setLoading(false);
|
|
199
204
|
});
|
|
200
|
-
}, [currentSchema, loadedSchemas]);
|
|
205
|
+
}, [currentSchema, loadedSchemas, preloadAll]);
|
|
206
|
+
React6.useEffect(() => {
|
|
207
|
+
if (!preloadAll) return;
|
|
208
|
+
if (schemas.length === 0) {
|
|
209
|
+
setLoading(false);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
let cancelled = false;
|
|
213
|
+
const pending = schemas.filter((s) => !loadedSchemas.has(s.id));
|
|
214
|
+
if (pending.length === 0) {
|
|
215
|
+
setLoading(false);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
setLoading(true);
|
|
219
|
+
setLoadStates((prev) => {
|
|
220
|
+
const next = new Map(prev);
|
|
221
|
+
for (const s of pending) next.set(s.id, { loading: true, error: null });
|
|
222
|
+
return next;
|
|
223
|
+
});
|
|
224
|
+
Promise.allSettled(
|
|
225
|
+
pending.map(
|
|
226
|
+
(s) => fetchSchema(s.url).then((schema) => ({ id: s.id, name: s.name, schema }))
|
|
227
|
+
)
|
|
228
|
+
).then((results) => {
|
|
229
|
+
if (cancelled) return;
|
|
230
|
+
setLoadedSchemas((prev) => {
|
|
231
|
+
const next = new Map(prev);
|
|
232
|
+
for (const r of results) {
|
|
233
|
+
if (r.status === "fulfilled") {
|
|
234
|
+
next.set(r.value.id, r.value.schema);
|
|
235
|
+
consola__default.default.success(`Schema loaded: ${r.value.name}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return next;
|
|
239
|
+
});
|
|
240
|
+
setLoadStates((prev) => {
|
|
241
|
+
const next = new Map(prev);
|
|
242
|
+
results.forEach((r, i) => {
|
|
243
|
+
const src = pending[i];
|
|
244
|
+
if (r.status === "fulfilled") {
|
|
245
|
+
next.set(src.id, { loading: false, error: null });
|
|
246
|
+
} else {
|
|
247
|
+
const msg = r.reason instanceof Error ? r.reason.message : "Failed to load schema";
|
|
248
|
+
consola__default.default.error(`Error loading schema from ${src.url}:`, r.reason);
|
|
249
|
+
next.set(src.id, { loading: false, error: msg });
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
return next;
|
|
253
|
+
});
|
|
254
|
+
setLoading(false);
|
|
255
|
+
});
|
|
256
|
+
return () => {
|
|
257
|
+
cancelled = true;
|
|
258
|
+
};
|
|
259
|
+
}, [preloadAll, schemas, loadedSchemas]);
|
|
260
|
+
const schemasData = React6.useMemo(() => {
|
|
261
|
+
if (!preloadAll) return [];
|
|
262
|
+
return schemas.map((src) => {
|
|
263
|
+
const raw = loadedSchemas.get(src.id) ?? null;
|
|
264
|
+
const deref = raw ? chunkIULI4XII_cjs.dereferenceSchema(raw) : null;
|
|
265
|
+
const resolved = chunkIULI4XII_cjs.resolveBaseUrl({
|
|
266
|
+
schemaSource: src.baseUrl,
|
|
267
|
+
config: configBaseUrl,
|
|
268
|
+
fromServers: raw?.servers?.[0]?.url
|
|
269
|
+
});
|
|
270
|
+
const info = raw?.info ? {
|
|
271
|
+
title: raw.info.title,
|
|
272
|
+
version: raw.info.version,
|
|
273
|
+
description: raw.info.description,
|
|
274
|
+
servers: raw.servers
|
|
275
|
+
} : null;
|
|
276
|
+
const eps = deref ? extractEndpoints(deref, resolved, src.id) : [];
|
|
277
|
+
const state = loadStates.get(src.id) ?? { loading: !raw, error: null };
|
|
278
|
+
return {
|
|
279
|
+
source: src,
|
|
280
|
+
info,
|
|
281
|
+
rawSchema: raw,
|
|
282
|
+
endpoints: eps,
|
|
283
|
+
resolvedBaseUrl: resolved || void 0,
|
|
284
|
+
loading: state.loading,
|
|
285
|
+
error: state.error
|
|
286
|
+
};
|
|
287
|
+
});
|
|
288
|
+
}, [preloadAll, schemas, loadedSchemas, loadStates, configBaseUrl]);
|
|
201
289
|
const setCurrentSchema = React6.useCallback((schemaId) => {
|
|
202
290
|
setCurrentSchemaId(schemaId);
|
|
203
291
|
}, []);
|
|
@@ -234,10 +322,75 @@ function useOpenApiSchema({
|
|
|
234
322
|
// convention from the resolver into undefined at the API boundary.
|
|
235
323
|
resolvedBaseUrl: resolvedBaseUrl || void 0,
|
|
236
324
|
setCurrentSchema,
|
|
237
|
-
refresh
|
|
325
|
+
refresh,
|
|
326
|
+
schemasData
|
|
238
327
|
};
|
|
239
328
|
}
|
|
240
329
|
chunkWGEGR3DF_cjs.__name(useOpenApiSchema, "useOpenApiSchema");
|
|
330
|
+
function parseDocsHash(hash) {
|
|
331
|
+
const raw = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
332
|
+
if (!raw) return { schemaId: null, anchor: null };
|
|
333
|
+
const [schemaId = null, ...rest] = raw.split("/");
|
|
334
|
+
const anchor = rest.length > 0 ? rest.join("/") : null;
|
|
335
|
+
return {
|
|
336
|
+
schemaId: schemaId || null,
|
|
337
|
+
anchor: anchor || null
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
chunkWGEGR3DF_cjs.__name(parseDocsHash, "parseDocsHash");
|
|
341
|
+
function buildDocsHash(schemaId, anchor) {
|
|
342
|
+
if (!schemaId && !anchor) return "";
|
|
343
|
+
if (schemaId && anchor) return `#${schemaId}/${anchor}`;
|
|
344
|
+
if (schemaId) return `#${schemaId}`;
|
|
345
|
+
return anchor ? `#${anchor}` : "";
|
|
346
|
+
}
|
|
347
|
+
chunkWGEGR3DF_cjs.__name(buildDocsHash, "buildDocsHash");
|
|
348
|
+
function useDocsUrlSync({
|
|
349
|
+
enabled,
|
|
350
|
+
currentSchemaId,
|
|
351
|
+
activeAnchor,
|
|
352
|
+
onHashTarget
|
|
353
|
+
}) {
|
|
354
|
+
const primedRef = React6.useRef(false);
|
|
355
|
+
const onHashTargetRef = React6.useRef(onHashTarget);
|
|
356
|
+
React6.useEffect(() => {
|
|
357
|
+
onHashTargetRef.current = onHashTarget;
|
|
358
|
+
}, [onHashTarget]);
|
|
359
|
+
React6.useEffect(() => {
|
|
360
|
+
if (!enabled || typeof window === "undefined") return;
|
|
361
|
+
const apply = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
362
|
+
onHashTargetRef.current(parseDocsHash(window.location.hash));
|
|
363
|
+
}, "apply");
|
|
364
|
+
apply();
|
|
365
|
+
primedRef.current = true;
|
|
366
|
+
window.addEventListener("hashchange", apply);
|
|
367
|
+
window.addEventListener("popstate", apply);
|
|
368
|
+
return () => {
|
|
369
|
+
window.removeEventListener("hashchange", apply);
|
|
370
|
+
window.removeEventListener("popstate", apply);
|
|
371
|
+
};
|
|
372
|
+
}, [enabled]);
|
|
373
|
+
React6.useEffect(() => {
|
|
374
|
+
if (!enabled || typeof window === "undefined") return;
|
|
375
|
+
if (!primedRef.current) return;
|
|
376
|
+
const next = buildDocsHash(currentSchemaId, activeAnchor);
|
|
377
|
+
const current = window.location.hash;
|
|
378
|
+
if (next === current) return;
|
|
379
|
+
const url = next ? `${window.location.pathname}${window.location.search}${next}` : `${window.location.pathname}${window.location.search}`;
|
|
380
|
+
window.history.replaceState(window.history.state, "", url);
|
|
381
|
+
}, [enabled, currentSchemaId, activeAnchor]);
|
|
382
|
+
const pushTarget = React6.useCallback(
|
|
383
|
+
(schemaId, anchor) => {
|
|
384
|
+
if (!enabled || typeof window === "undefined") return;
|
|
385
|
+
const next = buildDocsHash(schemaId, anchor);
|
|
386
|
+
const url = next ? `${window.location.pathname}${window.location.search}${next}` : `${window.location.pathname}${window.location.search}`;
|
|
387
|
+
window.history.pushState(window.history.state, "", url);
|
|
388
|
+
},
|
|
389
|
+
[enabled]
|
|
390
|
+
);
|
|
391
|
+
return { pushTarget };
|
|
392
|
+
}
|
|
393
|
+
chunkWGEGR3DF_cjs.__name(useDocsUrlSync, "useDocsUrlSync");
|
|
241
394
|
var EMPTY_DRAFT = { parameters: {}, requestBody: "" };
|
|
242
395
|
function storageKey(schemaId, ep) {
|
|
243
396
|
if (!schemaId || !ep) return null;
|
|
@@ -368,6 +521,18 @@ function EndpointDraftSync({ schemaId }) {
|
|
|
368
521
|
return null;
|
|
369
522
|
}
|
|
370
523
|
chunkWGEGR3DF_cjs.__name(EndpointDraftSync, "EndpointDraftSync");
|
|
524
|
+
|
|
525
|
+
// src/tools/OpenapiViewer/components/DocsLayout/anchor.ts
|
|
526
|
+
function endpointAnchor(ep, schemaId) {
|
|
527
|
+
const slug = ep.path.replace(/^https?:\/\/[^/]+/, "").replace(/[{}]/g, "").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
528
|
+
const schemaSlug = schemaId ? `${slugifySchemaId(schemaId)}-` : "";
|
|
529
|
+
return `ep-${schemaSlug}${ep.method.toLowerCase()}-${slug}`;
|
|
530
|
+
}
|
|
531
|
+
chunkWGEGR3DF_cjs.__name(endpointAnchor, "endpointAnchor");
|
|
532
|
+
function slugifySchemaId(id) {
|
|
533
|
+
return id.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
534
|
+
}
|
|
535
|
+
chunkWGEGR3DF_cjs.__name(slugifySchemaId, "slugifySchemaId");
|
|
371
536
|
var METHOD_STYLES = {
|
|
372
537
|
GET: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/25",
|
|
373
538
|
POST: "bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/25",
|
|
@@ -463,13 +628,6 @@ function CollapsibleSection({
|
|
|
463
628
|
}
|
|
464
629
|
chunkWGEGR3DF_cjs.__name(CollapsibleSection, "CollapsibleSection");
|
|
465
630
|
|
|
466
|
-
// src/tools/OpenapiViewer/components/DocsLayout/anchor.ts
|
|
467
|
-
function endpointAnchor(ep) {
|
|
468
|
-
const slug = ep.path.replace(/^https?:\/\/[^/]+/, "").replace(/[{}]/g, "").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
469
|
-
return `ep-${ep.method.toLowerCase()}-${slug}`;
|
|
470
|
-
}
|
|
471
|
-
chunkWGEGR3DF_cjs.__name(endpointAnchor, "endpointAnchor");
|
|
472
|
-
|
|
473
631
|
// src/tools/OpenapiViewer/components/DocsLayout/sidebarLabel.ts
|
|
474
632
|
function longestCommonPrefix(paths) {
|
|
475
633
|
if (paths.length === 0) return "";
|
|
@@ -510,6 +668,8 @@ function sidebarTooltip(ep) {
|
|
|
510
668
|
return `${ep.method} ${relativePath2(ep.path)}`;
|
|
511
669
|
}
|
|
512
670
|
chunkWGEGR3DF_cjs.__name(sidebarTooltip, "sidebarTooltip");
|
|
671
|
+
|
|
672
|
+
// src/tools/OpenapiViewer/components/DocsLayout/grouping.ts
|
|
513
673
|
var METHOD_ORDER = {
|
|
514
674
|
GET: 0,
|
|
515
675
|
POST: 1,
|
|
@@ -517,138 +677,25 @@ var METHOD_ORDER = {
|
|
|
517
677
|
PATCH: 3,
|
|
518
678
|
DELETE: 4
|
|
519
679
|
};
|
|
680
|
+
var methodRank = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((ep) => METHOD_ORDER[ep.method] ?? 99, "methodRank");
|
|
520
681
|
function groupEndpoints(list) {
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
const arr = map.get(ep.category) ?? [];
|
|
524
|
-
arr.push(ep);
|
|
525
|
-
map.set(ep.category, arr);
|
|
526
|
-
}
|
|
527
|
-
const groups = Array.from(map.entries()).map(([category, endpoints]) => ({
|
|
682
|
+
const byCategory = lodashEs.groupBy(list, "category");
|
|
683
|
+
const all = Object.entries(byCategory).map(([category, endpoints]) => ({
|
|
528
684
|
category,
|
|
529
|
-
endpoints:
|
|
530
|
-
const byPath = a.path.localeCompare(b.path);
|
|
531
|
-
if (byPath !== 0) return byPath;
|
|
532
|
-
return (METHOD_ORDER[a.method] ?? 99) - (METHOD_ORDER[b.method] ?? 99);
|
|
533
|
-
}),
|
|
685
|
+
endpoints: lodashEs.orderBy(endpoints, ["path", methodRank], ["asc", "asc"]),
|
|
534
686
|
commonPrefix: longestCommonPrefix(endpoints.map((e) => e.path))
|
|
535
687
|
}));
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
if (b.category === "Other") return -1;
|
|
539
|
-
return a.category.localeCompare(b.category);
|
|
540
|
-
});
|
|
541
|
-
return groups;
|
|
688
|
+
const [other, named] = lodashEs.partition(all, (g) => g.category === "Other");
|
|
689
|
+
return [...lodashEs.sortBy(named, (g) => g.category.toLowerCase()), ...other];
|
|
542
690
|
}
|
|
543
691
|
chunkWGEGR3DF_cjs.__name(groupEndpoints, "groupEndpoints");
|
|
544
|
-
function
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
onSchemaChange,
|
|
550
|
-
activeEndpointId,
|
|
551
|
-
selectedVersion,
|
|
552
|
-
onNavigate
|
|
553
|
-
}) {
|
|
554
|
-
const [search, setSearch] = React6.useState("");
|
|
555
|
-
const [debounced, setDebounced] = React6.useState("");
|
|
556
|
-
React6.useEffect(() => {
|
|
557
|
-
const id = setTimeout(() => setDebounced(search), 120);
|
|
558
|
-
return () => clearTimeout(id);
|
|
559
|
-
}, [search]);
|
|
560
|
-
const filteredGroups = React6.useMemo(() => {
|
|
561
|
-
let list = chunkIULI4XII_cjs.deduplicateEndpoints(endpoints, selectedVersion);
|
|
562
|
-
if (debounced) {
|
|
563
|
-
const q = debounced.toLowerCase();
|
|
564
|
-
list = list.filter(
|
|
565
|
-
(e) => e.summary.toLowerCase().includes(q) || e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.path.toLowerCase().includes(q)
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
return groupEndpoints(list);
|
|
569
|
-
}, [endpoints, debounced, selectedVersion]);
|
|
570
|
-
const schemaOptions = React6.useMemo(
|
|
571
|
-
() => schemas.map((s) => ({ value: s.id, label: s.name })),
|
|
572
|
-
[schemas]
|
|
573
|
-
);
|
|
574
|
-
const hasMultipleSchemas = schemas.length > 1;
|
|
575
|
-
const apiTitle = info?.title ?? "API Reference";
|
|
576
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "flex flex-col min-h-0 border-r bg-muted/10", children: [
|
|
577
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-4 h-12 flex items-center gap-2", children: [
|
|
578
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[13px] font-semibold text-foreground truncate", children: apiTitle }),
|
|
579
|
-
info?.version && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-[10px] text-muted-foreground/70 shrink-0", children: [
|
|
580
|
-
"v",
|
|
581
|
-
info.version
|
|
582
|
-
] })
|
|
583
|
-
] }),
|
|
584
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 border-b px-3 py-3 space-y-2", children: [
|
|
585
|
-
hasMultipleSchemas && /* @__PURE__ */ jsxRuntime.jsx(
|
|
586
|
-
components.Combobox,
|
|
587
|
-
{
|
|
588
|
-
options: schemaOptions,
|
|
589
|
-
value: currentSchemaId ?? "",
|
|
590
|
-
onValueChange: (id) => id && onSchemaChange(id),
|
|
591
|
-
placeholder: "Select API",
|
|
592
|
-
searchPlaceholder: "Search APIs\u2026",
|
|
593
|
-
emptyText: "No APIs found",
|
|
594
|
-
className: "w-full h-8 text-xs"
|
|
595
|
-
}
|
|
596
|
-
),
|
|
597
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
598
|
-
/* @__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" }),
|
|
599
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
600
|
-
components.Input,
|
|
601
|
-
{
|
|
602
|
-
placeholder: "Search endpoints\u2026",
|
|
603
|
-
value: search,
|
|
604
|
-
onChange: (e) => setSearch(e.target.value),
|
|
605
|
-
className: "pl-8 h-8 text-xs"
|
|
606
|
-
}
|
|
607
|
-
)
|
|
608
|
-
] })
|
|
609
|
-
] }),
|
|
610
|
-
/* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { children: filteredGroups.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: debounced ? `No endpoints match "${debounced}"` : "No endpoints in this schema" }) : /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-2", children: filteredGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 last:mb-2", children: [
|
|
611
|
-
/* @__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: group.category }),
|
|
612
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: group.endpoints.map((ep) => {
|
|
613
|
-
const anchor = endpointAnchor(ep);
|
|
614
|
-
const isActive = activeEndpointId === anchor;
|
|
615
|
-
const label = sidebarLabel(ep, group.commonPrefix);
|
|
616
|
-
const tooltip = sidebarTooltip(ep);
|
|
617
|
-
const useMono = !ep.summary;
|
|
618
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(components.Tooltip, { delayDuration: 350, children: [
|
|
619
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
620
|
-
"button",
|
|
621
|
-
{
|
|
622
|
-
onClick: () => onNavigate(anchor),
|
|
623
|
-
"aria-current": isActive ? "location" : void 0,
|
|
624
|
-
className: lib.cn(
|
|
625
|
-
"relative group w-full text-left flex items-center gap-2 pl-4 pr-3 py-1.5 transition-colors",
|
|
626
|
-
isActive ? "bg-primary/10 text-foreground" : "hover:bg-muted/40 text-foreground/75 hover:text-foreground"
|
|
627
|
-
),
|
|
628
|
-
children: [
|
|
629
|
-
isActive && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-0 top-1 bottom-1 w-0.5 rounded-r bg-primary" }),
|
|
630
|
-
/* @__PURE__ */ jsxRuntime.jsx(MethodBadge, { method: ep.method }),
|
|
631
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
632
|
-
"span",
|
|
633
|
-
{
|
|
634
|
-
className: lib.cn(
|
|
635
|
-
"truncate leading-tight flex-1 min-w-0",
|
|
636
|
-
useMono ? "font-mono text-[11px]" : "text-[12px]",
|
|
637
|
-
isActive && "text-foreground font-medium"
|
|
638
|
-
),
|
|
639
|
-
children: label
|
|
640
|
-
}
|
|
641
|
-
)
|
|
642
|
-
]
|
|
643
|
-
}
|
|
644
|
-
) }),
|
|
645
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.TooltipContent, { side: "right", align: "center", className: "font-mono text-[11px]", children: tooltip })
|
|
646
|
-
] }, `${ep.method}-${ep.path}`);
|
|
647
|
-
}) })
|
|
648
|
-
] }, group.category)) }) })
|
|
649
|
-
] });
|
|
692
|
+
function buildSchemaSections(sources, endpointsBySchema) {
|
|
693
|
+
return sources.map((source) => ({
|
|
694
|
+
source,
|
|
695
|
+
groups: groupEndpoints(endpointsBySchema[source.id] ?? [])
|
|
696
|
+
}));
|
|
650
697
|
}
|
|
651
|
-
chunkWGEGR3DF_cjs.__name(
|
|
698
|
+
chunkWGEGR3DF_cjs.__name(buildSchemaSections, "buildSchemaSections");
|
|
652
699
|
var FLAVOUR_LABELS = {
|
|
653
700
|
markdown: {
|
|
654
701
|
title: "Markdown for LLM",
|
|
@@ -663,7 +710,7 @@ var FLAVOUR_LABELS = {
|
|
|
663
710
|
hint: "Full OpenAPI document with $refs."
|
|
664
711
|
}
|
|
665
712
|
};
|
|
666
|
-
function SchemaCopyMenu({ schema, endpoints, baseUrl }) {
|
|
713
|
+
function SchemaCopyMenu({ schema, endpoints, baseUrl, variant = "button" }) {
|
|
667
714
|
const [sizeCache, setSizeCache] = React6.useState({});
|
|
668
715
|
const [justCopied, setJustCopied] = React6.useState(null);
|
|
669
716
|
const [open, setOpen] = React6.useState(false);
|
|
@@ -681,20 +728,36 @@ function SchemaCopyMenu({ schema, endpoints, baseUrl }) {
|
|
|
681
728
|
async (flavour) => {
|
|
682
729
|
if (!isReady) return;
|
|
683
730
|
const text = build(flavour);
|
|
731
|
+
const label = FLAVOUR_LABELS[flavour].title;
|
|
684
732
|
try {
|
|
685
733
|
await navigator.clipboard.writeText(text);
|
|
686
|
-
|
|
734
|
+
const size = chunkIULI4XII_cjs.formatBytes(text);
|
|
735
|
+
setSizeCache((prev) => ({ ...prev, [flavour]: size }));
|
|
687
736
|
setJustCopied(flavour);
|
|
688
737
|
setTimeout(() => setJustCopied(null), 1500);
|
|
689
738
|
setOpen(false);
|
|
690
|
-
|
|
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 });
|
|
691
743
|
}
|
|
692
744
|
},
|
|
693
745
|
[build, isReady]
|
|
694
746
|
);
|
|
695
747
|
const flavours = React6.useMemo(() => ["markdown", "compact", "raw"], []);
|
|
696
748
|
return /* @__PURE__ */ jsxRuntime.jsxs(components.DropdownMenu, { open, onOpenChange: setOpen, children: [
|
|
697
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.
|
|
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: [
|
|
698
761
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3 w-3" }),
|
|
699
762
|
"Copy for AI",
|
|
700
763
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3 w-3 opacity-60" })
|
|
@@ -732,6 +795,296 @@ function SchemaCopyMenu({ schema, endpoints, baseUrl }) {
|
|
|
732
795
|
] });
|
|
733
796
|
}
|
|
734
797
|
chunkWGEGR3DF_cjs.__name(SchemaCopyMenu, "SchemaCopyMenu");
|
|
798
|
+
var METHOD_FILTERS = ["ALL", "GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
799
|
+
function filterEndpoints(list, query, method) {
|
|
800
|
+
let out = list;
|
|
801
|
+
if (method !== "ALL") {
|
|
802
|
+
out = out.filter((e) => e.method === method);
|
|
803
|
+
}
|
|
804
|
+
if (query) {
|
|
805
|
+
const q = query.toLowerCase();
|
|
806
|
+
out = out.filter(
|
|
807
|
+
(e) => e.summary.toLowerCase().includes(q) || e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.path.toLowerCase().includes(q)
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
return out;
|
|
811
|
+
}
|
|
812
|
+
chunkWGEGR3DF_cjs.__name(filterEndpoints, "filterEndpoints");
|
|
813
|
+
function buildCategory(group, activeEndpointId, schemaId, keyPrefix) {
|
|
814
|
+
const rows = group.endpoints.map((ep) => {
|
|
815
|
+
const anchor = endpointAnchor(ep, schemaId ?? ep.schemaId ?? null);
|
|
816
|
+
return {
|
|
817
|
+
key: `${ep.method}-${ep.path}`,
|
|
818
|
+
anchor,
|
|
819
|
+
schemaId: schemaId ?? ep.schemaId ?? null,
|
|
820
|
+
label: sidebarLabel(ep, group.commonPrefix),
|
|
821
|
+
tooltip: sidebarTooltip(ep),
|
|
822
|
+
method: ep.method,
|
|
823
|
+
useMono: !ep.summary,
|
|
824
|
+
isActive: activeEndpointId === anchor
|
|
825
|
+
};
|
|
826
|
+
});
|
|
827
|
+
return {
|
|
828
|
+
key: `${keyPrefix}${group.category}`,
|
|
829
|
+
category: group.category,
|
|
830
|
+
rows
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
chunkWGEGR3DF_cjs.__name(buildCategory, "buildCategory");
|
|
834
|
+
var emptyTextFor = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((query, method, defaultText) => {
|
|
835
|
+
if (query && method !== "ALL") return `No ${method} endpoints match "${query}"`;
|
|
836
|
+
if (query) return `No endpoints match "${query}"`;
|
|
837
|
+
if (method !== "ALL") return `No ${method} endpoints`;
|
|
838
|
+
return defaultText;
|
|
839
|
+
}, "emptyTextFor");
|
|
840
|
+
function buildFlatVM(endpoints, selectedVersion, query, method, activeEndpointId) {
|
|
841
|
+
const filtered = filterEndpoints(chunkIULI4XII_cjs.deduplicateEndpoints(endpoints, selectedVersion), query, method);
|
|
842
|
+
const groups = groupEndpoints(filtered);
|
|
843
|
+
return {
|
|
844
|
+
kind: "flat",
|
|
845
|
+
categories: groups.map((g) => buildCategory(g, activeEndpointId, null, "")),
|
|
846
|
+
emptyText: emptyTextFor(query, method, "No endpoints in this schema")
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
chunkWGEGR3DF_cjs.__name(buildFlatVM, "buildFlatVM");
|
|
850
|
+
function buildSectionsVM(schemas, endpointsBySchema, selectedVersion, query, method, activeEndpointId) {
|
|
851
|
+
const filteredMap = {};
|
|
852
|
+
for (const src of schemas) {
|
|
853
|
+
const raw = endpointsBySchema[src.id] ?? [];
|
|
854
|
+
filteredMap[src.id] = filterEndpoints(chunkIULI4XII_cjs.deduplicateEndpoints(raw, selectedVersion), query, method);
|
|
855
|
+
}
|
|
856
|
+
const rawSections = buildSchemaSections(schemas, filteredMap);
|
|
857
|
+
const sections = rawSections.filter((s) => s.groups.length > 0).map((s) => ({
|
|
858
|
+
sourceId: s.source.id,
|
|
859
|
+
sourceName: s.source.name,
|
|
860
|
+
categories: s.groups.map((g) => buildCategory(g, activeEndpointId, s.source.id, `${s.source.id}-`))
|
|
861
|
+
}));
|
|
862
|
+
return {
|
|
863
|
+
kind: "sections",
|
|
864
|
+
sections,
|
|
865
|
+
emptyText: emptyTextFor(query, method, "No endpoints in any schema")
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
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
|
|
973
|
+
}) {
|
|
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(
|
|
977
|
+
"button",
|
|
978
|
+
{
|
|
979
|
+
type: "button",
|
|
980
|
+
onClick: () => onChange(m),
|
|
981
|
+
"aria-pressed": active,
|
|
982
|
+
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"
|
|
985
|
+
),
|
|
986
|
+
children: m
|
|
987
|
+
},
|
|
988
|
+
m
|
|
989
|
+
);
|
|
990
|
+
}) });
|
|
991
|
+
}
|
|
992
|
+
chunkWGEGR3DF_cjs.__name(MethodChips, "MethodChips");
|
|
993
|
+
function SidebarBody({ body, onNavigate }) {
|
|
994
|
+
if (body.kind === "flat") {
|
|
995
|
+
if (body.categories.length === 0) {
|
|
996
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: body.emptyText });
|
|
997
|
+
}
|
|
998
|
+
return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "py-2", children: body.categories.map((cat) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBlock, { category: cat, onNavigate }, cat.key)) });
|
|
999
|
+
}
|
|
1000
|
+
if (body.sections.length === 0) {
|
|
1001
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 px-4 text-center text-xs text-muted-foreground", children: body.emptyText });
|
|
1002
|
+
}
|
|
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)) });
|
|
1007
|
+
}
|
|
1008
|
+
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(
|
|
1024
|
+
"button",
|
|
1025
|
+
{
|
|
1026
|
+
onClick: () => onNavigate(row.anchor, row.schemaId),
|
|
1027
|
+
"aria-current": row.isActive ? "location" : void 0,
|
|
1028
|
+
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"
|
|
1031
|
+
),
|
|
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
|
+
]
|
|
1047
|
+
}
|
|
1048
|
+
) }),
|
|
1049
|
+
/* @__PURE__ */ jsxRuntime.jsx(components.TooltipContent, { side: "right", align: "center", className: "font-mono text-[11px]", children: row.tooltip })
|
|
1050
|
+
] });
|
|
1051
|
+
}, "EndpointRow"));
|
|
1052
|
+
|
|
1053
|
+
// src/tools/OpenapiViewer/utils/scrollParent.ts
|
|
1054
|
+
function getScrollParent(el) {
|
|
1055
|
+
if (typeof window === "undefined") return null;
|
|
1056
|
+
if (!el) return window;
|
|
1057
|
+
let cur = el.parentElement;
|
|
1058
|
+
while (cur && cur !== document.body && cur !== document.documentElement) {
|
|
1059
|
+
const style = getComputedStyle(cur);
|
|
1060
|
+
const overflowY = style.overflowY;
|
|
1061
|
+
const canScroll = (overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay") && cur.scrollHeight > cur.clientHeight;
|
|
1062
|
+
if (canScroll) return cur;
|
|
1063
|
+
cur = cur.parentElement;
|
|
1064
|
+
}
|
|
1065
|
+
return window;
|
|
1066
|
+
}
|
|
1067
|
+
chunkWGEGR3DF_cjs.__name(getScrollParent, "getScrollParent");
|
|
1068
|
+
function getScrollTop(target) {
|
|
1069
|
+
return target === window ? window.scrollY : target.scrollTop;
|
|
1070
|
+
}
|
|
1071
|
+
chunkWGEGR3DF_cjs.__name(getScrollTop, "getScrollTop");
|
|
1072
|
+
function getViewportHeight(target) {
|
|
1073
|
+
return target === window ? window.innerHeight : target.clientHeight;
|
|
1074
|
+
}
|
|
1075
|
+
chunkWGEGR3DF_cjs.__name(getViewportHeight, "getViewportHeight");
|
|
1076
|
+
function getTargetTop(target) {
|
|
1077
|
+
return target === window ? 0 : target.getBoundingClientRect().top;
|
|
1078
|
+
}
|
|
1079
|
+
chunkWGEGR3DF_cjs.__name(getTargetTop, "getTargetTop");
|
|
1080
|
+
function scrollTargetTo(target, top) {
|
|
1081
|
+
if (target === window) {
|
|
1082
|
+
window.scrollTo({ top, behavior: "smooth" });
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
target.scrollTop = top;
|
|
1086
|
+
}
|
|
1087
|
+
chunkWGEGR3DF_cjs.__name(scrollTargetTo, "scrollTargetTo");
|
|
735
1088
|
function ApiIntroSection({ info, schema, endpoints, resolvedBaseUrl }) {
|
|
736
1089
|
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pb-10 mb-10 border-b", children: [
|
|
737
1090
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 flex-wrap", children: [
|
|
@@ -835,8 +1188,9 @@ function schemaToFields(schema, prefix = "", depth = 0) {
|
|
|
835
1188
|
return rows;
|
|
836
1189
|
}
|
|
837
1190
|
chunkWGEGR3DF_cjs.__name(schemaToFields, "schemaToFields");
|
|
838
|
-
function EndpointDoc({ endpoint, isLoadedInPlayground, onTryIt }) {
|
|
839
|
-
const
|
|
1191
|
+
function EndpointDoc({ endpoint, isLoadedInPlayground, onTryIt, schemaId }) {
|
|
1192
|
+
const scopedSchemaId = schemaId ?? endpoint.schemaId ?? null;
|
|
1193
|
+
const anchor = endpointAnchor(endpoint, scopedSchemaId);
|
|
840
1194
|
const pathParams = endpoint.parameters?.filter((p) => endpoint.path.includes(`{${p.name}}`)) ?? [];
|
|
841
1195
|
const queryParams = endpoint.parameters?.filter((p) => !endpoint.path.includes(`{${p.name}}`)) ?? [];
|
|
842
1196
|
const [copied, setCopied] = React6.useState(false);
|
|
@@ -854,6 +1208,7 @@ function EndpointDoc({ endpoint, isLoadedInPlayground, onTryIt }) {
|
|
|
854
1208
|
{
|
|
855
1209
|
id: anchor,
|
|
856
1210
|
"data-endpoint-anchor": anchor,
|
|
1211
|
+
"data-schema-id": scopedSchemaId ?? "",
|
|
857
1212
|
className: "scroll-mt-24 py-10 first:pt-0",
|
|
858
1213
|
children: [
|
|
859
1214
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "space-y-4", children: [
|
|
@@ -1014,52 +1369,103 @@ function StatusTag({ code }) {
|
|
|
1014
1369
|
), children: code });
|
|
1015
1370
|
}
|
|
1016
1371
|
chunkWGEGR3DF_cjs.__name(StatusTag, "StatusTag");
|
|
1017
|
-
var
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1372
|
+
var readNavbarOffset = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
1373
|
+
if (typeof document === "undefined") return 0;
|
|
1374
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue("--navbar-height");
|
|
1375
|
+
const parsed = parseInt(raw || "", 10);
|
|
1376
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
1377
|
+
}, "readNavbarOffset");
|
|
1378
|
+
var isSameEndpoint = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((a, b) => a !== null && a.method === b.method && a.path === b.path, "isSameEndpoint");
|
|
1379
|
+
function buildEndpointRow(ep, loadedEndpoint, schemaId) {
|
|
1380
|
+
const keySchema = schemaId ? `${schemaId}-` : "";
|
|
1381
|
+
return {
|
|
1382
|
+
key: `${keySchema}${ep.method}-${ep.path}`,
|
|
1383
|
+
endpoint: ep,
|
|
1384
|
+
isLoaded: isSameEndpoint(loadedEndpoint, ep),
|
|
1385
|
+
schemaId
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
chunkWGEGR3DF_cjs.__name(buildEndpointRow, "buildEndpointRow");
|
|
1389
|
+
function buildSchemaSectionVM(entry, selectedVersion, loadedEndpoint) {
|
|
1390
|
+
const title = entry.info?.title ?? entry.source.name;
|
|
1391
|
+
const version = entry.info?.version ?? null;
|
|
1392
|
+
const description = entry.info?.description ?? null;
|
|
1393
|
+
let state;
|
|
1394
|
+
if (entry.loading) {
|
|
1395
|
+
state = { kind: "loading" };
|
|
1396
|
+
} else if (entry.error) {
|
|
1397
|
+
state = { kind: "error", message: entry.error };
|
|
1398
|
+
} else {
|
|
1399
|
+
const visible = chunkIULI4XII_cjs.deduplicateEndpoints(entry.endpoints, selectedVersion);
|
|
1400
|
+
state = visible.length === 0 ? { kind: "empty" } : {
|
|
1401
|
+
kind: "ready",
|
|
1402
|
+
rows: visible.map((ep) => buildEndpointRow(ep, loadedEndpoint, entry.source.id))
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
return {
|
|
1406
|
+
schemaId: entry.source.id,
|
|
1407
|
+
title,
|
|
1408
|
+
version,
|
|
1409
|
+
description,
|
|
1410
|
+
state,
|
|
1411
|
+
rawSchema: entry.rawSchema,
|
|
1412
|
+
baseUrl: entry.resolvedBaseUrl,
|
|
1413
|
+
allEndpoints: entry.endpoints
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
chunkWGEGR3DF_cjs.__name(buildSchemaSectionVM, "buildSchemaSectionVM");
|
|
1417
|
+
var DocsView = React6__default.default.forwardRef(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function DocsView2(props, ref) {
|
|
1027
1418
|
const scrollRef = React6.useRef(null);
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const el = root.querySelector(`[data-endpoint-anchor="${anchor}"]`);
|
|
1036
|
-
if (!el) return;
|
|
1037
|
-
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
1419
|
+
const scrollTargetRef = React6.useRef(null);
|
|
1420
|
+
const { onActiveChange } = props;
|
|
1421
|
+
const ensureScrollTarget = React6.useCallback(() => {
|
|
1422
|
+
if (scrollTargetRef.current) return scrollTargetRef.current;
|
|
1423
|
+
if (!scrollRef.current) return null;
|
|
1424
|
+
scrollTargetRef.current = getScrollParent(scrollRef.current);
|
|
1425
|
+
return scrollTargetRef.current;
|
|
1038
1426
|
}, []);
|
|
1427
|
+
const scrollToAnchor = React6.useCallback(
|
|
1428
|
+
(anchor) => {
|
|
1429
|
+
const root = scrollRef.current;
|
|
1430
|
+
if (!root) return;
|
|
1431
|
+
const el = root.querySelector(`[data-endpoint-anchor="${anchor}"]`);
|
|
1432
|
+
if (!el) return;
|
|
1433
|
+
const target = ensureScrollTarget();
|
|
1434
|
+
if (!target) return;
|
|
1435
|
+
const navbar = readNavbarOffset();
|
|
1436
|
+
const top = el.getBoundingClientRect().top - getTargetTop(target) + getScrollTop(target) - navbar - 8;
|
|
1437
|
+
scrollTargetTo(target, top);
|
|
1438
|
+
},
|
|
1439
|
+
[ensureScrollTarget]
|
|
1440
|
+
);
|
|
1039
1441
|
React6__default.default.useImperativeHandle(ref, () => ({ scrollToAnchor }), [scrollToAnchor]);
|
|
1040
1442
|
React6.useEffect(() => {
|
|
1041
1443
|
const root = scrollRef.current;
|
|
1042
1444
|
if (!root) return;
|
|
1445
|
+
const target = ensureScrollTarget();
|
|
1446
|
+
if (!target) return;
|
|
1043
1447
|
let rafId = 0;
|
|
1044
1448
|
let lastActive = null;
|
|
1045
1449
|
const compute = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
1046
1450
|
rafId = 0;
|
|
1047
1451
|
const sections = root.querySelectorAll("[data-endpoint-anchor]");
|
|
1048
1452
|
if (sections.length === 0) return;
|
|
1049
|
-
const
|
|
1050
|
-
const
|
|
1453
|
+
const navbar = readNavbarOffset();
|
|
1454
|
+
const viewportTop = getTargetTop(target);
|
|
1455
|
+
const threshold = viewportTop + navbar + getViewportHeight(target) * 0.25;
|
|
1051
1456
|
let active = null;
|
|
1052
1457
|
for (const s of Array.from(sections)) {
|
|
1053
1458
|
const top = s.getBoundingClientRect().top;
|
|
1054
1459
|
if (top <= threshold) {
|
|
1055
|
-
active = s
|
|
1460
|
+
active = s;
|
|
1056
1461
|
} else {
|
|
1057
1462
|
break;
|
|
1058
1463
|
}
|
|
1059
1464
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1465
|
+
const anchor = active?.dataset.endpointAnchor ?? null;
|
|
1466
|
+
if (anchor !== lastActive) {
|
|
1467
|
+
lastActive = anchor;
|
|
1468
|
+
onActiveChange(anchor, active?.dataset.schemaId || null);
|
|
1063
1469
|
}
|
|
1064
1470
|
}, "compute");
|
|
1065
1471
|
const onScroll = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
@@ -1067,13 +1473,39 @@ var DocsView = React6__default.default.forwardRef(/* @__PURE__ */ chunkWGEGR3DF_
|
|
|
1067
1473
|
rafId = requestAnimationFrame(compute);
|
|
1068
1474
|
}, "onScroll");
|
|
1069
1475
|
compute();
|
|
1070
|
-
|
|
1476
|
+
target.addEventListener("scroll", onScroll, { passive: true });
|
|
1477
|
+
window.addEventListener("resize", onScroll, { passive: true });
|
|
1071
1478
|
return () => {
|
|
1072
|
-
|
|
1479
|
+
target.removeEventListener("scroll", onScroll);
|
|
1480
|
+
window.removeEventListener("resize", onScroll);
|
|
1073
1481
|
if (rafId) cancelAnimationFrame(rafId);
|
|
1074
1482
|
};
|
|
1075
|
-
}, [
|
|
1076
|
-
|
|
1483
|
+
}, [onActiveChange, ensureScrollTarget, props]);
|
|
1484
|
+
if (props.grouping === "sections") {
|
|
1485
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SectionsBody, { scrollRef, ...props });
|
|
1486
|
+
}
|
|
1487
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectorBody, { scrollRef, ...props });
|
|
1488
|
+
}, "DocsView"));
|
|
1489
|
+
function SelectorBody({
|
|
1490
|
+
scrollRef,
|
|
1491
|
+
info,
|
|
1492
|
+
rawSchema,
|
|
1493
|
+
resolvedBaseUrl,
|
|
1494
|
+
endpoints,
|
|
1495
|
+
selectedVersion,
|
|
1496
|
+
loadedEndpoint,
|
|
1497
|
+
onTryEndpoint
|
|
1498
|
+
}) {
|
|
1499
|
+
const visibleEndpoints = React6.useMemo(
|
|
1500
|
+
() => chunkIULI4XII_cjs.deduplicateEndpoints(endpoints, selectedVersion),
|
|
1501
|
+
[endpoints, selectedVersion]
|
|
1502
|
+
);
|
|
1503
|
+
const rows = React6.useMemo(
|
|
1504
|
+
() => visibleEndpoints.map((ep) => buildEndpointRow(ep, loadedEndpoint, ep.schemaId ?? null)),
|
|
1505
|
+
[visibleEndpoints, loadedEndpoint]
|
|
1506
|
+
);
|
|
1507
|
+
const isEmpty = rows.length === 0;
|
|
1508
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-[860px] px-6 md:px-10 lg:px-14 py-12", children: [
|
|
1077
1509
|
info && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1078
1510
|
ApiIntroSection,
|
|
1079
1511
|
{
|
|
@@ -1083,20 +1515,96 @@ var DocsView = React6__default.default.forwardRef(/* @__PURE__ */ chunkWGEGR3DF_
|
|
|
1083
1515
|
resolvedBaseUrl
|
|
1084
1516
|
}
|
|
1085
1517
|
),
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1518
|
+
isEmpty ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-16 text-center text-sm text-muted-foreground", children: "No endpoints to display." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/60", children: rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1519
|
+
EndpointDoc,
|
|
1520
|
+
{
|
|
1521
|
+
endpoint: row.endpoint,
|
|
1522
|
+
isLoadedInPlayground: row.isLoaded,
|
|
1523
|
+
onTryIt: () => onTryEndpoint(row.endpoint),
|
|
1524
|
+
schemaId: row.schemaId
|
|
1525
|
+
},
|
|
1526
|
+
row.key
|
|
1527
|
+
)) })
|
|
1528
|
+
] }) });
|
|
1529
|
+
}
|
|
1530
|
+
chunkWGEGR3DF_cjs.__name(SelectorBody, "SelectorBody");
|
|
1531
|
+
function SectionsBody({
|
|
1532
|
+
scrollRef,
|
|
1533
|
+
schemasData,
|
|
1534
|
+
selectedVersion,
|
|
1535
|
+
loadedEndpoint,
|
|
1536
|
+
onTryEndpoint
|
|
1537
|
+
}) {
|
|
1538
|
+
const sections = React6.useMemo(
|
|
1539
|
+
() => schemasData.map((e) => buildSchemaSectionVM(e, selectedVersion, loadedEndpoint)),
|
|
1540
|
+
[schemasData, selectedVersion, loadedEndpoint]
|
|
1541
|
+
);
|
|
1542
|
+
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
|
+
}
|
|
1544
|
+
chunkWGEGR3DF_cjs.__name(SectionsBody, "SectionsBody");
|
|
1545
|
+
var SchemaSectionView = React6__default.default.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function SchemaSectionView2({
|
|
1546
|
+
section,
|
|
1547
|
+
onTryEndpoint
|
|
1548
|
+
}) {
|
|
1549
|
+
const canCopy = section.rawSchema !== null && section.allEndpoints.length > 0;
|
|
1550
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { "data-schema-anchor": section.schemaId, className: "scroll-mt-20", children: [
|
|
1551
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "mb-8 pb-4 border-b", children: [
|
|
1552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
1553
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-3 min-w-0", children: [
|
|
1554
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: section.title }),
|
|
1555
|
+
section.version && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-xs text-muted-foreground/70", children: [
|
|
1556
|
+
"v",
|
|
1557
|
+
section.version
|
|
1558
|
+
] })
|
|
1559
|
+
] }),
|
|
1560
|
+
canCopy && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1561
|
+
SchemaCopyMenu,
|
|
1562
|
+
{
|
|
1563
|
+
schema: section.rawSchema,
|
|
1564
|
+
endpoints: section.allEndpoints,
|
|
1565
|
+
baseUrl: section.baseUrl
|
|
1566
|
+
}
|
|
1567
|
+
)
|
|
1568
|
+
] }),
|
|
1569
|
+
section.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground whitespace-pre-wrap", children: section.description })
|
|
1570
|
+
] }),
|
|
1571
|
+
/* @__PURE__ */ jsxRuntime.jsx(SchemaSectionStateView, { section, onTryEndpoint })
|
|
1572
|
+
] });
|
|
1573
|
+
}, "SchemaSectionView"));
|
|
1574
|
+
function SchemaSectionStateView({
|
|
1575
|
+
section,
|
|
1576
|
+
onTryEndpoint
|
|
1577
|
+
}) {
|
|
1578
|
+
switch (section.state.kind) {
|
|
1579
|
+
case "loading":
|
|
1580
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-8 text-center text-sm text-muted-foreground", children: [
|
|
1581
|
+
"Loading ",
|
|
1582
|
+
section.title,
|
|
1583
|
+
"\u2026"
|
|
1584
|
+
] });
|
|
1585
|
+
case "error":
|
|
1586
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-8 text-center text-sm text-destructive", children: [
|
|
1587
|
+
"Failed to load ",
|
|
1588
|
+
section.title,
|
|
1589
|
+
": ",
|
|
1590
|
+
section.state.message
|
|
1591
|
+
] });
|
|
1592
|
+
case "empty":
|
|
1593
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground", children: "No endpoints in this schema." });
|
|
1594
|
+
case "ready":
|
|
1595
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/60", children: section.state.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1089
1596
|
EndpointDoc,
|
|
1090
1597
|
{
|
|
1091
|
-
endpoint:
|
|
1092
|
-
isLoadedInPlayground: isLoaded,
|
|
1093
|
-
onTryIt: () => onTryEndpoint(
|
|
1598
|
+
endpoint: row.endpoint,
|
|
1599
|
+
isLoadedInPlayground: row.isLoaded,
|
|
1600
|
+
onTryIt: () => onTryEndpoint(row.endpoint),
|
|
1601
|
+
schemaId: row.schemaId
|
|
1094
1602
|
},
|
|
1095
|
-
|
|
1096
|
-
);
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1603
|
+
row.key
|
|
1604
|
+
)) });
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
chunkWGEGR3DF_cjs.__name(SchemaSectionStateView, "SchemaSectionStateView");
|
|
1100
1608
|
var MAX_DEPTH2 = 6;
|
|
1101
1609
|
function defaultForSchema(schema) {
|
|
1102
1610
|
if (!schema) return null;
|
|
@@ -1889,6 +2397,9 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
|
1889
2397
|
const { state, config, setSelectedEndpoint } = chunkIULI4XII_cjs.usePlaygroundContext();
|
|
1890
2398
|
const isDesktop = hooks.useMediaQuery("(min-width: 1024px)");
|
|
1891
2399
|
const isMobile = !isDesktop;
|
|
2400
|
+
const grouping = config.schemaGrouping ?? "selector";
|
|
2401
|
+
const preloadAll = grouping === "sections";
|
|
2402
|
+
const urlSyncEnabled = typeof config.urlSync === "boolean" ? config.urlSync : Boolean(config.urlSync?.enabled);
|
|
1892
2403
|
const {
|
|
1893
2404
|
endpoints,
|
|
1894
2405
|
schemaInfo,
|
|
@@ -1898,16 +2409,26 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
|
1898
2409
|
error,
|
|
1899
2410
|
schemas,
|
|
1900
2411
|
currentSchema,
|
|
1901
|
-
setCurrentSchema
|
|
2412
|
+
setCurrentSchema,
|
|
2413
|
+
schemasData
|
|
1902
2414
|
} = useOpenApiSchema({
|
|
1903
2415
|
schemas: config.schemas,
|
|
1904
2416
|
defaultSchemaId: config.defaultSchemaId,
|
|
1905
|
-
baseUrl: config.baseUrl
|
|
2417
|
+
baseUrl: config.baseUrl,
|
|
2418
|
+
preloadAll
|
|
1906
2419
|
});
|
|
1907
2420
|
const [activeAnchor, setActiveAnchor] = React6.useState(null);
|
|
2421
|
+
const [activeSchemaId, setActiveSchemaId] = React6.useState(null);
|
|
1908
2422
|
const [sheetOpen, setSheetOpen] = React6.useState(false);
|
|
1909
2423
|
const docsRef = React6.useRef(null);
|
|
1910
2424
|
const slideOpen = !isMobile && state.selectedEndpoint !== null;
|
|
2425
|
+
const endpointsBySchema = React6.useMemo(() => {
|
|
2426
|
+
if (grouping !== "sections") return {};
|
|
2427
|
+
const byId = lodashEs.keyBy(schemasData, (e) => e.source.id);
|
|
2428
|
+
const out = {};
|
|
2429
|
+
for (const src of schemas) out[src.id] = byId[src.id]?.endpoints ?? [];
|
|
2430
|
+
return out;
|
|
2431
|
+
}, [grouping, schemasData, schemas]);
|
|
1911
2432
|
const handleTry = React6.useCallback(
|
|
1912
2433
|
(ep) => {
|
|
1913
2434
|
setSelectedEndpoint(ep);
|
|
@@ -1918,29 +2439,71 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
|
1918
2439
|
const handleCloseSlide = React6.useCallback(() => {
|
|
1919
2440
|
setSelectedEndpoint(null);
|
|
1920
2441
|
}, [setSelectedEndpoint]);
|
|
1921
|
-
const handleNavigate = React6.useCallback(
|
|
1922
|
-
|
|
2442
|
+
const handleNavigate = React6.useCallback(
|
|
2443
|
+
(anchor, schemaId) => {
|
|
2444
|
+
if (schemaId && schemaId !== currentSchema?.id && grouping === "selector") {
|
|
2445
|
+
setCurrentSchema(schemaId);
|
|
2446
|
+
requestAnimationFrame(() => {
|
|
2447
|
+
docsRef.current?.scrollToAnchor(anchor);
|
|
2448
|
+
});
|
|
2449
|
+
return;
|
|
2450
|
+
}
|
|
2451
|
+
docsRef.current?.scrollToAnchor(anchor);
|
|
2452
|
+
},
|
|
2453
|
+
[currentSchema?.id, grouping, setCurrentSchema]
|
|
2454
|
+
);
|
|
2455
|
+
const handleActiveChange = React6.useCallback((anchor, schemaId) => {
|
|
2456
|
+
setActiveAnchor(anchor);
|
|
2457
|
+
setActiveSchemaId(schemaId);
|
|
1923
2458
|
}, []);
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-8 space-y-4", children: [
|
|
1933
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-8 w-1/2" }),
|
|
1934
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-4 w-full" }),
|
|
1935
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-4 w-3/4" }),
|
|
1936
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 space-y-6", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
1937
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-6 w-1/3" }),
|
|
1938
|
-
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-20 w-full" })
|
|
1939
|
-
] }, i)) })
|
|
1940
|
-
] })
|
|
1941
|
-
]
|
|
2459
|
+
const effectiveSchemaId = grouping === "sections" ? activeSchemaId : currentSchema?.id ?? null;
|
|
2460
|
+
const handleHashTarget = React6.useCallback(
|
|
2461
|
+
(target) => {
|
|
2462
|
+
if (!target.schemaId && !target.anchor) return;
|
|
2463
|
+
const matched = target.schemaId ? schemas.find((s) => s.id === target.schemaId || slugifySchemaId(s.id) === target.schemaId) : null;
|
|
2464
|
+
const needsSchemaSwitch = matched && grouping === "selector" && matched.id !== currentSchema?.id;
|
|
2465
|
+
if (needsSchemaSwitch) {
|
|
2466
|
+
setCurrentSchema(matched.id);
|
|
1942
2467
|
}
|
|
1943
|
-
|
|
2468
|
+
if (target.anchor) {
|
|
2469
|
+
const anchor = target.anchor;
|
|
2470
|
+
if (needsSchemaSwitch) {
|
|
2471
|
+
requestAnimationFrame(() => {
|
|
2472
|
+
docsRef.current?.scrollToAnchor(anchor);
|
|
2473
|
+
});
|
|
2474
|
+
} else {
|
|
2475
|
+
docsRef.current?.scrollToAnchor(anchor);
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
},
|
|
2479
|
+
[schemas, grouping, currentSchema?.id, setCurrentSchema]
|
|
2480
|
+
);
|
|
2481
|
+
useDocsUrlSync({
|
|
2482
|
+
enabled: urlSyncEnabled,
|
|
2483
|
+
currentSchemaId: effectiveSchemaId,
|
|
2484
|
+
activeAnchor,
|
|
2485
|
+
onHashTarget: handleHashTarget
|
|
2486
|
+
});
|
|
2487
|
+
if (loading) {
|
|
2488
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[260px_1fr] items-start", children: [
|
|
2489
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2490
|
+
"div",
|
|
2491
|
+
{
|
|
2492
|
+
className: "sticky top-[var(--navbar-height,64px)] border-r p-3 space-y-1.5 overflow-y-auto",
|
|
2493
|
+
style: { height: "calc(100dvh - var(--navbar-height, 64px))" },
|
|
2494
|
+
children: Array.from({ length: 12 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-8 w-full rounded" }, i))
|
|
2495
|
+
}
|
|
2496
|
+
),
|
|
2497
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-8 space-y-4", children: [
|
|
2498
|
+
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-8 w-1/2" }),
|
|
2499
|
+
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-4 w-full" }),
|
|
2500
|
+
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-4 w-3/4" }),
|
|
2501
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 space-y-6", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
2502
|
+
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-6 w-1/3" }),
|
|
2503
|
+
/* @__PURE__ */ jsxRuntime.jsx(components.Skeleton, { className: "h-20 w-full" })
|
|
2504
|
+
] }, i)) })
|
|
2505
|
+
] })
|
|
2506
|
+
] });
|
|
1944
2507
|
}
|
|
1945
2508
|
if (error) {
|
|
1946
2509
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1956,40 +2519,44 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
|
1956
2519
|
);
|
|
1957
2520
|
}
|
|
1958
2521
|
if (isMobile) {
|
|
1959
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2522
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
2523
|
+
/* @__PURE__ */ jsxRuntime.jsx(EndpointDraftSync, { schemaId: currentSchema?.id ?? null }),
|
|
2524
|
+
grouping === "sections" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2525
|
+
DocsView,
|
|
2526
|
+
{
|
|
2527
|
+
ref: docsRef,
|
|
2528
|
+
grouping: "sections",
|
|
2529
|
+
schemasData,
|
|
2530
|
+
selectedVersion: state.selectedVersion,
|
|
2531
|
+
loadedEndpoint: state.selectedEndpoint,
|
|
2532
|
+
onTryEndpoint: handleTry,
|
|
2533
|
+
onActiveChange: handleActiveChange
|
|
2534
|
+
}
|
|
2535
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2536
|
+
DocsView,
|
|
2537
|
+
{
|
|
2538
|
+
ref: docsRef,
|
|
2539
|
+
info: schemaInfo,
|
|
2540
|
+
rawSchema,
|
|
2541
|
+
resolvedBaseUrl,
|
|
2542
|
+
endpoints,
|
|
2543
|
+
selectedVersion: state.selectedVersion,
|
|
2544
|
+
loadedEndpoint: state.selectedEndpoint,
|
|
2545
|
+
onTryEndpoint: handleTry,
|
|
2546
|
+
onActiveChange: handleActiveChange
|
|
2547
|
+
}
|
|
2548
|
+
),
|
|
2549
|
+
/* @__PURE__ */ jsxRuntime.jsx(TryItSheet, { open: sheetOpen, onOpenChange: setSheetOpen })
|
|
2550
|
+
] });
|
|
2551
|
+
}
|
|
2552
|
+
return /* @__PURE__ */ jsxRuntime.jsx(components.TooltipProvider, { delayDuration: 350, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[260px_minmax(0,1fr)] items-start", children: [
|
|
2553
|
+
/* @__PURE__ */ jsxRuntime.jsx(EndpointDraftSync, { schemaId: currentSchema?.id ?? null }),
|
|
2554
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1960
2555
|
"div",
|
|
1961
2556
|
{
|
|
1962
|
-
className: "
|
|
2557
|
+
className: "sticky top-[var(--navbar-height,64px)]",
|
|
1963
2558
|
style: { height: "calc(100dvh - var(--navbar-height, 64px))" },
|
|
1964
|
-
children:
|
|
1965
|
-
/* @__PURE__ */ jsxRuntime.jsx(EndpointDraftSync, { schemaId: currentSchema?.id ?? null }),
|
|
1966
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1967
|
-
DocsView,
|
|
1968
|
-
{
|
|
1969
|
-
ref: docsRef,
|
|
1970
|
-
info: schemaInfo,
|
|
1971
|
-
rawSchema,
|
|
1972
|
-
resolvedBaseUrl,
|
|
1973
|
-
endpoints,
|
|
1974
|
-
selectedVersion: state.selectedVersion,
|
|
1975
|
-
loadedEndpoint: state.selectedEndpoint,
|
|
1976
|
-
onTryEndpoint: handleTry,
|
|
1977
|
-
onActiveChange: setActiveAnchor
|
|
1978
|
-
}
|
|
1979
|
-
),
|
|
1980
|
-
/* @__PURE__ */ jsxRuntime.jsx(TryItSheet, { open: sheetOpen, onOpenChange: setSheetOpen })
|
|
1981
|
-
]
|
|
1982
|
-
}
|
|
1983
|
-
);
|
|
1984
|
-
}
|
|
1985
|
-
return /* @__PURE__ */ jsxRuntime.jsx(components.TooltipProvider, { delayDuration: 350, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1986
|
-
"div",
|
|
1987
|
-
{
|
|
1988
|
-
className: "grid grid-cols-[260px_minmax(0,1fr)] min-h-0 overflow-hidden",
|
|
1989
|
-
style: { height: "calc(100dvh - var(--navbar-height, 64px))" },
|
|
1990
|
-
children: [
|
|
1991
|
-
/* @__PURE__ */ jsxRuntime.jsx(EndpointDraftSync, { schemaId: currentSchema?.id ?? null }),
|
|
1992
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2559
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1993
2560
|
DocsSidebar,
|
|
1994
2561
|
{
|
|
1995
2562
|
info: schemaInfo,
|
|
@@ -1999,29 +2566,44 @@ var DocsLayout = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
|
1999
2566
|
onSchemaChange: setCurrentSchema,
|
|
2000
2567
|
activeEndpointId: activeAnchor,
|
|
2001
2568
|
selectedVersion: state.selectedVersion,
|
|
2002
|
-
onNavigate: handleNavigate
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2006
|
-
DocsView,
|
|
2007
|
-
{
|
|
2008
|
-
ref: docsRef,
|
|
2009
|
-
info: schemaInfo,
|
|
2569
|
+
onNavigate: handleNavigate,
|
|
2570
|
+
grouping,
|
|
2571
|
+
endpointsBySchema,
|
|
2010
2572
|
rawSchema,
|
|
2011
|
-
resolvedBaseUrl
|
|
2012
|
-
endpoints,
|
|
2013
|
-
selectedVersion: state.selectedVersion,
|
|
2014
|
-
loadedEndpoint: state.selectedEndpoint,
|
|
2015
|
-
onTryEndpoint: handleTry,
|
|
2016
|
-
onActiveChange: setActiveAnchor
|
|
2573
|
+
resolvedBaseUrl
|
|
2017
2574
|
}
|
|
2018
|
-
)
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2575
|
+
)
|
|
2576
|
+
}
|
|
2577
|
+
),
|
|
2578
|
+
grouping === "sections" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2579
|
+
DocsView,
|
|
2580
|
+
{
|
|
2581
|
+
ref: docsRef,
|
|
2582
|
+
grouping: "sections",
|
|
2583
|
+
schemasData,
|
|
2584
|
+
selectedVersion: state.selectedVersion,
|
|
2585
|
+
loadedEndpoint: state.selectedEndpoint,
|
|
2586
|
+
onTryEndpoint: handleTry,
|
|
2587
|
+
onActiveChange: handleActiveChange
|
|
2588
|
+
}
|
|
2589
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2590
|
+
DocsView,
|
|
2591
|
+
{
|
|
2592
|
+
ref: docsRef,
|
|
2593
|
+
info: schemaInfo,
|
|
2594
|
+
rawSchema,
|
|
2595
|
+
resolvedBaseUrl,
|
|
2596
|
+
endpoints,
|
|
2597
|
+
selectedVersion: state.selectedVersion,
|
|
2598
|
+
loadedEndpoint: state.selectedEndpoint,
|
|
2599
|
+
onTryEndpoint: handleTry,
|
|
2600
|
+
onActiveChange: handleActiveChange
|
|
2601
|
+
}
|
|
2602
|
+
),
|
|
2603
|
+
/* @__PURE__ */ jsxRuntime.jsx(SlideInPlayground, { open: slideOpen, onClose: handleCloseSlide })
|
|
2604
|
+
] }) });
|
|
2023
2605
|
}, "DocsLayout");
|
|
2024
2606
|
|
|
2025
2607
|
exports.DocsLayout = DocsLayout;
|
|
2026
|
-
//# sourceMappingURL=DocsLayout-
|
|
2027
|
-
//# sourceMappingURL=DocsLayout-
|
|
2608
|
+
//# sourceMappingURL=DocsLayout-YDR7DSMM.cjs.map
|
|
2609
|
+
//# sourceMappingURL=DocsLayout-YDR7DSMM.cjs.map
|