@takazudo/zudo-doc 6.1.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,53 +3,350 @@ import {
3
3
  BEFORE_NAVIGATE_EVENT
4
4
  } from "../transitions/index.js";
5
5
  const installedControllers = /* @__PURE__ */ new WeakMap();
6
+ const HISTORY_KEY = "zdSidebarScroll";
7
+ const PENDING_KEY = "zd-sidebar-scroll-pending";
8
+ const VIEWPORTS = ["desktop", "mobile"];
9
+ function canonicalPath(pathname) {
10
+ return pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
11
+ }
6
12
  function installSidebarScrollPreserve({
7
13
  document: document2,
8
14
  requestAnimationFrame,
9
- cancelAnimationFrame
15
+ cancelAnimationFrame,
16
+ ResizeObserver: ResizeObserverImpl
10
17
  }) {
11
- let snapshot;
18
+ const view = document2.defaultView;
19
+ let epoch = 0;
20
+ let shortRetries = 0;
21
+ let traverse = false;
22
+ let awaiting = false;
12
23
  let restoreFrame;
13
- const cancelPendingRestore = () => {
24
+ let didInitial = false;
25
+ let writing = false;
26
+ let observer;
27
+ const observed = /* @__PURE__ */ new Set();
28
+ const skipped = /* @__PURE__ */ new Set();
29
+ const applied = /* @__PURE__ */ new Set();
30
+ let elements = {};
31
+ let memory = {};
32
+ let pending;
33
+ let held = {};
34
+ const cancelFrame = () => {
14
35
  if (restoreFrame === void 0) return;
15
36
  cancelAnimationFrame(restoreFrame);
16
37
  restoreFrame = void 0;
17
38
  };
18
- const onBefore = () => {
19
- cancelPendingRestore();
20
- const element = document2.querySelector("#desktop-sidebar");
21
- snapshot = element ? { element, scrollTop: element.scrollTop } : void 0;
39
+ const disconnectObserver = () => {
40
+ observer?.disconnect();
41
+ observer = void 0;
22
42
  };
23
- const onAfter = () => {
24
- if (!snapshot) return;
25
- const saved = snapshot;
26
- snapshot = void 0;
43
+ const capture = () => {
44
+ const next = { ...memory };
45
+ for (const kind of VIEWPORTS) {
46
+ const element = findViewport(document2, kind);
47
+ if (!element) {
48
+ delete next[kind];
49
+ delete elements[kind];
50
+ continue;
51
+ }
52
+ if (!measurable(element)) continue;
53
+ if (isEmptyTree(element) && element.scrollTop === 0 && (next[kind]?.scrollTop ?? 0) > 0) continue;
54
+ next[kind] = readSlot(element);
55
+ elements[kind] = element;
56
+ }
57
+ memory = next;
58
+ return next;
59
+ };
60
+ const writeHistory = (slots) => {
61
+ if (!view || traverse) return;
62
+ const state = view.history.state;
63
+ if (!state || typeof state !== "object") return;
64
+ if (JSON.stringify(state.zdSidebarScroll) === JSON.stringify(slots)) return;
65
+ try {
66
+ view.history.replaceState({ ...state, [HISTORY_KEY]: slots }, "");
67
+ } catch {
68
+ }
69
+ };
70
+ const schedule = () => {
71
+ if (restoreFrame !== void 0) return;
27
72
  restoreFrame = requestAnimationFrame(() => {
28
73
  restoreFrame = void 0;
29
- const current = document2.querySelector("#desktop-sidebar");
30
- if (current === saved.element) current.scrollTop = saved.scrollTop;
74
+ apply();
31
75
  });
32
76
  };
77
+ const arm = (kind, element) => {
78
+ const Observer = ResizeObserverImpl ?? view?.ResizeObserver;
79
+ if (!Observer || observed.has(kind)) return false;
80
+ observed.add(kind);
81
+ disconnectObserver();
82
+ const epochAt = epoch;
83
+ try {
84
+ const next = new Observer(() => {
85
+ disconnectObserver();
86
+ if (epochAt !== epoch) return;
87
+ apply();
88
+ });
89
+ next.observe(element);
90
+ observer = next;
91
+ return true;
92
+ } catch {
93
+ return false;
94
+ }
95
+ };
96
+ const finishIfSettled = (waiting) => {
97
+ if (waiting) return;
98
+ pending = void 0;
99
+ awaiting = false;
100
+ writeHistory(memory);
101
+ };
102
+ const applyHeld = () => {
103
+ let restored = false;
104
+ for (const kind of VIEWPORTS) {
105
+ const slot = held[kind];
106
+ if (!slot) continue;
107
+ const element = findViewport(document2, kind);
108
+ if (!element || !measurable(element)) continue;
109
+ const outcome = restoreViewport(kind, element, slot);
110
+ if (outcome === "wait") {
111
+ arm(kind, element);
112
+ continue;
113
+ }
114
+ memory[kind] = readSlot(element);
115
+ delete held[kind];
116
+ restored = true;
117
+ }
118
+ if (restored && !awaiting) writeHistory(memory);
119
+ };
120
+ const apply = () => {
121
+ if (!pending) {
122
+ if (Object.keys(held).length) applyHeld();
123
+ if (!didInitial) {
124
+ didInitial = true;
125
+ for (const kind of VIEWPORTS) {
126
+ const element = findViewport(document2, kind);
127
+ if (element && measurable(element)) revealCurrent(element, writeScroll);
128
+ }
129
+ }
130
+ return;
131
+ }
132
+ let waiting = false;
133
+ for (const kind of VIEWPORTS) {
134
+ const slot = pending[kind];
135
+ if (!slot || skipped.has(kind) || applied.has(kind)) continue;
136
+ const element = findViewport(document2, kind);
137
+ if (!element || !measurable(element)) {
138
+ if (element) {
139
+ held[kind] = slot;
140
+ memory[kind] = slot;
141
+ }
142
+ applied.add(kind);
143
+ continue;
144
+ }
145
+ const outcome = restoreViewport(kind, element, slot);
146
+ if (outcome === "wait") {
147
+ if (!isEmptyTree(element)) shortRetries += 1;
148
+ arm(kind, element);
149
+ waiting = true;
150
+ if (!isEmptyTree(element) && shortRetries < 8) schedule();
151
+ continue;
152
+ }
153
+ memory[kind] = readSlot(element);
154
+ applied.add(kind);
155
+ }
156
+ finishIfSettled(waiting);
157
+ };
158
+ const restoreViewport = (kind, element, slot) => {
159
+ const context = readContext(element);
160
+ if (slot.contextId) {
161
+ if (!context) return observed.has(kind) ? "done" : "wait";
162
+ if (context !== slot.contextId) {
163
+ revealCurrent(element, writeScroll);
164
+ return "done";
165
+ }
166
+ } else if (elements[kind] !== element) {
167
+ return "done";
168
+ }
169
+ const canHold = slot.scrollTop === 0 || element.scrollHeight - element.clientHeight + 2 >= slot.scrollTop;
170
+ if (!canHold) {
171
+ if (!isEmptyTree(element) && shortRetries >= 8) {
172
+ revealCurrent(element, writeScroll);
173
+ return "done";
174
+ }
175
+ return "wait";
176
+ }
177
+ const compatible = readViewKey(element) === slot.viewKey && readScope(element) === slot.scopeId && Math.abs(element.scrollHeight - slot.contentHeight) <= 2;
178
+ if (compatible) {
179
+ writeScroll(element, slot.scrollTop);
180
+ return "done";
181
+ }
182
+ if (slot.anchorId) {
183
+ const row = findAnchor(element, slot.anchorId);
184
+ if (row) {
185
+ const delta = row.getBoundingClientRect().top - element.getBoundingClientRect().top - (slot.anchorOffset ?? 0);
186
+ const next = element.scrollTop + delta;
187
+ if (next > element.scrollHeight - element.clientHeight + 2) return "wait";
188
+ writeScroll(element, next);
189
+ return "done";
190
+ }
191
+ }
192
+ revealCurrent(element, writeScroll);
193
+ return "done";
194
+ };
195
+ const writeScroll = (element, next) => {
196
+ if (Math.abs(element.scrollTop - next) <= 2) return;
197
+ writing = true;
198
+ element.scrollTop = next;
199
+ writing = false;
200
+ };
201
+ const begin = (slots) => {
202
+ epoch += 1;
203
+ cancelFrame();
204
+ disconnectObserver();
205
+ observed.clear();
206
+ skipped.clear();
207
+ applied.clear();
208
+ pending = slots;
209
+ held = {};
210
+ awaiting = true;
211
+ didInitial = true;
212
+ shortRetries = 0;
213
+ };
214
+ const onBefore = () => {
215
+ if (traverse) {
216
+ traverse = false;
217
+ return;
218
+ }
219
+ const slots = capture();
220
+ begin(slots);
221
+ awaiting = false;
222
+ writeHistory(slots);
223
+ };
224
+ const onAfter = () => {
225
+ try {
226
+ view?.sessionStorage.removeItem(PENDING_KEY);
227
+ } catch {
228
+ }
229
+ if (!pending) return;
230
+ awaiting = true;
231
+ };
232
+ const onPopState = () => {
233
+ traverse = true;
234
+ begin(readHistory(view) ?? {});
235
+ };
236
+ const onClick = (event) => {
237
+ const mouse = event;
238
+ if (mouse.button !== 0 || mouse.metaKey || mouse.ctrlKey || mouse.shiftKey || mouse.altKey) return;
239
+ const target = mouse.target;
240
+ if (!(target instanceof Element) || !view) return;
241
+ const link = target.closest("a[href]");
242
+ if (!(link instanceof HTMLAnchorElement) || link.target === "_blank") return;
243
+ if (!link.closest("#desktop-sidebar, [data-zd-mobile-sidebar]")) return;
244
+ let url;
245
+ try {
246
+ url = new URL(link.href, view.location.href);
247
+ } catch {
248
+ return;
249
+ }
250
+ if (url.origin !== view.location.origin) return;
251
+ if (url.pathname === view.location.pathname && url.search === view.location.search) return;
252
+ try {
253
+ view.sessionStorage.setItem(PENDING_KEY, JSON.stringify({ to: canonicalPath(url.pathname), slots: capture() }));
254
+ } catch {
255
+ }
256
+ };
257
+ const onUserScroll = (event) => {
258
+ if (writing) return;
259
+ const kind = viewportKind(event.target);
260
+ if (!kind || skipped.has(kind)) return;
261
+ if (!awaiting && !held[kind]) return;
262
+ if (event.type === "keydown") {
263
+ const key = event.key;
264
+ if (!["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", " "].includes(key)) return;
265
+ }
266
+ skipped.add(kind);
267
+ applied.add(kind);
268
+ delete held[kind];
269
+ cancelFrame();
270
+ schedule();
271
+ };
272
+ const onScroll = (event) => {
273
+ if (writing || traverse || awaiting) return;
274
+ if (!viewportKind(event.target)) return;
275
+ capture();
276
+ scheduleHistory();
277
+ };
278
+ let historyFrame;
279
+ const scheduleHistory = () => {
280
+ if (historyFrame !== void 0) return;
281
+ historyFrame = requestAnimationFrame(() => {
282
+ historyFrame = void 0;
283
+ writeHistory(memory);
284
+ });
285
+ };
286
+ const notify = (root) => {
287
+ if (root.ownerDocument !== document2) return;
288
+ if (awaiting) schedule();
289
+ else if (Object.keys(held).length || !didInitial) schedule();
290
+ };
291
+ const consumePendingStorage = () => {
292
+ if (!view) return;
293
+ try {
294
+ const raw = view.sessionStorage.getItem(PENDING_KEY);
295
+ if (!raw) return;
296
+ view.sessionStorage.removeItem(PENDING_KEY);
297
+ const parsed = JSON.parse(raw);
298
+ if (!isRecord(parsed) || typeof parsed.to !== "string") return;
299
+ if (canonicalPath(parsed.to) !== canonicalPath(view.location.pathname)) return;
300
+ const slots = sanitizeSlots(parsed.slots);
301
+ if (!slots) return;
302
+ begin(slots);
303
+ } catch {
304
+ }
305
+ };
306
+ consumePendingStorage();
307
+ if (!pending) {
308
+ const stored = readHistory(view);
309
+ if (stored) begin(stored);
310
+ }
33
311
  document2.addEventListener(BEFORE_NAVIGATE_EVENT, onBefore);
34
312
  document2.addEventListener(AFTER_NAVIGATE_EVENT, onAfter);
35
- return () => {
313
+ document2.addEventListener("click", onClick, true);
314
+ document2.addEventListener("pointerdown", onUserScroll, true);
315
+ document2.addEventListener("wheel", onUserScroll, true);
316
+ document2.addEventListener("touchmove", onUserScroll, true);
317
+ document2.addEventListener("keydown", onUserScroll, true);
318
+ document2.addEventListener("scroll", onScroll, true);
319
+ view?.addEventListener("popstate", onPopState);
320
+ const cleanup = () => {
36
321
  document2.removeEventListener(BEFORE_NAVIGATE_EVENT, onBefore);
37
322
  document2.removeEventListener(AFTER_NAVIGATE_EVENT, onAfter);
38
- cancelPendingRestore();
39
- snapshot = void 0;
323
+ document2.removeEventListener("click", onClick, true);
324
+ document2.removeEventListener("pointerdown", onUserScroll, true);
325
+ document2.removeEventListener("wheel", onUserScroll, true);
326
+ document2.removeEventListener("touchmove", onUserScroll, true);
327
+ document2.removeEventListener("keydown", onUserScroll, true);
328
+ document2.removeEventListener("scroll", onScroll, true);
329
+ view?.removeEventListener("popstate", onPopState);
330
+ cancelFrame();
331
+ if (historyFrame !== void 0) cancelAnimationFrame(historyFrame);
332
+ disconnectObserver();
333
+ pending = void 0;
334
+ awaiting = false;
335
+ if (installedControllers.get(document2)?.cleanup === cleanup) installedControllers.delete(document2);
40
336
  };
337
+ installedControllers.set(document2, { cleanup, notify });
338
+ return cleanup;
41
339
  }
42
340
  function ensureSidebarScrollPreserve(options) {
43
341
  const resolved = options ?? resolveBrowserOptions();
44
342
  if (!resolved || installedControllers.has(resolved.document)) return;
45
- installedControllers.set(
46
- resolved.document,
47
- installSidebarScrollPreserve(resolved)
48
- );
343
+ installSidebarScrollPreserve(resolved);
344
+ }
345
+ function notifySidebarScrollReady(root) {
346
+ installedControllers.get(root.ownerDocument)?.notify(root);
49
347
  }
50
348
  function resolveBrowserOptions() {
51
- if (typeof document === "undefined" || typeof window === "undefined")
52
- return void 0;
349
+ if (typeof document === "undefined" || typeof window === "undefined") return void 0;
53
350
  return {
54
351
  document,
55
352
  requestAnimationFrame: window.requestAnimationFrame.bind(window),
@@ -57,11 +354,114 @@ function resolveBrowserOptions() {
57
354
  };
58
355
  }
59
356
  function disposeSidebarScrollPreserve(document2) {
60
- installedControllers.get(document2)?.();
357
+ installedControllers.get(document2)?.cleanup();
61
358
  installedControllers.delete(document2);
62
359
  }
360
+ function findViewport(document2, kind) {
361
+ if (kind === "desktop") return document2.querySelector("#desktop-sidebar");
362
+ return document2.querySelector("aside[data-zd-mobile-sidebar] .flex-1.overflow-y-auto");
363
+ }
364
+ function measurable(element) {
365
+ if (element.clientHeight <= 0 || element.closest("[inert]")) return false;
366
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
367
+ return !style || style.display !== "none" && style.visibility !== "hidden";
368
+ }
369
+ function isEmptyTree(element) {
370
+ return element.querySelector("a[href], [data-sidebar-focus-scope]") === null;
371
+ }
372
+ function readContext(element) {
373
+ const value = element.querySelector("nav")?.getAttribute("data-sidebar-context");
374
+ return value || void 0;
375
+ }
376
+ function readScope(element) {
377
+ return element.querySelector("nav")?.getAttribute("data-sidebar-scope") ?? "";
378
+ }
379
+ function readViewKey(element) {
380
+ const parts = [];
381
+ for (const node of element.querySelectorAll("[data-sidebar-focus-scope], a[href]")) {
382
+ const id = node.dataset.sidebarFocusScope || node.getAttribute("href");
383
+ if (id) parts.push(id);
384
+ }
385
+ let hash = 2166136261;
386
+ const serialized = parts.join("\n");
387
+ for (let i = 0; i < serialized.length; i++) hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
388
+ return String(hash >>> 0);
389
+ }
390
+ function readSlot(element) {
391
+ const anchor = captureAnchor(element);
392
+ return {
393
+ scrollTop: element.scrollTop,
394
+ ...anchor,
395
+ contextId: readContext(element),
396
+ scopeId: readScope(element),
397
+ viewKey: readViewKey(element),
398
+ contentHeight: element.scrollHeight
399
+ };
400
+ }
401
+ function captureAnchor(element) {
402
+ const bounds = element.getBoundingClientRect();
403
+ for (const row of element.querySelectorAll("[data-sidebar-focus-scope], a[href]")) {
404
+ const rect = row.getBoundingClientRect();
405
+ if (rect.height === 0 && rect.top === 0 && rect.bottom === 0) continue;
406
+ if (rect.bottom > bounds.top && rect.top < bounds.bottom) {
407
+ const anchorId = row.dataset.sidebarFocusScope || row.getAttribute("href") || void 0;
408
+ return anchorId ? { anchorId, anchorOffset: rect.top - bounds.top } : {};
409
+ }
410
+ }
411
+ return {};
412
+ }
413
+ function findAnchor(element, id) {
414
+ for (const node of element.querySelectorAll("[data-sidebar-focus-scope], a[href]")) {
415
+ if (node.dataset.sidebarFocusScope === id || node.getAttribute("href") === id) return node;
416
+ }
417
+ return null;
418
+ }
419
+ function revealCurrent(element, write) {
420
+ const current = element.querySelector('[aria-current="page"]');
421
+ if (!current) return;
422
+ const bounds = element.getBoundingClientRect();
423
+ const row = current.getBoundingClientRect();
424
+ if (row.height === 0 && row.top === 0 && row.bottom === 0) return;
425
+ if (row.top < bounds.top) write(element, element.scrollTop + row.top - bounds.top - 8);
426
+ else if (row.bottom > bounds.bottom) write(element, element.scrollTop + row.bottom - bounds.bottom + 8);
427
+ }
428
+ function viewportKind(target) {
429
+ if (!(target instanceof Element)) return void 0;
430
+ if (target.id === "desktop-sidebar" || target.closest("#desktop-sidebar")) return "desktop";
431
+ if (target.closest("[data-zd-mobile-sidebar]")) return "mobile";
432
+ return void 0;
433
+ }
434
+ function isRecord(value) {
435
+ return typeof value === "object" && value !== null && !Array.isArray(value);
436
+ }
437
+ function sanitizeSlots(value) {
438
+ if (!isRecord(value)) return void 0;
439
+ const slots = {};
440
+ for (const kind of VIEWPORTS) {
441
+ const slot = value[kind];
442
+ if (!isRecord(slot) || typeof slot.scrollTop !== "number" || !Number.isFinite(slot.scrollTop)) continue;
443
+ if (typeof slot.viewKey !== "string" || typeof slot.scopeId !== "string" || typeof slot.contentHeight !== "number") continue;
444
+ const next = {
445
+ scrollTop: slot.scrollTop,
446
+ scopeId: slot.scopeId,
447
+ viewKey: slot.viewKey,
448
+ contentHeight: slot.contentHeight
449
+ };
450
+ if (typeof slot.contextId === "string") next.contextId = slot.contextId;
451
+ if (typeof slot.anchorId === "string") next.anchorId = slot.anchorId;
452
+ if (typeof slot.anchorOffset === "number") next.anchorOffset = slot.anchorOffset;
453
+ slots[kind] = next;
454
+ }
455
+ return slots;
456
+ }
457
+ function readHistory(view) {
458
+ const state = view?.history.state;
459
+ if (!isRecord(state)) return void 0;
460
+ return sanitizeSlots(state[HISTORY_KEY]);
461
+ }
63
462
  export {
64
463
  disposeSidebarScrollPreserve,
65
464
  ensureSidebarScrollPreserve,
66
- installSidebarScrollPreserve
465
+ installSidebarScrollPreserve,
466
+ notifySidebarScrollReady
67
467
  };
@@ -36,6 +36,14 @@ export interface SidebarDefinition {
36
36
  * @default "children"
37
37
  */
38
38
  initialPathMode?: "children" | "node";
39
+ /**
40
+ * Highest tree Broaden can reach. `"editorial"` keeps the current forest,
41
+ * including the full automatic tree where that is already reachable.
42
+ * `"configured"` stops at the authored forest. `initialPath` stays the
43
+ * starting view and the Restore baseline.
44
+ * @default "editorial"
45
+ */
46
+ scopeRoot?: "configured" | "editorial";
39
47
  /** Share across sections using the same editorial tree. Locale/version are added by chrome. */
40
48
  contextId?: string;
41
49
  }
@@ -78,11 +78,48 @@ function buildSidebarForSection(docs, lang, categoryMatch, categoryMeta, sidebar
78
78
  const tree = buildNavTree(docs, lang, categoryMeta);
79
79
  const sectionKey = categoryMatch ?? "default";
80
80
  const config = sidebars[sectionKey];
81
- if (!config || (Array.isArray(config) ? config.length === 0 : config.items.length === 0)) {
82
- return filterByCategory(tree, categoryMatch, explicitCategoryPrefixes);
81
+ const definition = config && !Array.isArray(config) ? config : void 0;
82
+ scopeRootOf(definition, sectionKey);
83
+ const items = Array.isArray(config) ? config : definition?.items;
84
+ const forest = items?.length ? resolveItems(items, tree, lang) : filterByCategory(tree, categoryMatch, explicitCategoryPrefixes);
85
+ return followInitialPath(forest, definition, sectionKey).nodes;
86
+ }
87
+ function scopeRootOf(definition, sectionKey) {
88
+ const value = definition?.scopeRoot;
89
+ if (value === void 0 || value === "editorial") return "editorial";
90
+ if (value === "configured") return "configured";
91
+ throw new Error(`Invalid sidebar scopeRoot for ${sectionKey}`);
92
+ }
93
+ function retainForest(roots, parents) {
94
+ const ids = /* @__PURE__ */ new Set();
95
+ const visit = (nodes) => {
96
+ for (const node of nodes) {
97
+ if (node.occurrenceId) ids.add(node.occurrenceId);
98
+ visit(node.children);
99
+ }
100
+ };
101
+ visit(roots);
102
+ for (const id of Object.keys(parents)) if (!ids.has(id)) delete parents[id];
103
+ for (const root of roots) if (root.occurrenceId) parents[root.occurrenceId] = null;
104
+ }
105
+ function applyConfiguredCap(items, categoryMatch, prefixes, automatic, state, parents) {
106
+ if (!items?.length) {
107
+ if (!categoryMatch) return;
108
+ state.roots = filterByCategory(automatic, categoryMatch, prefixes);
109
+ state.nodes = state.roots;
110
+ retainForest(state.roots, parents);
111
+ return;
112
+ }
113
+ const only = items.length === 1 && typeof items[0] !== "string" ? items[0] : void 0;
114
+ if (only?.type === "autogenerated") {
115
+ if (!only.dirName) return;
116
+ const source = findNode(automatic, only.dirName);
117
+ state.roots = source ? [source] : [];
118
+ state.nodes = source?.children ?? [];
119
+ retainForest(state.roots, parents);
120
+ return;
83
121
  }
84
- if (Array.isArray(config)) return resolveItems(config, tree, lang);
85
- return followInitialPath(resolveItems(config.items, tree, lang), config, sectionKey).nodes;
122
+ retainForest(state.roots, parents);
86
123
  }
87
124
  function followInitialPath(forest, definition, sectionKey) {
88
125
  const mode = definition?.initialPathMode;
@@ -108,8 +145,10 @@ function buildSidebarNavigation(...args) {
108
145
  }
109
146
  }
110
147
  const tree = buildTree(docs, lang, meta);
111
- const config = sidebars[categoryMatch ?? "default"];
148
+ const sectionKey = categoryMatch ?? "default";
149
+ const config = sidebars[sectionKey];
112
150
  const definition = config && !Array.isArray(config) ? config : void 0;
151
+ const scopeRoot = scopeRootOf(definition, sectionKey);
113
152
  const items = Array.isArray(config) ? config : definition?.items;
114
153
  const parents = {};
115
154
  function identify(nodes2, prefix, parent) {
@@ -165,7 +204,13 @@ function buildSidebarNavigation(...args) {
165
204
  roots = result.canonical;
166
205
  nodes = result.visible;
167
206
  }
168
- const { nodes: local, target } = followInitialPath(nodes, definition, categoryMatch ?? "default");
207
+ if (scopeRoot === "configured") {
208
+ const state = { roots, nodes };
209
+ applyConfiguredCap(items, categoryMatch, prefixes, automatic, state, parents);
210
+ roots = state.roots;
211
+ nodes = state.nodes;
212
+ }
213
+ const { nodes: local, target } = followInitialPath(nodes, definition, sectionKey);
169
214
  nodes = local;
170
215
  const localParentId = definition?.initialPathMode === "node" && target?.occurrenceId ? parents[target.occurrenceId] ?? void 0 : target?.occurrenceId;
171
216
  let hash = 2166136261;