@takazudo/zudo-doc 5.5.3 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +39 -0
  3. package/dist/chrome/derive.d.ts +46 -0
  4. package/dist/chrome/derive.js +6 -2
  5. package/dist/config-assertions/index.d.ts +31 -0
  6. package/dist/config-assertions/index.js +24 -0
  7. package/dist/config.d.ts +23 -2
  8. package/dist/config.js +3 -0
  9. package/dist/current-path/index.d.ts +27 -0
  10. package/dist/current-path/index.js +11 -0
  11. package/dist/design-token-panel-bootstrap.d.ts +89 -23
  12. package/dist/design-token-panel-bootstrap.js +19 -6
  13. package/dist/doc-page-props/index.d.ts +5 -67
  14. package/dist/doc-route-entries/index.d.ts +10 -95
  15. package/dist/doc-route-entries/index.js +1 -78
  16. package/dist/doc-route-paths/index.d.ts +1 -1
  17. package/dist/head-with-defaults/index.d.ts +3 -1
  18. package/dist/head-with-defaults/index.js +76 -4
  19. package/dist/header/nav-active.d.ts +31 -0
  20. package/dist/header/nav-active.js +2 -1
  21. package/dist/header/nav-overflow-generated-script.d.ts +11 -0
  22. package/dist/header/nav-overflow-generated-script.js +302 -0
  23. package/dist/header/nav-overflow-script.d.ts +1 -1
  24. package/dist/header/nav-overflow-script.js +1 -286
  25. package/dist/header-with-defaults/index.js +11 -2
  26. package/dist/i18n-version/language-switcher.d.ts +6 -0
  27. package/dist/i18n-version/language-switcher.js +3 -1
  28. package/dist/i18n-version/version-switcher.d.ts +6 -0
  29. package/dist/i18n-version/version-switcher.js +3 -1
  30. package/dist/md-utils/index.js +33 -1
  31. package/dist/nav-source-docs/index.d.ts +7 -11
  32. package/dist/plugins/route-pages-candidates.d.ts +19 -0
  33. package/dist/plugins/route-pages-candidates.js +17 -0
  34. package/dist/plugins/routes.d.ts +46 -0
  35. package/dist/plugins/routes.js +72 -18
  36. package/dist/preset.d.ts +12 -1
  37. package/dist/preset.js +2 -0
  38. package/dist/route-context/index.js +2 -2
  39. package/dist/routes/_chrome.d.ts +1 -1
  40. package/dist/routes/_chrome.js +4 -0
  41. package/dist/routes/_context.d.ts +3 -3
  42. package/dist/routes/_design-token-panel-bootstrap.d.ts +18 -0
  43. package/dist/routes/_design-token-panel-bootstrap.js +11 -0
  44. package/dist/routes/_docs-helpers.d.ts +1 -36
  45. package/dist/routes/_docs-helpers.js +0 -138
  46. package/dist/safelist.css +1 -1
  47. package/dist/search-widget-script/generated-script.d.ts +8 -0
  48. package/dist/search-widget-script/generated-script.js +465 -0
  49. package/dist/search-widget-script/index.d.ts +1 -18
  50. package/dist/search-widget-script/index.js +1 -443
  51. package/dist/settings.d.ts +82 -1
  52. package/dist/sidebar-toggle-island/index.js +2 -1
  53. package/dist/sidebar-tree/category-meta.d.ts +9 -0
  54. package/dist/sidebar-tree/category-meta.js +21 -12
  55. package/dist/sidebar-tree-island/index.d.ts +8 -1
  56. package/dist/sidebar-tree-island/index.js +16 -14
  57. package/dist/site-schema/doc-route-entries.d.ts +89 -0
  58. package/dist/site-schema/doc-route-entries.js +83 -0
  59. package/dist/site-schema/index.d.ts +17 -0
  60. package/dist/site-schema/index.js +46 -0
  61. package/dist/site-schema/nav-tree.d.ts +28 -0
  62. package/dist/site-schema/nav-tree.js +138 -0
  63. package/dist/site-schema/types.d.ts +97 -0
  64. package/dist/site-schema/types.js +0 -0
  65. package/dist/theme/theme-pack-provider.d.ts +34 -3
  66. package/dist/theme/theme-pack-provider.js +30 -2
  67. package/dist/transitions/index.d.ts +1 -0
  68. package/dist/transitions/index.js +2 -0
  69. package/dist/transitions/nested-island-props-refresh.d.ts +19 -0
  70. package/dist/transitions/nested-island-props-refresh.js +104 -0
  71. package/eject/header/header.tsx +13 -5
  72. package/eject/header/nav-active.ts +16 -1
  73. package/eject/header/nav-class-tokens.ts +9 -5
  74. package/eject/header/nav-overflow-generated-script.ts +29 -0
  75. package/eject/header/nav-overflow-script.ts +26 -304
  76. package/eject/sidebar-toggle-island/index.tsx +13 -1
  77. package/eject/sidebar-tree-island/index.tsx +44 -20
  78. package/package.json +25 -12
  79. package/routes-src/_chrome.tsx +21 -9
  80. package/routes-src/_design-token-panel-bootstrap.tsx +63 -0
  81. package/routes-src/_docs-helpers.ts +18 -225
  82. package/routes-src/_virtual.d.ts +5 -2
  83. package/virtual-modules.d.ts +5 -2
@@ -0,0 +1,302 @@
1
+ function buildNavOverflowScript() {
2
+ return `(function () {
3
+ var cleanupNavOverflow = null;
4
+
5
+ function trimSlashes(p) {
6
+ while (p.length > 1 && p.charAt(p.length - 1) === "/") p = p.slice(0, -1);
7
+ return p || "/";
8
+ }
9
+
10
+ function navPathname(a) {
11
+ try { return trimSlashes(new URL(a.href, location.href).pathname); }
12
+ catch (e) { return ""; }
13
+ }
14
+
15
+ // Explicit current-route override, embedded from current-path/index.ts so
16
+ // this script cannot drift from the three other read sites
17
+ // (zudolab/zudo-doc#3398, #3408).
18
+ var CURRENT_PATH_DATASET_KEY="zdCurrentPath";var readCurrentPath=function readCurrentPath(datasetKey, explicit) {
19
+ const override = typeof document === "undefined" ? void 0 : document.documentElement.dataset[datasetKey];
20
+ return explicit || override || (typeof window === "undefined" ? void 0 : window.location.pathname);
21
+ };
22
+
23
+ // Shared matching core (zudolab/zudo-doc#3398): embedded verbatim from
24
+ // nav-active.ts so this script's longest-match walk cannot drift from the
25
+ // SSR header's own computeActiveNavPath call (header.tsx). computeActiveNavPath
26
+ // closes over pathMatchesNavPath, so both are embedded together.
27
+ var pathMatchesNavPath = function pathMatchesNavPath(currentPath, navPath) {
28
+ if (currentPath === navPath) return true;
29
+ const prefix = navPath.endsWith("/") ? navPath : \`\${navPath}/\`;
30
+ return currentPath.startsWith(prefix);
31
+ };
32
+ var computeActiveNavPath = function computeActiveNavPath(navItems, pathForMatchValue) {
33
+ const allNavPaths = navItems.flatMap((item) => {
34
+ const paths = [item.path];
35
+ if (item.children) {
36
+ paths.push(...item.children.map((child) => child.path));
37
+ }
38
+ return paths;
39
+ });
40
+ return allNavPaths.filter((p) => pathMatchesNavPath(pathForMatchValue, p)).sort((a, b) => b.length - a.length)[0];
41
+ };
42
+
43
+ // Recompute which header nav item is "active" from the CURRENT URL and
44
+ // repaint the highlight. SSR sets the active item on first paint, but the
45
+ // header is persisted across same-locale client-router swaps
46
+ // (data-zfb-transition-persist), so without this the highlight would stay
47
+ // frozen on the page where the header was first rendered. Mirrors the
48
+ // sidebar island's client-side approach (match the current path against
49
+ // each entry's href) and the SSR longest-match + dropdown-parent rules.
50
+ // URL-based: hrefs and the current path both carry the base + locale
51
+ // prefix, so they compare directly without stripping.
52
+ function applyActiveNav() {
53
+ var nav = document.querySelector("[data-header-nav]");
54
+ if (!nav) return;
55
+ var topItems = Array.from(nav.querySelectorAll(":scope > [data-nav-item]"));
56
+ if (topItems.length === 0) return;
57
+
58
+ var cur = trimSlashes(readCurrentPath(CURRENT_PATH_DATASET_KEY));
59
+
60
+ // Build NavItemLike-shaped entries from the live DOM so the shared
61
+ // computeActiveNavPath can do the deepest-match walk \u2014 the same call
62
+ // shape the SSR header uses (matches computeActiveNavPath). A dropdown
63
+ // missing its own top-level anchor is skipped entirely (path "" would
64
+ // otherwise match every current path \u2014 pathMatchesNavPath treats "" as
65
+ // the root "/"), mirroring the parentLink guard used below for the same
66
+ // malformed-markup case.
67
+ var navItems = [];
68
+ topItems.forEach(function (it) {
69
+ var isDropdown = it.hasAttribute("data-nav-item-dropdown");
70
+ var topA = isDropdown ? it.querySelector(":scope > a") : it;
71
+ if (!topA) return;
72
+ var children = [];
73
+ if (isDropdown) {
74
+ it.querySelectorAll(":scope > div a").forEach(function (c) {
75
+ children.push({ path: navPathname(c) });
76
+ });
77
+ }
78
+ navItems.push({ path: navPathname(topA), children: children });
79
+ });
80
+
81
+ var activePath = computeActiveNavPath(navItems, cur) || "";
82
+
83
+ function setTopActive(a, active) {
84
+ if (!a) return;
85
+ if (active) {
86
+ a.classList.add("bg-fg", "text-bg");
87
+ a.classList.remove("text-muted", "hover:text-accent", "hover:underline", "focus:underline", "focus:text-accent");
88
+ a.setAttribute("aria-current", "page");
89
+ } else {
90
+ a.classList.remove("bg-fg", "text-bg");
91
+ a.classList.add("text-muted", "hover:text-accent", "hover:underline", "focus:underline", "focus:text-accent");
92
+ a.removeAttribute("aria-current");
93
+ }
94
+ }
95
+
96
+ topItems.forEach(function (it) {
97
+ var isDropdown = it.hasAttribute("data-nav-item-dropdown");
98
+ var topA = isDropdown ? it.querySelector(":scope > a") : it;
99
+ var topActive = false;
100
+
101
+ if (isDropdown) {
102
+ var parentMatch = !!topA && navPathname(topA) === activePath && activePath !== "";
103
+ var anyChild = false;
104
+ it.querySelectorAll(":scope > div a").forEach(function (c) {
105
+ var childActive = navPathname(c) === activePath && activePath !== "";
106
+ if (childActive) {
107
+ anyChild = true;
108
+ c.setAttribute("data-active", "");
109
+ c.classList.add("font-bold", "text-accent");
110
+ c.classList.remove("text-fg", "hover:text-accent", "focus-visible:text-accent");
111
+ } else {
112
+ c.removeAttribute("data-active");
113
+ c.classList.remove("font-bold", "text-accent");
114
+ c.classList.add("text-fg", "hover:text-accent", "focus-visible:text-accent");
115
+ }
116
+ });
117
+ topActive = parentMatch || anyChild;
118
+ var svg = topA ? topA.querySelector("svg") : null;
119
+ if (svg) {
120
+ if (topActive) { svg.classList.add("text-bg"); svg.classList.remove("text-muted"); }
121
+ else { svg.classList.add("text-muted"); svg.classList.remove("text-bg"); }
122
+ }
123
+ } else {
124
+ topActive = activePath !== "" && navPathname(topA) === activePath;
125
+ }
126
+
127
+ setTopActive(topA, topActive);
128
+ });
129
+ }
130
+
131
+ function initNavOverflow() {
132
+ if (cleanupNavOverflow) cleanupNavOverflow();
133
+
134
+ // Repaint the active highlight for the current URL before measuring /
135
+ // cloning, so the overflow "\xB7\xB7\xB7" menu mirrors the correct active state.
136
+ applyActiveNav();
137
+
138
+ var nav = document.querySelector("[data-header-nav]");
139
+ var moreContainer = document.querySelector("[data-nav-more]");
140
+ var moreMenu = document.querySelector("[data-nav-more-menu]");
141
+ var moreToggle = document.querySelector("[data-nav-more-toggle]");
142
+ if (!nav || !moreContainer || !moreMenu || !moreToggle) return;
143
+
144
+ var items = Array.from(nav.querySelectorAll(":scope > [data-nav-item]"));
145
+ if (items.length === 0) return;
146
+
147
+ var controller = new AbortController();
148
+
149
+ function update() {
150
+ items.forEach(function (el) { el.style.display = ""; });
151
+ moreContainer.style.display = "";
152
+ moreMenu.innerHTML = "";
153
+ moreMenu.classList.add("hidden");
154
+ moreToggle.setAttribute("aria-expanded", "false");
155
+
156
+ var itemWidths = items.map(function (el) { return el.offsetWidth; });
157
+ var moreWidth = moreContainer.offsetWidth;
158
+ var navGap = parseFloat(getComputedStyle(nav).columnGap) || 0;
159
+ var available = nav.clientWidth;
160
+
161
+ if (available <= 0) {
162
+ moreContainer.style.display = "none";
163
+ return;
164
+ }
165
+
166
+ var total = 0;
167
+ for (var i = 0; i < itemWidths.length; i++) {
168
+ total += itemWidths[i] + (i > 0 ? navGap : 0);
169
+ }
170
+
171
+ if (total <= available) {
172
+ moreContainer.style.display = "none";
173
+ return;
174
+ }
175
+
176
+ var used = 0;
177
+ var cutoffIndex = 0;
178
+
179
+ for (var i2 = 0; i2 < items.length; i2++) {
180
+ var w = itemWidths[i2] + (i2 > 0 ? navGap : 0);
181
+ if (used + w > available - moreWidth - navGap) break;
182
+ used += w;
183
+ cutoffIndex = i2 + 1;
184
+ }
185
+
186
+ for (var i3 = cutoffIndex; i3 < items.length; i3++) {
187
+ items[i3].style.display = "none";
188
+ }
189
+
190
+ for (var i4 = cutoffIndex; i4 < items.length; i4++) {
191
+ var el = items[i4];
192
+ var isDropdown = el.hasAttribute("data-nav-item-dropdown");
193
+
194
+ if (isDropdown) {
195
+ var parentLink = el.querySelector(":scope > a");
196
+ var childLinks = el.querySelectorAll(":scope > div a");
197
+ if (parentLink) {
198
+ var li = document.createElement("li");
199
+ var a = document.createElement("a");
200
+ a.href = parentLink.href;
201
+ var parentText = parentLink.textContent ? parentLink.textContent.trim().replace(/\\s+/g, " ") : "";
202
+ a.textContent = parentText;
203
+ a.className = "block px-hsp-md py-vsp-2xs text-small font-bold hover:bg-accent/10 hover:underline focus-visible:underline focus-visible:text-accent text-fg hover:text-accent";
204
+ if (parentLink.getAttribute("aria-current") === "page") {
205
+ a.className += " text-accent";
206
+ }
207
+ li.appendChild(a);
208
+ moreMenu.appendChild(li);
209
+ }
210
+ childLinks.forEach(function (child) {
211
+ var li = document.createElement("li");
212
+ var a = document.createElement("a");
213
+ a.href = child.href;
214
+ a.textContent = child.textContent ? child.textContent.trim() : "";
215
+ var isChildActive = child.hasAttribute("data-active");
216
+ a.className = isChildActive
217
+ ? "block pl-hsp-xl pr-hsp-md py-vsp-2xs text-small font-bold text-accent hover:bg-accent/10 hover:underline focus-visible:underline"
218
+ : "block pl-hsp-xl pr-hsp-md py-vsp-2xs text-small text-fg hover:bg-accent/10 hover:text-accent hover:underline focus-visible:underline focus-visible:text-accent";
219
+ li.appendChild(a);
220
+ moreMenu.appendChild(li);
221
+ });
222
+ } else {
223
+ var anchor = el;
224
+ var li2 = document.createElement("li");
225
+ var a2 = document.createElement("a");
226
+ a2.href = anchor.href;
227
+ a2.textContent = anchor.textContent ? anchor.textContent.trim() : "";
228
+ a2.className = "block px-hsp-md py-vsp-2xs text-small hover:bg-accent/10 hover:underline focus-visible:underline focus-visible:text-accent text-fg hover:text-accent";
229
+ if (anchor.getAttribute("aria-current") === "page") {
230
+ a2.className += " font-bold text-accent";
231
+ }
232
+ li2.appendChild(a2);
233
+ moreMenu.appendChild(li2);
234
+ }
235
+ }
236
+ }
237
+
238
+ moreToggle.addEventListener("click", function () {
239
+ var isOpen = !moreMenu.classList.contains("hidden");
240
+ moreMenu.classList.toggle("hidden", isOpen);
241
+ moreToggle.setAttribute("aria-expanded", String(!isOpen));
242
+ }, { signal: controller.signal });
243
+
244
+ document.addEventListener("click", function (e) {
245
+ if (!moreContainer.contains(e.target)) {
246
+ moreMenu.classList.add("hidden");
247
+ moreToggle.setAttribute("aria-expanded", "false");
248
+ }
249
+ }, { signal: controller.signal });
250
+
251
+ document.addEventListener("keydown", function (e) {
252
+ if (e.key !== "Escape") return;
253
+ if (!moreMenu.classList.contains("hidden")) {
254
+ moreMenu.classList.add("hidden");
255
+ moreToggle.setAttribute("aria-expanded", "false");
256
+ moreToggle.focus();
257
+ return;
258
+ }
259
+ var active = document.activeElement;
260
+ var dropdown = active && active.closest ? active.closest("[data-nav-item-dropdown]") : null;
261
+ if (dropdown && active && active.blur) {
262
+ active.blur();
263
+ }
264
+ }, { signal: controller.signal });
265
+
266
+ var dropdowns = nav.querySelectorAll("[data-nav-item-dropdown]");
267
+ dropdowns.forEach(function (dd) {
268
+ var trigger = dd.querySelector(":scope > a");
269
+ if (!trigger) return;
270
+ function setExpanded(v) {
271
+ trigger.setAttribute("aria-expanded", String(v));
272
+ }
273
+ dd.addEventListener("mouseenter", function () { setExpanded(true); }, { signal: controller.signal });
274
+ dd.addEventListener("mouseleave", function () { setExpanded(false); }, { signal: controller.signal });
275
+ dd.addEventListener("focusin", function () { setExpanded(true); }, { signal: controller.signal });
276
+ dd.addEventListener("focusout", function (e) {
277
+ if (!dd.contains(e.relatedTarget)) {
278
+ setExpanded(false);
279
+ }
280
+ }, { signal: controller.signal });
281
+ });
282
+
283
+ var ro = new ResizeObserver(update);
284
+ ro.observe(nav);
285
+ controller.signal.addEventListener("abort", function () { ro.disconnect(); });
286
+
287
+ document.fonts.ready.then(update);
288
+
289
+ update();
290
+
291
+ cleanupNavOverflow = function () { controller.abort(); };
292
+ }
293
+
294
+ initNavOverflow();
295
+ document.addEventListener("zfb:after-swap", initNavOverflow);
296
+ })();`;
297
+ }
298
+ const NAV_OVERFLOW_SCRIPT = buildNavOverflowScript();
299
+ export {
300
+ NAV_OVERFLOW_SCRIPT,
301
+ buildNavOverflowScript
302
+ };
@@ -1 +1 @@
1
- export declare const NAV_OVERFLOW_SCRIPT: string;
1
+ export { NAV_OVERFLOW_SCRIPT } from "./nav-overflow-generated-script.js";
@@ -1,289 +1,4 @@
1
- import { AFTER_NAVIGATE_EVENT } from "../transitions/page-events.js";
2
- import {
3
- NAV_CHEVRON_ACTIVE,
4
- NAV_CHEVRON_INACTIVE,
5
- NAV_CHILD_ACTIVE,
6
- NAV_CHILD_INACTIVE,
7
- NAV_MENU_CHILD_ACTIVE,
8
- NAV_MENU_CHILD_INACTIVE,
9
- NAV_MENU_PARENT,
10
- NAV_MENU_PARENT_ACTIVE_SUFFIX,
11
- NAV_MENU_PLAIN,
12
- NAV_MENU_PLAIN_ACTIVE_SUFFIX,
13
- NAV_TOP_ACTIVE,
14
- NAV_TOP_INACTIVE
15
- } from "./nav-class-tokens.js";
16
- const clsArgs = (tokens) => tokens.map((token) => JSON.stringify(token)).join(", ");
17
- const clsLiteral = (tokens) => JSON.stringify(tokens.join(" "));
18
- const clsAppend = (tokens) => JSON.stringify(" " + tokens.join(" "));
19
- const NAV_OVERFLOW_SCRIPT = `(function () {
20
- var cleanupNavOverflow = null;
21
-
22
- function trimSlashes(p) {
23
- while (p.length > 1 && p.charAt(p.length - 1) === "/") p = p.slice(0, -1);
24
- return p || "/";
25
- }
26
-
27
- function navPathname(a) {
28
- try { return trimSlashes(new URL(a.href, location.href).pathname); }
29
- catch (e) { return ""; }
30
- }
31
-
32
- function isUnderPath(cur, p) {
33
- if (!p) return false;
34
- if (cur === p) return true;
35
- return p !== "/" && cur.indexOf(p + "/") === 0;
36
- }
37
-
38
- // Recompute which header nav item is "active" from the CURRENT URL and
39
- // repaint the highlight. SSR sets the active item on first paint, but the
40
- // header is persisted across same-locale client-router swaps
41
- // (data-zfb-transition-persist), so without this the highlight would stay
42
- // frozen on the page where the header was first rendered. Mirrors the
43
- // sidebar island's client-side approach (match location.pathname against
44
- // each entry's href) and the SSR longest-match + dropdown-parent rules.
45
- // URL-based: hrefs and location.pathname both carry the base + locale
46
- // prefix, so they compare directly without stripping.
47
- function applyActiveNav() {
48
- var nav = document.querySelector("[data-header-nav]");
49
- if (!nav) return;
50
- var topItems = Array.from(nav.querySelectorAll(":scope > [data-nav-item]"));
51
- if (topItems.length === 0) return;
52
-
53
- var cur = trimSlashes(location.pathname);
54
-
55
- // Deepest (longest) nav path the current URL lives under, across both
56
- // top-level and dropdown-child paths \u2014 matches computeActiveNavPath.
57
- var activePath = "";
58
- topItems.forEach(function (it) {
59
- var isDropdown = it.hasAttribute("data-nav-item-dropdown");
60
- var topA = isDropdown ? it.querySelector(":scope > a") : it;
61
- if (topA) {
62
- var tp = navPathname(topA);
63
- if (isUnderPath(cur, tp) && tp.length > activePath.length) activePath = tp;
64
- }
65
- if (isDropdown) {
66
- it.querySelectorAll(":scope > div a").forEach(function (c) {
67
- var cp = navPathname(c);
68
- if (isUnderPath(cur, cp) && cp.length > activePath.length) activePath = cp;
69
- });
70
- }
71
- });
72
-
73
- function setTopActive(a, active) {
74
- if (!a) return;
75
- if (active) {
76
- a.classList.add(${clsArgs(NAV_TOP_ACTIVE)});
77
- a.classList.remove(${clsArgs(NAV_TOP_INACTIVE)});
78
- a.setAttribute("aria-current", "page");
79
- } else {
80
- a.classList.remove(${clsArgs(NAV_TOP_ACTIVE)});
81
- a.classList.add(${clsArgs(NAV_TOP_INACTIVE)});
82
- a.removeAttribute("aria-current");
83
- }
84
- }
85
-
86
- topItems.forEach(function (it) {
87
- var isDropdown = it.hasAttribute("data-nav-item-dropdown");
88
- var topA = isDropdown ? it.querySelector(":scope > a") : it;
89
- var topActive = false;
90
-
91
- if (isDropdown) {
92
- var parentMatch = !!topA && navPathname(topA) === activePath && activePath !== "";
93
- var anyChild = false;
94
- it.querySelectorAll(":scope > div a").forEach(function (c) {
95
- var childActive = navPathname(c) === activePath && activePath !== "";
96
- if (childActive) {
97
- anyChild = true;
98
- c.setAttribute("data-active", "");
99
- c.classList.add(${clsArgs(NAV_CHILD_ACTIVE)});
100
- c.classList.remove(${clsArgs(NAV_CHILD_INACTIVE)});
101
- } else {
102
- c.removeAttribute("data-active");
103
- c.classList.remove(${clsArgs(NAV_CHILD_ACTIVE)});
104
- c.classList.add(${clsArgs(NAV_CHILD_INACTIVE)});
105
- }
106
- });
107
- topActive = parentMatch || anyChild;
108
- var svg = topA ? topA.querySelector("svg") : null;
109
- if (svg) {
110
- if (topActive) { svg.classList.add(${clsArgs(NAV_CHEVRON_ACTIVE)}); svg.classList.remove(${clsArgs(NAV_CHEVRON_INACTIVE)}); }
111
- else { svg.classList.add(${clsArgs(NAV_CHEVRON_INACTIVE)}); svg.classList.remove(${clsArgs(NAV_CHEVRON_ACTIVE)}); }
112
- }
113
- } else {
114
- topActive = activePath !== "" && navPathname(topA) === activePath;
115
- }
116
-
117
- setTopActive(topA, topActive);
118
- });
119
- }
120
-
121
- function initNavOverflow() {
122
- if (cleanupNavOverflow) cleanupNavOverflow();
123
-
124
- // Repaint the active highlight for the current URL before measuring /
125
- // cloning, so the overflow "\xB7\xB7\xB7" menu mirrors the correct active state.
126
- applyActiveNav();
127
-
128
- var nav = document.querySelector("[data-header-nav]");
129
- var moreContainer = document.querySelector("[data-nav-more]");
130
- var moreMenu = document.querySelector("[data-nav-more-menu]");
131
- var moreToggle = document.querySelector("[data-nav-more-toggle]");
132
- if (!nav || !moreContainer || !moreMenu || !moreToggle) return;
133
-
134
- var items = Array.from(nav.querySelectorAll(":scope > [data-nav-item]"));
135
- if (items.length === 0) return;
136
-
137
- var controller = new AbortController();
138
-
139
- function update() {
140
- items.forEach(function (el) { el.style.display = ""; });
141
- moreContainer.style.display = "";
142
- moreMenu.innerHTML = "";
143
- moreMenu.classList.add("hidden");
144
- moreToggle.setAttribute("aria-expanded", "false");
145
-
146
- var itemWidths = items.map(function (el) { return el.offsetWidth; });
147
- var moreWidth = moreContainer.offsetWidth;
148
- var navGap = parseFloat(getComputedStyle(nav).columnGap) || 0;
149
- var available = nav.clientWidth;
150
-
151
- if (available <= 0) {
152
- moreContainer.style.display = "none";
153
- return;
154
- }
155
-
156
- var total = 0;
157
- for (var i = 0; i < itemWidths.length; i++) {
158
- total += itemWidths[i] + (i > 0 ? navGap : 0);
159
- }
160
-
161
- if (total <= available) {
162
- moreContainer.style.display = "none";
163
- return;
164
- }
165
-
166
- var used = 0;
167
- var cutoffIndex = 0;
168
-
169
- for (var i2 = 0; i2 < items.length; i2++) {
170
- var w = itemWidths[i2] + (i2 > 0 ? navGap : 0);
171
- if (used + w > available - moreWidth - navGap) break;
172
- used += w;
173
- cutoffIndex = i2 + 1;
174
- }
175
-
176
- for (var i3 = cutoffIndex; i3 < items.length; i3++) {
177
- items[i3].style.display = "none";
178
- }
179
-
180
- for (var i4 = cutoffIndex; i4 < items.length; i4++) {
181
- var el = items[i4];
182
- var isDropdown = el.hasAttribute("data-nav-item-dropdown");
183
-
184
- if (isDropdown) {
185
- var parentLink = el.querySelector(":scope > a");
186
- var childLinks = el.querySelectorAll(":scope > div a");
187
- if (parentLink) {
188
- var li = document.createElement("li");
189
- var a = document.createElement("a");
190
- a.href = parentLink.href;
191
- var parentText = parentLink.textContent ? parentLink.textContent.trim().replace(/\\s+/g, " ") : "";
192
- a.textContent = parentText;
193
- a.className = ${clsLiteral(NAV_MENU_PARENT)};
194
- if (parentLink.getAttribute("aria-current") === "page") {
195
- a.className += ${clsAppend(NAV_MENU_PARENT_ACTIVE_SUFFIX)};
196
- }
197
- li.appendChild(a);
198
- moreMenu.appendChild(li);
199
- }
200
- childLinks.forEach(function (child) {
201
- var li = document.createElement("li");
202
- var a = document.createElement("a");
203
- a.href = child.href;
204
- a.textContent = child.textContent ? child.textContent.trim() : "";
205
- var isChildActive = child.hasAttribute("data-active");
206
- a.className = isChildActive
207
- ? ${clsLiteral(NAV_MENU_CHILD_ACTIVE)}
208
- : ${clsLiteral(NAV_MENU_CHILD_INACTIVE)};
209
- li.appendChild(a);
210
- moreMenu.appendChild(li);
211
- });
212
- } else {
213
- var anchor = el;
214
- var li2 = document.createElement("li");
215
- var a2 = document.createElement("a");
216
- a2.href = anchor.href;
217
- a2.textContent = anchor.textContent ? anchor.textContent.trim() : "";
218
- a2.className = ${clsLiteral(NAV_MENU_PLAIN)};
219
- if (anchor.getAttribute("aria-current") === "page") {
220
- a2.className += ${clsAppend(NAV_MENU_PLAIN_ACTIVE_SUFFIX)};
221
- }
222
- li2.appendChild(a2);
223
- moreMenu.appendChild(li2);
224
- }
225
- }
226
- }
227
-
228
- moreToggle.addEventListener("click", function () {
229
- var isOpen = !moreMenu.classList.contains("hidden");
230
- moreMenu.classList.toggle("hidden", isOpen);
231
- moreToggle.setAttribute("aria-expanded", String(!isOpen));
232
- }, { signal: controller.signal });
233
-
234
- document.addEventListener("click", function (e) {
235
- if (!moreContainer.contains(e.target)) {
236
- moreMenu.classList.add("hidden");
237
- moreToggle.setAttribute("aria-expanded", "false");
238
- }
239
- }, { signal: controller.signal });
240
-
241
- document.addEventListener("keydown", function (e) {
242
- if (e.key !== "Escape") return;
243
- if (!moreMenu.classList.contains("hidden")) {
244
- moreMenu.classList.add("hidden");
245
- moreToggle.setAttribute("aria-expanded", "false");
246
- moreToggle.focus();
247
- return;
248
- }
249
- var active = document.activeElement;
250
- var dropdown = active && active.closest ? active.closest("[data-nav-item-dropdown]") : null;
251
- if (dropdown && active && active.blur) {
252
- active.blur();
253
- }
254
- }, { signal: controller.signal });
255
-
256
- var dropdowns = nav.querySelectorAll("[data-nav-item-dropdown]");
257
- dropdowns.forEach(function (dd) {
258
- var trigger = dd.querySelector(":scope > a");
259
- if (!trigger) return;
260
- function setExpanded(v) {
261
- trigger.setAttribute("aria-expanded", String(v));
262
- }
263
- dd.addEventListener("mouseenter", function () { setExpanded(true); }, { signal: controller.signal });
264
- dd.addEventListener("mouseleave", function () { setExpanded(false); }, { signal: controller.signal });
265
- dd.addEventListener("focusin", function () { setExpanded(true); }, { signal: controller.signal });
266
- dd.addEventListener("focusout", function (e) {
267
- if (!dd.contains(e.relatedTarget)) {
268
- setExpanded(false);
269
- }
270
- }, { signal: controller.signal });
271
- });
272
-
273
- var ro = new ResizeObserver(update);
274
- ro.observe(nav);
275
- controller.signal.addEventListener("abort", function () { ro.disconnect(); });
276
-
277
- document.fonts.ready.then(update);
278
-
279
- update();
280
-
281
- cleanupNavOverflow = function () { controller.abort(); };
282
- }
283
-
284
- initNavOverflow();
285
- document.addEventListener(${JSON.stringify(AFTER_NAVIGATE_EVENT)}, initNavOverflow);
286
- })();`;
1
+ import { NAV_OVERFLOW_SCRIPT } from "./nav-overflow-generated-script.js";
287
2
  export {
288
3
  NAV_OVERFLOW_SCRIPT
289
4
  };
@@ -12,7 +12,8 @@ import { assertChromeContext } from "../chrome/assert-chrome-context.js";
12
12
  import {
13
13
  deriveGetUnavailableVersions,
14
14
  deriveNavDataPrep,
15
- deriveSearchWidgetSlot
15
+ deriveSearchWidgetSlot,
16
+ skipsPackageDefaultDesignTokenPanel
16
17
  } from "../chrome/derive.js";
17
18
  function createHeaderWithDefaults(ctx) {
18
19
  assertChromeContext(ctx, "createHeaderWithDefaults");
@@ -130,7 +131,15 @@ function createHeaderWithDefaults(ctx) {
130
131
  const headerRightItems = filterHeaderRightItems(
131
132
  settings.headerRightItems ?? [],
132
133
  {
133
- designTokenPanel: Boolean(settings.designTokenPanel),
134
+ // Mirrors `deriveBodyEndIslands`' slot resolution (#3414): when the
135
+ // derive-level skip leaves a page with no panel island and no
136
+ // pre-hydration toggle shim, the header toggle button must go with
137
+ // them — otherwise it dispatches `toggle-design-token-panel` into a
138
+ // document with no listener and no click queue (a dead button).
139
+ // `hostBindings.DesignTokenPanelBootstrap` covers the injected-route
140
+ // path too (`routes/_chrome.tsx` threads the configured island through
141
+ // that slot), so injected pages keep the button.
142
+ designTokenPanel: Boolean(settings.designTokenPanel) && (ctx.hostBindings.DesignTokenPanelBootstrap != null || !skipsPackageDefaultDesignTokenPanel(ctx.settings)),
134
143
  aiAssistant: Boolean(settings.aiAssistant),
135
144
  colorMode: Boolean(settings.colorMode),
136
145
  hasLocales: Object.keys(settings.locales).length > 0,
@@ -40,6 +40,12 @@ export declare function switchLocaleHref(pathname: string, config: LanguageSwitc
40
40
  * `window[FLAG]` makes it idempotent: the tag may re-execute on a hard reload
41
41
  * or a cross-locale header repaint, but the listener is registered exactly
42
42
  * once per page lifetime.
43
+ *
44
+ * The pathname fed to `switchLocaleHref` comes from the embedded
45
+ * `readCurrentPath`, which prefers the `data-zd-current-path` override over
46
+ * `location.pathname` — the same explicit current-route reader
47
+ * `nav-overflow-script.ts` / `sidebar-tree-island` / `version-switcher.tsx`
48
+ * use (zudolab/zudo-doc#3398, consolidated by #3408).
43
49
  */
44
50
  export declare const LANGUAGE_SWITCHER_INIT_SCRIPT: string;
45
51
  export interface LanguageSwitcherProps {
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs } from "preact/jsx-runtime";
2
2
  import { Fragment } from "preact";
3
3
  import { AFTER_NAVIGATE_EVENT } from "../transitions/index.js";
4
+ import { CURRENT_PATH_SCRIPT_PRELUDE } from "../current-path/index.js";
4
5
  function switchLocaleHref(pathname, config, currentLang, targetLang) {
5
6
  const normalizedBase = config.base;
6
7
  const defaultLocale = config.defaultLocale;
@@ -45,6 +46,7 @@ const LANGUAGE_SWITCHER_INIT_SCRIPT = `(function(){
45
46
  var FLAG="__zdLanguageSwitcherInit";
46
47
  if(window[FLAG])return;
47
48
  window[FLAG]=true;
49
+ ${CURRENT_PATH_SCRIPT_PRELUDE}
48
50
  var switchLocaleHref=${switchLocaleHref.toString()};
49
51
  function rewire(){
50
52
  var containers=document.querySelectorAll("[data-language-switcher]");
@@ -57,7 +59,7 @@ for(var j=0;j<anchors.length;j++){
57
59
  var a=anchors[j];
58
60
  var target=a.getAttribute("lang");
59
61
  if(!target)continue;
60
- a.setAttribute("href",switchLocaleHref(window.location.pathname,config,currentLang,target));
62
+ a.setAttribute("href",switchLocaleHref(readCurrentPath(CURRENT_PATH_DATASET_KEY),config,currentLang,target));
61
63
  }
62
64
  }
63
65
  }
@@ -208,6 +208,12 @@ export declare const VERSION_SWITCHER_INIT_SCRIPT: string;
208
208
  * `window[FLAG]` makes it idempotent: the tag may re-execute on a hard reload or
209
209
  * a cross-locale header repaint, but the listener registers exactly once per
210
210
  * page lifetime.
211
+ *
212
+ * The pathname fed to `computeVersionSwitcherState` comes from the embedded
213
+ * `readCurrentPath`, which prefers the `data-zd-current-path` override over
214
+ * `location.pathname` — the same explicit current-route reader
215
+ * `nav-overflow-script.ts` / `sidebar-tree-island` / `language-switcher.tsx`
216
+ * use (zudolab/zudo-doc#3398, consolidated by #3408).
211
217
  */
212
218
  export declare const VERSION_SWITCHER_REWIRE_SCRIPT: string;
213
219
  export type { VersionEntry, VersionSwitcherLabels };