@dreamlake/dockit 0.1.1
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/components/Callout.d.ts +11 -0
- package/dist/components/Callout.js +101 -0
- package/dist/components/ClientOnly.d.ts +4 -0
- package/dist/components/ClientOnly.js +11 -0
- package/dist/components/CodeBlock.d.ts +13 -0
- package/dist/components/CodeBlock.js +155 -0
- package/dist/components/DocFooter.d.ts +1 -0
- package/dist/components/DocFooter.js +63 -0
- package/dist/components/Preview.d.ts +16 -0
- package/dist/components/Preview.js +220 -0
- package/dist/components/SearchPalette.d.ts +8 -0
- package/dist/components/SearchPalette.js +678 -0
- package/dist/components/SearchResize.d.ts +11 -0
- package/dist/components/SearchResize.js +150 -0
- package/dist/components/Sidebar.d.ts +1 -0
- package/dist/components/Sidebar.js +134 -0
- package/dist/components/StatusTable.d.ts +19 -0
- package/dist/components/StatusTable.js +251 -0
- package/dist/components/TOC.d.ts +1 -0
- package/dist/components/TOC.js +674 -0
- package/dist/components/TabStrip.d.ts +8 -0
- package/dist/components/TabStrip.js +105 -0
- package/dist/components/ThemeProvider.d.ts +11 -0
- package/dist/components/ThemeProvider.js +40 -0
- package/dist/components/ThemeToggle.d.ts +2 -0
- package/dist/components/ThemeToggle.js +109 -0
- package/dist/components/Topbar.d.ts +9 -0
- package/dist/components/Topbar.js +818 -0
- package/dist/components/mdx-components.d.ts +30 -0
- package/dist/components/mdx-components.js +346 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +81 -0
- package/dist/lib/navigation.d.ts +80 -0
- package/dist/lib/navigation.js +57 -0
- package/dist/lib/pagefind-search.d.ts +21 -0
- package/dist/lib/pagefind-search.js +201 -0
- package/dist/lib/search-index.d.ts +43 -0
- package/dist/lib/search-index.js +112 -0
- package/dist/lib/tabs.d.ts +23 -0
- package/dist/lib/tabs.js +30 -0
- package/dist/lib/use-hidden-toggle.d.ts +15 -0
- package/dist/lib/use-hidden-toggle.js +23 -0
- package/dist/lib/use-line-numbers.d.ts +9 -0
- package/dist/lib/use-line-numbers.js +7 -0
- package/dist/lib/use-local-storage.d.ts +15 -0
- package/dist/lib/use-local-storage.js +58 -0
- package/dist/lib/use-media-query.d.ts +5 -0
- package/dist/lib/use-media-query.js +16 -0
- package/dist/renderer/Layout.d.ts +5 -0
- package/dist/renderer/Layout.js +170 -0
- package/dist/renderer/onRenderClient.d.ts +1 -0
- package/dist/renderer/onRenderClient.js +23 -0
- package/dist/renderer/onRenderHtml.d.ts +5 -0
- package/dist/renderer/onRenderHtml.js +44 -0
- package/dist/site-config.d.ts +61 -0
- package/dist/site-config.js +21 -0
- package/dist/styles.css +310 -0
- package/dist/vike.d.ts +12 -0
- package/dist/vike.js +8 -0
- package/dist/vite.d.ts +2 -0
- package/dist/vite.js +80 -0
- package/package.json +82 -0
- package/templates/netlify.example.toml +33 -0
- package/templates/set-version.mjs +70 -0
- package/templates/version-branch.sh +16 -0
- package/templates/versions.example.json +15 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef, useEffect, useMemo } from "react";
|
|
3
|
+
import { usePageContext } from "vike-react/usePageContext";
|
|
4
|
+
import { pages } from "../lib/navigation.js";
|
|
5
|
+
import { siteConfig } from "../site-config.js";
|
|
6
|
+
const TOC_KEY_PREFIX = "toc-collapsed:";
|
|
7
|
+
const X0 = 4;
|
|
8
|
+
const X_INDENT_H3 = 12;
|
|
9
|
+
const BEND = 8;
|
|
10
|
+
const ACTIVATE_LINE = 110;
|
|
11
|
+
const TWEEN_MS = 600;
|
|
12
|
+
function easeOut(t) {
|
|
13
|
+
return 1 - Math.pow(1 - t, 3);
|
|
14
|
+
}
|
|
15
|
+
function animateScrollTo(targetY) {
|
|
16
|
+
const startY = window.scrollY;
|
|
17
|
+
const distance = targetY - startY;
|
|
18
|
+
if (Math.abs(distance) < 1) return;
|
|
19
|
+
const duration = Math.min(700, Math.max(260, Math.abs(distance) * 0.35));
|
|
20
|
+
const start = performance.now();
|
|
21
|
+
let cancelled = false;
|
|
22
|
+
const cancel = () => {
|
|
23
|
+
cancelled = true;
|
|
24
|
+
};
|
|
25
|
+
window.addEventListener("wheel", cancel, { passive: true, once: true });
|
|
26
|
+
window.addEventListener("touchstart", cancel, { passive: true, once: true });
|
|
27
|
+
function step(now) {
|
|
28
|
+
if (cancelled) return;
|
|
29
|
+
const t = Math.min(1, (now - start) / duration);
|
|
30
|
+
const eased = t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
31
|
+
window.scrollTo(0, startY + distance * eased);
|
|
32
|
+
if (t < 1) {
|
|
33
|
+
requestAnimationFrame(step);
|
|
34
|
+
} else {
|
|
35
|
+
window.removeEventListener("wheel", cancel);
|
|
36
|
+
window.removeEventListener("touchstart", cancel);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
requestAnimationFrame(step);
|
|
40
|
+
}
|
|
41
|
+
function scrollToHeading(e, id) {
|
|
42
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
|
|
43
|
+
const target = document.getElementById(id);
|
|
44
|
+
if (!target) return;
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
const cs = window.getComputedStyle(target);
|
|
47
|
+
const marginTop = parseFloat(cs.scrollMarginTop) || 0;
|
|
48
|
+
const targetY = target.getBoundingClientRect().top + window.scrollY - marginTop;
|
|
49
|
+
animateScrollTo(targetY);
|
|
50
|
+
history.replaceState(null, "", `#${id}`);
|
|
51
|
+
}
|
|
52
|
+
function TOC() {
|
|
53
|
+
const { urlPathname } = usePageContext();
|
|
54
|
+
const mdHref = (() => {
|
|
55
|
+
const meta = pages.find((p) => p.path === urlPathname);
|
|
56
|
+
if (!meta || meta.noindex) return null;
|
|
57
|
+
return urlPathname === "/" ? "/index.md" : `${urlPathname}.md`;
|
|
58
|
+
})();
|
|
59
|
+
const editHref = (() => {
|
|
60
|
+
const meta = pages.find((p) => p.path === urlPathname);
|
|
61
|
+
if (!meta) return null;
|
|
62
|
+
const slug = urlPathname === "/" ? "index" : urlPathname.replace(/^\//, "");
|
|
63
|
+
const pagesPath = siteConfig.docsPagesPath ?? "docs/pages";
|
|
64
|
+
return `${siteConfig.docsRepoUrl}/edit/${siteConfig.docsBranch}/${pagesPath}/${slug}/+Page.mdx`;
|
|
65
|
+
})();
|
|
66
|
+
const issueHref = `${siteConfig.docsRepoUrl}/issues/new`;
|
|
67
|
+
const [headings, setHeadings] = useState([]);
|
|
68
|
+
const [endPos, setEndPos] = useState(null);
|
|
69
|
+
const [pathD, setPathD] = useState("");
|
|
70
|
+
const bodyRef = useRef(null);
|
|
71
|
+
const railBaseRef = useRef(null);
|
|
72
|
+
const activeStrokeRef = useRef(null);
|
|
73
|
+
const dotRef = useRef(null);
|
|
74
|
+
const gradientRef = useRef(null);
|
|
75
|
+
const railPointsRef = useRef([]);
|
|
76
|
+
const totalLenRef = useRef(0);
|
|
77
|
+
const currentLenRef = useRef(0);
|
|
78
|
+
const currentStartRef = useRef(0);
|
|
79
|
+
const animFromRef = useRef(0);
|
|
80
|
+
const animToRef = useRef(0);
|
|
81
|
+
const startAnimFromRef = useRef(0);
|
|
82
|
+
const startAnimToRef = useRef(0);
|
|
83
|
+
const animStartRef = useRef(0);
|
|
84
|
+
const animReqRef = useRef(null);
|
|
85
|
+
const activeIdRef = useRef(null);
|
|
86
|
+
const [collapsedH2s, setCollapsedH2s] = useState(() => {
|
|
87
|
+
if (typeof window === "undefined") return /* @__PURE__ */ new Set();
|
|
88
|
+
try {
|
|
89
|
+
return new Set(JSON.parse(localStorage.getItem(TOC_KEY_PREFIX + urlPathname) || "[]"));
|
|
90
|
+
} catch {
|
|
91
|
+
return /* @__PURE__ */ new Set();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const [foldVersion, setFoldVersion] = useState(0);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
try {
|
|
97
|
+
const stored = JSON.parse(localStorage.getItem(TOC_KEY_PREFIX + urlPathname) || "[]");
|
|
98
|
+
setCollapsedH2s(new Set(stored));
|
|
99
|
+
} catch {
|
|
100
|
+
setCollapsedH2s(/* @__PURE__ */ new Set());
|
|
101
|
+
}
|
|
102
|
+
}, [urlPathname]);
|
|
103
|
+
function toggleH2(id) {
|
|
104
|
+
setCollapsedH2s((prev) => {
|
|
105
|
+
const next = new Set(prev);
|
|
106
|
+
if (next.has(id)) next.delete(id);
|
|
107
|
+
else next.add(id);
|
|
108
|
+
localStorage.setItem(TOC_KEY_PREFIX + urlPathname, JSON.stringify([...next]));
|
|
109
|
+
return next;
|
|
110
|
+
});
|
|
111
|
+
setFoldVersion((v) => v + 1);
|
|
112
|
+
}
|
|
113
|
+
const h2HasChildren = useMemo(() => {
|
|
114
|
+
const set = /* @__PURE__ */ new Set();
|
|
115
|
+
let lastH2 = null;
|
|
116
|
+
for (const h of headings) {
|
|
117
|
+
if (h.level === 2) lastH2 = h.id;
|
|
118
|
+
else if (lastH2) set.add(lastH2);
|
|
119
|
+
}
|
|
120
|
+
return set;
|
|
121
|
+
}, [headings]);
|
|
122
|
+
const visibleHeadings = useMemo(() => {
|
|
123
|
+
const result = [];
|
|
124
|
+
let lastH2Id = null;
|
|
125
|
+
for (const h of headings) {
|
|
126
|
+
if (h.level === 2) {
|
|
127
|
+
lastH2Id = h.id;
|
|
128
|
+
result.push(h);
|
|
129
|
+
} else if (lastH2Id && !collapsedH2s.has(lastH2Id)) {
|
|
130
|
+
result.push(h);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}, [headings, collapsedH2s]);
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const main = document.querySelector("main.doc-content");
|
|
137
|
+
if (!main) {
|
|
138
|
+
setHeadings([]);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const current = pages.find((p) => p.path === urlPathname);
|
|
142
|
+
const tocLevel = current?.tocLevel ?? 3;
|
|
143
|
+
const selector = tocLevel >= 3 ? "[data-toc-anchor], h3[id]" : "[data-toc-anchor]";
|
|
144
|
+
function collect() {
|
|
145
|
+
const nodes = Array.from(
|
|
146
|
+
main.querySelectorAll(selector)
|
|
147
|
+
);
|
|
148
|
+
setHeadings(
|
|
149
|
+
nodes.map((el) => {
|
|
150
|
+
const isAnchor = el.hasAttribute("data-toc-anchor");
|
|
151
|
+
const textSource = isAnchor ? el.nextElementSibling : el;
|
|
152
|
+
return {
|
|
153
|
+
id: el.id,
|
|
154
|
+
text: textSource?.textContent?.replace(/#$/, "").trim() ?? "",
|
|
155
|
+
level: isAnchor ? 2 : 3,
|
|
156
|
+
// `el` drives scroll-spy (rect.top vs ACTIVATE_LINE). Always
|
|
157
|
+
// pick a non-sticky element: the anchor span for H2, the
|
|
158
|
+
// h3 itself for H3 (h3 is not sticky).
|
|
159
|
+
el
|
|
160
|
+
};
|
|
161
|
+
})
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
collect();
|
|
165
|
+
const mo = new MutationObserver(collect);
|
|
166
|
+
mo.observe(main, { childList: true, subtree: true });
|
|
167
|
+
return () => mo.disconnect();
|
|
168
|
+
}, [urlPathname]);
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
if (headings.length === 0 || !bodyRef.current) {
|
|
171
|
+
railPointsRef.current = [];
|
|
172
|
+
totalLenRef.current = 0;
|
|
173
|
+
currentLenRef.current = 0;
|
|
174
|
+
animFromRef.current = 0;
|
|
175
|
+
animToRef.current = 0;
|
|
176
|
+
setPathD("");
|
|
177
|
+
setEndPos(null);
|
|
178
|
+
applyRailDOM(0, 0);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
function buildRail() {
|
|
182
|
+
const body = bodyRef.current;
|
|
183
|
+
const base = railBaseRef.current;
|
|
184
|
+
if (!body || !base) return;
|
|
185
|
+
const links = Array.from(body.querySelectorAll("ul[data-toc-list] a"));
|
|
186
|
+
if (links.length === 0) return;
|
|
187
|
+
const bodyRect = body.getBoundingClientRect();
|
|
188
|
+
const rows = links.map((a) => {
|
|
189
|
+
const li = a.parentElement;
|
|
190
|
+
const r = a.getBoundingClientRect();
|
|
191
|
+
const indent = li.dataset.level === "3" ? X_INDENT_H3 : 0;
|
|
192
|
+
return {
|
|
193
|
+
id: a.getAttribute("href").slice(1),
|
|
194
|
+
top: r.top - bodyRect.top,
|
|
195
|
+
h: r.height,
|
|
196
|
+
indent
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
let d = "";
|
|
200
|
+
const startY = rows[0].top + 4;
|
|
201
|
+
const startX = X0 + rows[0].indent;
|
|
202
|
+
d += `M ${startX} ${startY}`;
|
|
203
|
+
for (let i = 1; i < rows.length; i++) {
|
|
204
|
+
const prev = rows[i - 1];
|
|
205
|
+
const cur = rows[i];
|
|
206
|
+
const prevX = X0 + prev.indent;
|
|
207
|
+
const curX = X0 + cur.indent;
|
|
208
|
+
const midY = cur.top + 4;
|
|
209
|
+
if (prevX === curX) {
|
|
210
|
+
d += ` L ${curX} ${midY}`;
|
|
211
|
+
} else {
|
|
212
|
+
const bendStart = midY - BEND;
|
|
213
|
+
const bendEnd = midY + 2;
|
|
214
|
+
d += ` L ${prevX} ${bendStart}`;
|
|
215
|
+
d += ` C ${prevX} ${bendStart + BEND * 0.6}, ${curX} ${bendStart + BEND * 0.4}, ${curX} ${bendEnd}`;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const lastRow = rows[rows.length - 1];
|
|
219
|
+
const endY = lastRow.top + lastRow.h / 2;
|
|
220
|
+
d += ` L ${X0 + lastRow.indent} ${endY}`;
|
|
221
|
+
setPathD(d);
|
|
222
|
+
base.setAttribute("d", d);
|
|
223
|
+
const pathLen = base.getTotalLength();
|
|
224
|
+
totalLenRef.current = pathLen;
|
|
225
|
+
const endPt = base.getPointAtLength(pathLen);
|
|
226
|
+
setEndPos({ x: endPt.x, y: endPt.y });
|
|
227
|
+
railPointsRef.current = rows.map((row) => {
|
|
228
|
+
const midY = row.top + row.h / 2;
|
|
229
|
+
let lo = 0;
|
|
230
|
+
let hi = pathLen;
|
|
231
|
+
for (let k = 0; k < 18; k++) {
|
|
232
|
+
const mid = (lo + hi) / 2;
|
|
233
|
+
const p = base.getPointAtLength(mid);
|
|
234
|
+
if (p.y < midY) lo = mid;
|
|
235
|
+
else hi = mid;
|
|
236
|
+
}
|
|
237
|
+
return { id: row.id, len: (lo + hi) / 2 };
|
|
238
|
+
});
|
|
239
|
+
const ai = activeIdRef.current;
|
|
240
|
+
if (ai) {
|
|
241
|
+
const match = railPointsRef.current.find((p) => p.id === ai);
|
|
242
|
+
if (match) {
|
|
243
|
+
snap(match.len, findParentH2Len(ai));
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
snap(0, 0);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function findParentH2Len(id) {
|
|
250
|
+
let parentH2Id = null;
|
|
251
|
+
for (const h of visibleHeadings) {
|
|
252
|
+
if (h.level === 2) parentH2Id = h.id;
|
|
253
|
+
if (h.id === id) break;
|
|
254
|
+
}
|
|
255
|
+
if (!parentH2Id) return 0;
|
|
256
|
+
const pt = railPointsRef.current.find((p) => p.id === parentH2Id);
|
|
257
|
+
return pt ? pt.len : 0;
|
|
258
|
+
}
|
|
259
|
+
function snap(len, start) {
|
|
260
|
+
currentLenRef.current = len;
|
|
261
|
+
currentStartRef.current = start;
|
|
262
|
+
animFromRef.current = len;
|
|
263
|
+
animToRef.current = len;
|
|
264
|
+
startAnimFromRef.current = start;
|
|
265
|
+
startAnimToRef.current = start;
|
|
266
|
+
applyRailDOM(start, len);
|
|
267
|
+
}
|
|
268
|
+
const raf = requestAnimationFrame(buildRail);
|
|
269
|
+
const onResize = () => buildRail();
|
|
270
|
+
window.addEventListener("resize", onResize);
|
|
271
|
+
if (document.fonts && document.fonts.ready) {
|
|
272
|
+
document.fonts.ready.then(() => buildRail());
|
|
273
|
+
}
|
|
274
|
+
return () => {
|
|
275
|
+
cancelAnimationFrame(raf);
|
|
276
|
+
window.removeEventListener("resize", onResize);
|
|
277
|
+
};
|
|
278
|
+
}, [headings, foldVersion]);
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
if (headings.length === 0) return;
|
|
281
|
+
let scheduled = false;
|
|
282
|
+
function pick() {
|
|
283
|
+
scheduled = false;
|
|
284
|
+
let id = headings[0].id;
|
|
285
|
+
for (let i = 0; i < headings.length; i++) {
|
|
286
|
+
const top = headings[i].el.getBoundingClientRect().top;
|
|
287
|
+
if (top - ACTIVATE_LINE <= 0.5) id = headings[i].id;
|
|
288
|
+
else break;
|
|
289
|
+
}
|
|
290
|
+
if (id) {
|
|
291
|
+
const h = headings.find((h2) => h2.id === id);
|
|
292
|
+
if (h && h.level === 3) {
|
|
293
|
+
let parentH2 = null;
|
|
294
|
+
for (const hh of headings) {
|
|
295
|
+
if (hh.level === 2) parentH2 = hh.id;
|
|
296
|
+
if (hh.id === id) break;
|
|
297
|
+
}
|
|
298
|
+
if (parentH2 && collapsedH2s.has(parentH2)) {
|
|
299
|
+
setCollapsedH2s((prev) => {
|
|
300
|
+
const next = new Set(prev);
|
|
301
|
+
next.delete(parentH2);
|
|
302
|
+
localStorage.setItem(TOC_KEY_PREFIX + urlPathname, JSON.stringify([...next]));
|
|
303
|
+
return next;
|
|
304
|
+
});
|
|
305
|
+
setFoldVersion((v) => v + 1);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const body = bodyRef.current;
|
|
310
|
+
if (body) {
|
|
311
|
+
const prev = body.querySelector('a[aria-current="location"]');
|
|
312
|
+
if (prev) prev.removeAttribute("aria-current");
|
|
313
|
+
if (id) {
|
|
314
|
+
const next = body.querySelector(`a[href="#${CSS.escape(id)}"]`);
|
|
315
|
+
if (next) next.setAttribute("aria-current", "location");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (id !== activeIdRef.current) {
|
|
319
|
+
activeIdRef.current = id;
|
|
320
|
+
tweenToActiveId(id);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function onScroll() {
|
|
324
|
+
if (scheduled) return;
|
|
325
|
+
scheduled = true;
|
|
326
|
+
requestAnimationFrame(pick);
|
|
327
|
+
}
|
|
328
|
+
pick();
|
|
329
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
330
|
+
window.addEventListener("resize", onScroll);
|
|
331
|
+
return () => {
|
|
332
|
+
window.removeEventListener("scroll", onScroll);
|
|
333
|
+
window.removeEventListener("resize", onScroll);
|
|
334
|
+
};
|
|
335
|
+
}, [headings, collapsedH2s]);
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
if (!foldVersion || !activeIdRef.current || !bodyRef.current) return;
|
|
338
|
+
const link = bodyRef.current.querySelector(`a[href="#${CSS.escape(activeIdRef.current)}"]`);
|
|
339
|
+
if (link) link.scrollIntoView({ block: "nearest", behavior: "auto" });
|
|
340
|
+
}, [foldVersion]);
|
|
341
|
+
function applyRailDOM(start, len) {
|
|
342
|
+
const base = railBaseRef.current;
|
|
343
|
+
const stroke = activeStrokeRef.current;
|
|
344
|
+
const dot = dotRef.current;
|
|
345
|
+
const grad = gradientRef.current;
|
|
346
|
+
currentStartRef.current = start;
|
|
347
|
+
currentLenRef.current = len;
|
|
348
|
+
if (stroke) {
|
|
349
|
+
const dashLen = Math.max(0, len - start);
|
|
350
|
+
stroke.style.strokeDasharray = `${dashLen} 99999`;
|
|
351
|
+
stroke.style.strokeDashoffset = `${-start}`;
|
|
352
|
+
}
|
|
353
|
+
if (base && dot) {
|
|
354
|
+
if (len > 0) {
|
|
355
|
+
const p = base.getPointAtLength(Math.max(0, len));
|
|
356
|
+
dot.setAttribute("cx", String(p.x));
|
|
357
|
+
dot.setAttribute("cy", String(p.y));
|
|
358
|
+
dot.style.opacity = "1";
|
|
359
|
+
} else {
|
|
360
|
+
dot.style.opacity = "0";
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (base && grad && len > start) {
|
|
364
|
+
const startPt = base.getPointAtLength(Math.max(0, start));
|
|
365
|
+
const endPt = base.getPointAtLength(Math.max(0, len));
|
|
366
|
+
const ah = visibleHeadings.find((h) => h.id === activeIdRef.current);
|
|
367
|
+
const isH3 = ah && ah.level === 3;
|
|
368
|
+
const fadeLen = isH3 ? Math.min(8, (endPt.y - startPt.y) * 0.12) : Math.min(40, (endPt.y - startPt.y) * 0.5);
|
|
369
|
+
grad.setAttribute("y1", String(startPt.y));
|
|
370
|
+
grad.setAttribute("y2", String(startPt.y + fadeLen));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function tweenTick(now) {
|
|
374
|
+
const t = Math.min(1, (now - animStartRef.current) / TWEEN_MS);
|
|
375
|
+
const k = easeOut(t);
|
|
376
|
+
const s = startAnimFromRef.current + (startAnimToRef.current - startAnimFromRef.current) * k;
|
|
377
|
+
const v = animFromRef.current + (animToRef.current - animFromRef.current) * k;
|
|
378
|
+
applyRailDOM(s, v);
|
|
379
|
+
if (t < 1) {
|
|
380
|
+
animReqRef.current = requestAnimationFrame(tweenTick);
|
|
381
|
+
} else {
|
|
382
|
+
animReqRef.current = null;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
function tweenTo(targetStart, targetLen) {
|
|
386
|
+
animFromRef.current = currentLenRef.current;
|
|
387
|
+
animToRef.current = targetLen;
|
|
388
|
+
startAnimFromRef.current = currentStartRef.current;
|
|
389
|
+
startAnimToRef.current = targetStart;
|
|
390
|
+
animStartRef.current = performance.now();
|
|
391
|
+
if (animReqRef.current === null) {
|
|
392
|
+
animReqRef.current = requestAnimationFrame(tweenTick);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function tweenToActiveId(id) {
|
|
396
|
+
if (!id) {
|
|
397
|
+
tweenTo(0, 0);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const match = railPointsRef.current.find((p) => p.id === id);
|
|
401
|
+
if (!match) return;
|
|
402
|
+
const activeH = visibleHeadings.find((h) => h.id === id);
|
|
403
|
+
let anchorId = null;
|
|
404
|
+
if (activeH && activeH.level === 3) {
|
|
405
|
+
for (const h of visibleHeadings) {
|
|
406
|
+
if (h.level === 2) anchorId = h.id;
|
|
407
|
+
if (h.id === id) break;
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
let prev = null;
|
|
411
|
+
for (const h of visibleHeadings) {
|
|
412
|
+
if (h.id === id) break;
|
|
413
|
+
if (h.level === 2) prev = h.id;
|
|
414
|
+
}
|
|
415
|
+
anchorId = prev;
|
|
416
|
+
}
|
|
417
|
+
const anchorPt = anchorId ? railPointsRef.current.find((p) => p.id === anchorId) : null;
|
|
418
|
+
const startLen = anchorPt ? Math.max(0, anchorPt.len - 20) : 0;
|
|
419
|
+
tweenTo(startLen, match.len);
|
|
420
|
+
}
|
|
421
|
+
if (headings.length === 0) return null;
|
|
422
|
+
const tocAside = /* @__PURE__ */ jsxs(
|
|
423
|
+
"aside",
|
|
424
|
+
{
|
|
425
|
+
"aria-label": "On this page",
|
|
426
|
+
className: "hidden lg:block sticky overflow-y-auto",
|
|
427
|
+
style: { top: 40, height: "calc(100vh - 40px)", padding: "32px 22px 32px 18px" },
|
|
428
|
+
children: [
|
|
429
|
+
/* @__PURE__ */ jsx(
|
|
430
|
+
"div",
|
|
431
|
+
{
|
|
432
|
+
className: "uppercase border-b border-doc-template-faint text-doc-template-muted",
|
|
433
|
+
style: {
|
|
434
|
+
fontFamily: "var(--font-doc-template-mono)",
|
|
435
|
+
fontSize: 9,
|
|
436
|
+
fontWeight: 600,
|
|
437
|
+
opacity: 0.7,
|
|
438
|
+
letterSpacing: "0.14em",
|
|
439
|
+
padding: "0 0 10px",
|
|
440
|
+
marginBottom: 6
|
|
441
|
+
},
|
|
442
|
+
children: "On this page"
|
|
443
|
+
}
|
|
444
|
+
),
|
|
445
|
+
/* @__PURE__ */ jsxs("div", { ref: bodyRef, style: { position: "relative" }, children: [
|
|
446
|
+
/* @__PURE__ */ jsxs(
|
|
447
|
+
"svg",
|
|
448
|
+
{
|
|
449
|
+
"aria-hidden": true,
|
|
450
|
+
preserveAspectRatio: "none",
|
|
451
|
+
style: {
|
|
452
|
+
position: "absolute",
|
|
453
|
+
top: 0,
|
|
454
|
+
bottom: 0,
|
|
455
|
+
left: 0,
|
|
456
|
+
width: 28,
|
|
457
|
+
height: "100%",
|
|
458
|
+
pointerEvents: "none",
|
|
459
|
+
overflow: "visible"
|
|
460
|
+
},
|
|
461
|
+
children: [
|
|
462
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
463
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "toc-rail-fade", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
464
|
+
/* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
465
|
+
/* @__PURE__ */ jsx("stop", { offset: "0.08", stopColor: "white", stopOpacity: "1" }),
|
|
466
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "white", stopOpacity: "1" })
|
|
467
|
+
] }),
|
|
468
|
+
/* @__PURE__ */ jsx("mask", { id: "toc-rail-mask", maskUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx("rect", { x: "0", y: "0", width: "100%", height: "100%", fill: "url(#toc-rail-fade)" }) }),
|
|
469
|
+
/* @__PURE__ */ jsxs("linearGradient", { ref: gradientRef, id: "toc-accent-fade", gradientUnits: "userSpaceOnUse", x1: "0", y1: "0", x2: "0", y2: "0", children: [
|
|
470
|
+
/* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "var(--color-doc-template-accent)", stopOpacity: "0" }),
|
|
471
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "var(--color-doc-template-accent)", stopOpacity: "1" })
|
|
472
|
+
] })
|
|
473
|
+
] }),
|
|
474
|
+
/* @__PURE__ */ jsxs("g", { mask: "url(#toc-rail-mask)", children: [
|
|
475
|
+
/* @__PURE__ */ jsx(
|
|
476
|
+
"path",
|
|
477
|
+
{
|
|
478
|
+
ref: railBaseRef,
|
|
479
|
+
d: pathD,
|
|
480
|
+
style: {
|
|
481
|
+
stroke: "var(--color-doc-template-rail-stroke)",
|
|
482
|
+
strokeWidth: 1.5,
|
|
483
|
+
fill: "none",
|
|
484
|
+
strokeLinecap: "round",
|
|
485
|
+
strokeLinejoin: "round"
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
),
|
|
489
|
+
/* @__PURE__ */ jsx(
|
|
490
|
+
"path",
|
|
491
|
+
{
|
|
492
|
+
ref: activeStrokeRef,
|
|
493
|
+
d: pathD,
|
|
494
|
+
style: {
|
|
495
|
+
stroke: "url(#toc-accent-fade)",
|
|
496
|
+
strokeWidth: 2,
|
|
497
|
+
fill: "none",
|
|
498
|
+
strokeLinecap: "round",
|
|
499
|
+
strokeLinejoin: "round",
|
|
500
|
+
strokeDasharray: "0 99999",
|
|
501
|
+
strokeDashoffset: 0
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
),
|
|
505
|
+
endPos && /* @__PURE__ */ jsx(
|
|
506
|
+
"rect",
|
|
507
|
+
{
|
|
508
|
+
x: endPos.x - 2.5,
|
|
509
|
+
y: endPos.y - 2.5,
|
|
510
|
+
width: 5,
|
|
511
|
+
height: 5,
|
|
512
|
+
style: { fill: "var(--color-doc-template-rail-stroke)" }
|
|
513
|
+
}
|
|
514
|
+
)
|
|
515
|
+
] }),
|
|
516
|
+
/* @__PURE__ */ jsx(
|
|
517
|
+
"circle",
|
|
518
|
+
{
|
|
519
|
+
ref: dotRef,
|
|
520
|
+
cx: 0,
|
|
521
|
+
cy: 0,
|
|
522
|
+
r: 3.5,
|
|
523
|
+
style: {
|
|
524
|
+
fill: "var(--color-doc-template-accent)",
|
|
525
|
+
opacity: 0
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
)
|
|
529
|
+
]
|
|
530
|
+
}
|
|
531
|
+
),
|
|
532
|
+
/* @__PURE__ */ jsx(
|
|
533
|
+
"ul",
|
|
534
|
+
{
|
|
535
|
+
"data-toc-list": true,
|
|
536
|
+
className: "list-none m-0 p-0 flex flex-col",
|
|
537
|
+
style: { marginLeft: 14, gap: 1 },
|
|
538
|
+
children: visibleHeadings.map((h) => {
|
|
539
|
+
const hasFold = h.level === 2 && h2HasChildren.has(h.id);
|
|
540
|
+
const isFolded = hasFold && collapsedH2s.has(h.id);
|
|
541
|
+
return /* @__PURE__ */ jsx(
|
|
542
|
+
"li",
|
|
543
|
+
{
|
|
544
|
+
"data-level": h.level,
|
|
545
|
+
style: h.level === 3 ? { paddingLeft: 12 } : void 0,
|
|
546
|
+
children: /* @__PURE__ */ jsxs(
|
|
547
|
+
"a",
|
|
548
|
+
{
|
|
549
|
+
href: `#${h.id}`,
|
|
550
|
+
onClick: (e) => scrollToHeading(e, h.id),
|
|
551
|
+
"data-level": h.level,
|
|
552
|
+
className: "toc-link",
|
|
553
|
+
children: [
|
|
554
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1, minWidth: 0 }, children: h.text }),
|
|
555
|
+
hasFold && /* @__PURE__ */ jsx(
|
|
556
|
+
"span",
|
|
557
|
+
{
|
|
558
|
+
role: "button",
|
|
559
|
+
tabIndex: 0,
|
|
560
|
+
"aria-label": isFolded ? "Expand" : "Collapse",
|
|
561
|
+
className: "toc-fold-toggle",
|
|
562
|
+
onClick: (e) => {
|
|
563
|
+
e.preventDefault();
|
|
564
|
+
e.stopPropagation();
|
|
565
|
+
toggleH2(h.id);
|
|
566
|
+
},
|
|
567
|
+
onKeyDown: (e) => {
|
|
568
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
569
|
+
e.preventDefault();
|
|
570
|
+
e.stopPropagation();
|
|
571
|
+
toggleH2(h.id);
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
children: /* @__PURE__ */ jsx(
|
|
575
|
+
"svg",
|
|
576
|
+
{
|
|
577
|
+
width: "8",
|
|
578
|
+
height: "8",
|
|
579
|
+
viewBox: "0 0 24 24",
|
|
580
|
+
fill: "none",
|
|
581
|
+
stroke: "currentColor",
|
|
582
|
+
strokeWidth: "3",
|
|
583
|
+
strokeLinecap: "round",
|
|
584
|
+
strokeLinejoin: "round",
|
|
585
|
+
"aria-hidden": true,
|
|
586
|
+
style: { transform: isFolded ? "rotate(0deg)" : "rotate(90deg)", transition: "transform 0.15s ease" },
|
|
587
|
+
children: /* @__PURE__ */ jsx("path", { d: "M9 18l6-6-6-6" })
|
|
588
|
+
}
|
|
589
|
+
)
|
|
590
|
+
}
|
|
591
|
+
)
|
|
592
|
+
]
|
|
593
|
+
}
|
|
594
|
+
)
|
|
595
|
+
},
|
|
596
|
+
h.id
|
|
597
|
+
);
|
|
598
|
+
})
|
|
599
|
+
}
|
|
600
|
+
)
|
|
601
|
+
] }),
|
|
602
|
+
/* @__PURE__ */ jsxs(
|
|
603
|
+
"div",
|
|
604
|
+
{
|
|
605
|
+
className: "flex flex-col border-t border-doc-template-faint",
|
|
606
|
+
style: { marginTop: 18, paddingTop: 14, gap: 6 },
|
|
607
|
+
children: [
|
|
608
|
+
mdHref && /* @__PURE__ */ jsx(
|
|
609
|
+
"a",
|
|
610
|
+
{
|
|
611
|
+
href: mdHref,
|
|
612
|
+
rel: "external",
|
|
613
|
+
className: "no-underline text-doc-template-muted hover:text-doc-template-ink uppercase",
|
|
614
|
+
style: {
|
|
615
|
+
padding: "4px 10px 4px 12px",
|
|
616
|
+
fontFamily: "var(--font-doc-template-mono)",
|
|
617
|
+
fontSize: 10,
|
|
618
|
+
fontWeight: 500,
|
|
619
|
+
borderLeft: "2px solid transparent",
|
|
620
|
+
marginLeft: -2,
|
|
621
|
+
letterSpacing: "0.04em"
|
|
622
|
+
},
|
|
623
|
+
children: "View as Markdown"
|
|
624
|
+
}
|
|
625
|
+
),
|
|
626
|
+
editHref && /* @__PURE__ */ jsx(
|
|
627
|
+
"a",
|
|
628
|
+
{
|
|
629
|
+
href: editHref,
|
|
630
|
+
target: "_blank",
|
|
631
|
+
rel: "noreferrer",
|
|
632
|
+
className: "no-underline text-doc-template-muted hover:text-doc-template-ink uppercase",
|
|
633
|
+
style: {
|
|
634
|
+
padding: "4px 10px 4px 12px",
|
|
635
|
+
fontFamily: "var(--font-doc-template-mono)",
|
|
636
|
+
fontSize: 10,
|
|
637
|
+
fontWeight: 500,
|
|
638
|
+
borderLeft: "2px solid transparent",
|
|
639
|
+
marginLeft: -2,
|
|
640
|
+
letterSpacing: "0.04em"
|
|
641
|
+
},
|
|
642
|
+
children: "Edit this page"
|
|
643
|
+
}
|
|
644
|
+
),
|
|
645
|
+
/* @__PURE__ */ jsx(
|
|
646
|
+
"a",
|
|
647
|
+
{
|
|
648
|
+
href: issueHref,
|
|
649
|
+
target: "_blank",
|
|
650
|
+
rel: "noreferrer",
|
|
651
|
+
className: "no-underline text-doc-template-muted hover:text-doc-template-ink uppercase",
|
|
652
|
+
style: {
|
|
653
|
+
padding: "4px 10px 4px 12px",
|
|
654
|
+
fontFamily: "var(--font-doc-template-mono)",
|
|
655
|
+
fontSize: 10,
|
|
656
|
+
fontWeight: 500,
|
|
657
|
+
borderLeft: "2px solid transparent",
|
|
658
|
+
marginLeft: -2,
|
|
659
|
+
letterSpacing: "0.04em"
|
|
660
|
+
},
|
|
661
|
+
children: "Report an issue"
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
]
|
|
665
|
+
}
|
|
666
|
+
)
|
|
667
|
+
]
|
|
668
|
+
}
|
|
669
|
+
);
|
|
670
|
+
return tocAside;
|
|
671
|
+
}
|
|
672
|
+
export {
|
|
673
|
+
TOC
|
|
674
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact tab cluster for the topbar's right side. Six tracked-uppercase
|
|
3
|
+
* mono labels with a moving 7px ink-colored underbar that slides between
|
|
4
|
+
* the active (or hovered) tab. Renders inline within the topbar — does
|
|
5
|
+
* NOT carry its own sticky / blur / background; the topbar wrapper
|
|
6
|
+
* supplies all that.
|
|
7
|
+
*/
|
|
8
|
+
export declare function TabStrip(): import("react").JSX.Element | null;
|