@dreamlake/dockit 0.2.31 → 0.2.33
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/ContinuousReading.d.ts +8 -0
- package/dist/components/ContinuousReading.js +162 -0
- package/dist/components/DocFooter.js +2 -2
- package/dist/components/Preview.d.ts +6 -1
- package/dist/components/Preview.js +33 -5
- package/dist/components/Sidebar.js +2 -2
- package/dist/components/TOC.js +8 -7
- package/dist/components/Topbar.js +2 -2
- package/dist/components/mdx-components.d.ts +3 -0
- package/dist/components/mdx-components.js +168 -96
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/lib/reading.d.ts +21 -0
- package/dist/lib/reading.js +46 -0
- package/dist/renderer/Layout.js +11 -6
- package/dist/site-config.d.ts +2 -0
- package/dist/styles.css +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/** Only the entry page is rendered on the server and indexed by Pagefind.
|
|
3
|
+
* Appended MDX modules retain their React components and interactions. */
|
|
4
|
+
export declare function ContinuousReading({ children, path, onActive, }: {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
path: string;
|
|
7
|
+
onActive: (path: string) => void;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useRef, Component } from "react";
|
|
3
|
+
import { usePageContext, PageContextProvider } from "vike-react/usePageContext";
|
|
4
|
+
import { nextReadingPage, pageLoader, ReadingPageContext } from "../lib/reading.js";
|
|
5
|
+
class ArticleBoundary extends Component {
|
|
6
|
+
state = { failed: false };
|
|
7
|
+
static getDerivedStateFromError() {
|
|
8
|
+
return { failed: true };
|
|
9
|
+
}
|
|
10
|
+
render() {
|
|
11
|
+
return this.state.failed ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
|
|
12
|
+
"This page could not be displayed here. ",
|
|
13
|
+
/* @__PURE__ */ jsx("a", { href: this.props.path, children: "Open the page" }),
|
|
14
|
+
"."
|
|
15
|
+
] }) : this.props.children;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function ContinuousReading({
|
|
19
|
+
children,
|
|
20
|
+
path,
|
|
21
|
+
onActive
|
|
22
|
+
}) {
|
|
23
|
+
const context = usePageContext();
|
|
24
|
+
const [enabled, setEnabled] = useState(false);
|
|
25
|
+
const [ready, setReady] = useState(false);
|
|
26
|
+
useEffect(() => setReady(true), []);
|
|
27
|
+
const [articles, setArticles] = useState([]);
|
|
28
|
+
const [error, setError] = useState(false);
|
|
29
|
+
const [busy, setBusy] = useState(false);
|
|
30
|
+
const [attempt, setAttempt] = useState(0);
|
|
31
|
+
const sentinel = useRef(null);
|
|
32
|
+
const root = useRef(null);
|
|
33
|
+
const lastPath = articles.at(-1)?.path ?? path;
|
|
34
|
+
const next = nextReadingPage(lastPath);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!enabled || !next || error) return;
|
|
37
|
+
const target = sentinel.current;
|
|
38
|
+
if (!target || typeof IntersectionObserver === "undefined") return;
|
|
39
|
+
let cancelled = false;
|
|
40
|
+
let started = false;
|
|
41
|
+
const observer = new IntersectionObserver(
|
|
42
|
+
(entries) => {
|
|
43
|
+
if (started || !entries.some((e) => e.isIntersecting)) return;
|
|
44
|
+
started = true;
|
|
45
|
+
setBusy(true);
|
|
46
|
+
pageLoader(next.path)().then((module) => {
|
|
47
|
+
if (!cancelled)
|
|
48
|
+
setArticles((items) => [...items, { path: next.path, Page: module.default }]);
|
|
49
|
+
}).catch(() => {
|
|
50
|
+
if (!cancelled) setError(true);
|
|
51
|
+
}).finally(() => {
|
|
52
|
+
if (!cancelled) setBusy(false);
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
{ rootMargin: "0px 0px 240px 0px" }
|
|
56
|
+
);
|
|
57
|
+
observer.observe(target);
|
|
58
|
+
return () => {
|
|
59
|
+
cancelled = true;
|
|
60
|
+
observer.disconnect();
|
|
61
|
+
};
|
|
62
|
+
}, [enabled, next?.path, error, attempt]);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!enabled) {
|
|
65
|
+
onActive(path);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
let frame = 0;
|
|
69
|
+
const update = () => {
|
|
70
|
+
frame = 0;
|
|
71
|
+
const sections = Array.from(
|
|
72
|
+
root.current?.querySelectorAll("[data-doc-page]") ?? []
|
|
73
|
+
);
|
|
74
|
+
const active = sections.filter((s) => s.getBoundingClientRect().top <= 130).at(-1) ?? sections[0];
|
|
75
|
+
if (active?.dataset.docPage) onActive(active.dataset.docPage);
|
|
76
|
+
};
|
|
77
|
+
const schedule = () => {
|
|
78
|
+
if (!frame) frame = requestAnimationFrame(update);
|
|
79
|
+
};
|
|
80
|
+
update();
|
|
81
|
+
window.addEventListener("scroll", schedule, { passive: true });
|
|
82
|
+
window.addEventListener("resize", schedule);
|
|
83
|
+
return () => {
|
|
84
|
+
cancelAnimationFrame(frame);
|
|
85
|
+
window.removeEventListener("scroll", schedule);
|
|
86
|
+
window.removeEventListener("resize", schedule);
|
|
87
|
+
};
|
|
88
|
+
}, [enabled, articles, onActive, path]);
|
|
89
|
+
return /* @__PURE__ */ jsxs("div", { ref: root, children: [
|
|
90
|
+
/* @__PURE__ */ jsxs("label", { className: "doc-reading-toggle", "data-pagefind-ignore": true, children: [
|
|
91
|
+
/* @__PURE__ */ jsx(
|
|
92
|
+
"input",
|
|
93
|
+
{
|
|
94
|
+
type: "checkbox",
|
|
95
|
+
disabled: !ready,
|
|
96
|
+
checked: enabled,
|
|
97
|
+
onChange: (e) => {
|
|
98
|
+
setEnabled(e.target.checked);
|
|
99
|
+
if (!e.target.checked) {
|
|
100
|
+
setArticles([]);
|
|
101
|
+
setBusy(false);
|
|
102
|
+
setError(false);
|
|
103
|
+
onActive(path);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
" ",
|
|
109
|
+
"Keep scrolling"
|
|
110
|
+
] }),
|
|
111
|
+
/* @__PURE__ */ jsx("section", { "data-doc-page": path, children: /* @__PURE__ */ jsx(ReadingPageContext.Provider, { value: { path, prefix: "" }, children }) }),
|
|
112
|
+
articles.map(({ path: articlePath, Page }) => /* @__PURE__ */ jsxs(
|
|
113
|
+
"section",
|
|
114
|
+
{
|
|
115
|
+
"data-doc-page": articlePath,
|
|
116
|
+
className: "doc-reading-page",
|
|
117
|
+
"data-pagefind-ignore": true,
|
|
118
|
+
children: [
|
|
119
|
+
/* @__PURE__ */ jsx("a", { className: "doc-reading-permalink", href: articlePath, children: "Open this page ↗" }),
|
|
120
|
+
/* @__PURE__ */ jsx(ArticleBoundary, { path: articlePath, children: /* @__PURE__ */ jsx(PageContextProvider, { pageContext: { ...context, urlPathname: articlePath }, children: /* @__PURE__ */ jsx(
|
|
121
|
+
ReadingPageContext.Provider,
|
|
122
|
+
{
|
|
123
|
+
value: {
|
|
124
|
+
path: articlePath,
|
|
125
|
+
prefix: `doc-${encodeURIComponent(articlePath)}--`
|
|
126
|
+
},
|
|
127
|
+
children: /* @__PURE__ */ jsx(Page, {})
|
|
128
|
+
}
|
|
129
|
+
) }) })
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
articlePath
|
|
133
|
+
)),
|
|
134
|
+
enabled && next && /* @__PURE__ */ jsx("div", { ref: sentinel, className: "doc-reading-next", "data-pagefind-ignore": true, children: error ? /* @__PURE__ */ jsxs("p", { role: "status", children: [
|
|
135
|
+
"Could not load ",
|
|
136
|
+
next.title,
|
|
137
|
+
".",
|
|
138
|
+
" ",
|
|
139
|
+
/* @__PURE__ */ jsx(
|
|
140
|
+
"button",
|
|
141
|
+
{
|
|
142
|
+
type: "button",
|
|
143
|
+
onClick: () => {
|
|
144
|
+
setError(false);
|
|
145
|
+
setAttempt((n) => n + 1);
|
|
146
|
+
},
|
|
147
|
+
children: "Retry"
|
|
148
|
+
}
|
|
149
|
+
),
|
|
150
|
+
" ",
|
|
151
|
+
"or ",
|
|
152
|
+
/* @__PURE__ */ jsx("a", { href: next.path, children: "open the page" }),
|
|
153
|
+
"."
|
|
154
|
+
] }) : /* @__PURE__ */ jsxs("p", { role: busy ? "status" : void 0, children: [
|
|
155
|
+
busy ? "Loading " : "Up next: ",
|
|
156
|
+
/* @__PURE__ */ jsx("a", { href: next.path, children: next.title })
|
|
157
|
+
] }) })
|
|
158
|
+
] });
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
ContinuousReading
|
|
162
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useDocPath } from "../lib/reading.js";
|
|
3
3
|
import { getAdjacentPages } from "../lib/navigation.js";
|
|
4
4
|
import { useHiddenToggle } from "../lib/use-hidden-toggle.js";
|
|
5
5
|
const LINK = {
|
|
@@ -21,7 +21,7 @@ const LABEL = {
|
|
|
21
21
|
color: "var(--color-doc-template-muted)"
|
|
22
22
|
};
|
|
23
23
|
function DocFooter() {
|
|
24
|
-
const
|
|
24
|
+
const urlPathname = useDocPath();
|
|
25
25
|
const [showHidden] = useHiddenToggle();
|
|
26
26
|
const { prev, next } = getAdjacentPages(urlPathname, { includeHidden: showHidden });
|
|
27
27
|
if (!prev && !next) return null;
|
|
@@ -12,5 +12,10 @@ export interface PreviewProps {
|
|
|
12
12
|
defaultTab?: 'preview' | 'source' | 'data';
|
|
13
13
|
/** Force a height for the preview pane. */
|
|
14
14
|
height?: number | string;
|
|
15
|
+
/** `split` shows the source and the live render side by side (source on
|
|
16
|
+
* the left), stacking source above preview when the frame is narrower
|
|
17
|
+
* than 560px. The preview pane is then a size container, so a demo's
|
|
18
|
+
* container queries follow the pane's width. Default `tabs`. */
|
|
19
|
+
layout?: 'tabs' | 'split';
|
|
15
20
|
}
|
|
16
|
-
export declare function Preview({ children, source, dataSource, filename, defaultTab, height, }: PreviewProps): import("react").JSX.Element;
|
|
21
|
+
export declare function Preview({ children, source, dataSource, filename, defaultTab, height, layout, }: PreviewProps): import("react").JSX.Element;
|
|
@@ -161,9 +161,12 @@ function Preview({
|
|
|
161
161
|
dataSource,
|
|
162
162
|
filename,
|
|
163
163
|
defaultTab = "preview",
|
|
164
|
-
height
|
|
164
|
+
height,
|
|
165
|
+
layout = "tabs"
|
|
165
166
|
}) {
|
|
166
|
-
const
|
|
167
|
+
const split = layout === "split";
|
|
168
|
+
const [selectedTab, setTab] = useState(defaultTab);
|
|
169
|
+
const tab = split ? "source" : selectedTab;
|
|
167
170
|
const [copied, setCopied] = useState(false);
|
|
168
171
|
const [fullscreen, setFullscreen] = useState(false);
|
|
169
172
|
const [showLines, setShowLines] = useLineNumbers();
|
|
@@ -187,7 +190,8 @@ function Preview({
|
|
|
187
190
|
"div",
|
|
188
191
|
{
|
|
189
192
|
"data-line-numbers": showLines ? "on" : "off",
|
|
190
|
-
|
|
193
|
+
...split ? { "data-preview-layout": "split" } : null,
|
|
194
|
+
className: "dockit-preview border border-doc-template-faint bg-doc-template-panel",
|
|
191
195
|
style: fullscreen ? {
|
|
192
196
|
// Full-viewport overlay. `--color-doc-template-bg` is the page
|
|
193
197
|
// surface token so the backdrop matches the site in both light
|
|
@@ -213,7 +217,7 @@ function Preview({
|
|
|
213
217
|
background: "color-mix(in srgb, var(--color-doc-template-ink) 3%, transparent)"
|
|
214
218
|
},
|
|
215
219
|
children: [
|
|
216
|
-
/* @__PURE__ */ jsx("div", { style: { display: "inline-flex", gap: 2 }, role: "tablist", children: ["preview", "source", ...dataSource ? ["data"] : []].map((t) => {
|
|
220
|
+
split ? /* @__PURE__ */ jsx("span", { style: { ...TAB, color: "var(--color-doc-template-muted)", cursor: "default", display: "inline-flex", alignItems: "center" }, children: "Source · Preview" }) : /* @__PURE__ */ jsx("div", { style: { display: "inline-flex", gap: 2 }, role: "tablist", children: ["preview", "source", ...dataSource ? ["data"] : []].map((t) => {
|
|
217
221
|
const active = t === tab;
|
|
218
222
|
return /* @__PURE__ */ jsx(
|
|
219
223
|
"button",
|
|
@@ -285,7 +289,31 @@ function Preview({
|
|
|
285
289
|
]
|
|
286
290
|
}
|
|
287
291
|
),
|
|
288
|
-
|
|
292
|
+
split ? /* @__PURE__ */ jsxs(
|
|
293
|
+
"div",
|
|
294
|
+
{
|
|
295
|
+
className: "dockit-preview-split",
|
|
296
|
+
style: fullscreen ? { flex: 1, minHeight: 0, overflow: "auto" } : void 0,
|
|
297
|
+
children: [
|
|
298
|
+
/* @__PURE__ */ jsx(
|
|
299
|
+
"div",
|
|
300
|
+
{
|
|
301
|
+
className: "dockit-preview-split-source",
|
|
302
|
+
style: { background: "var(--color-doc-template-code)", minWidth: 0 },
|
|
303
|
+
children: /* @__PURE__ */ jsx(HighlightedSource, { code: source, filename })
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
/* @__PURE__ */ jsx(
|
|
307
|
+
"div",
|
|
308
|
+
{
|
|
309
|
+
className: "dockit-preview-split-render",
|
|
310
|
+
style: { padding: 24, minHeight: 80, minWidth: 0, ...height ? { height } : null },
|
|
311
|
+
children
|
|
312
|
+
}
|
|
313
|
+
)
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
) : tab === "preview" ? /* @__PURE__ */ jsxs(
|
|
289
317
|
"div",
|
|
290
318
|
{
|
|
291
319
|
...fullscreen ? { "data-preview-fill": "" } : null,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useState, useEffect } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { useDocPath } from "../lib/reading.js";
|
|
4
4
|
import { normalizePath, groupedPages, groupedVisiblePages } from "../lib/navigation.js";
|
|
5
5
|
import { useHiddenToggle } from "../lib/use-hidden-toggle.js";
|
|
6
6
|
import { tabForUrl, urlInTab } from "../lib/tabs.js";
|
|
@@ -14,7 +14,7 @@ function loadCollapsed() {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
function Sidebar() {
|
|
17
|
-
const
|
|
17
|
+
const urlPathname = useDocPath();
|
|
18
18
|
const currentPath = normalizePath(urlPathname);
|
|
19
19
|
const [showHidden] = useHiddenToggle();
|
|
20
20
|
const allGroups = showHidden ? groupedPages : groupedVisiblePages;
|
package/dist/components/TOC.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef, useEffect, useMemo } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { useDocPath } from "../lib/reading.js";
|
|
4
4
|
import { normalizePath, findPage } from "../lib/navigation.js";
|
|
5
5
|
import { siteConfig } from "../site-config.js";
|
|
6
6
|
import { useHiddenToggle } from "../lib/use-hidden-toggle.js";
|
|
@@ -48,10 +48,10 @@ function scrollToHeading(e, id) {
|
|
|
48
48
|
const marginTop = parseFloat(cs.scrollMarginTop) || 0;
|
|
49
49
|
const targetY = target.getBoundingClientRect().top + window.scrollY - marginTop;
|
|
50
50
|
animateScrollTo(targetY);
|
|
51
|
-
history.replaceState(
|
|
51
|
+
if (!target.closest("[data-doc-page]")) history.replaceState(history.state, "", `#${id}`);
|
|
52
52
|
}
|
|
53
53
|
function TOC() {
|
|
54
|
-
const
|
|
54
|
+
const urlPathname = useDocPath();
|
|
55
55
|
const currentPath = normalizePath(urlPathname);
|
|
56
56
|
const [showDeveloperLinks] = useHiddenToggle();
|
|
57
57
|
const mdHref = (() => {
|
|
@@ -137,7 +137,7 @@ function TOC() {
|
|
|
137
137
|
return result;
|
|
138
138
|
}, [headings, collapsedH2s]);
|
|
139
139
|
useEffect(() => {
|
|
140
|
-
const main = document.querySelector("main.doc-content");
|
|
140
|
+
const main = document.querySelector(`[data-doc-page="${CSS.escape(urlPathname)}"]`) ?? document.querySelector("main.doc-content");
|
|
141
141
|
if (!main) {
|
|
142
142
|
setHeadings([]);
|
|
143
143
|
return;
|
|
@@ -315,7 +315,7 @@ function TOC() {
|
|
|
315
315
|
const prev = body.querySelector('a[aria-current="location"]');
|
|
316
316
|
if (prev) prev.removeAttribute("aria-current");
|
|
317
317
|
if (id) {
|
|
318
|
-
const next = body.querySelector(`a[
|
|
318
|
+
const next = body.querySelector(`a[data-toc-target="${CSS.escape(id)}"]`);
|
|
319
319
|
if (next) next.setAttribute("aria-current", "location");
|
|
320
320
|
}
|
|
321
321
|
}
|
|
@@ -339,7 +339,7 @@ function TOC() {
|
|
|
339
339
|
}, [headings, collapsedH2s]);
|
|
340
340
|
useEffect(() => {
|
|
341
341
|
if (!foldVersion || !activeIdRef.current || !bodyRef.current) return;
|
|
342
|
-
const link = bodyRef.current.querySelector(`a[
|
|
342
|
+
const link = bodyRef.current.querySelector(`a[data-toc-target="${CSS.escape(activeIdRef.current)}"]`);
|
|
343
343
|
if (link) link.scrollIntoView({ block: "nearest", behavior: "auto" });
|
|
344
344
|
}, [foldVersion]);
|
|
345
345
|
function applyRailDOM(start, len) {
|
|
@@ -550,7 +550,8 @@ function TOC() {
|
|
|
550
550
|
children: /* @__PURE__ */ jsxs(
|
|
551
551
|
"a",
|
|
552
552
|
{
|
|
553
|
-
href: `#${h.id}`,
|
|
553
|
+
href: h.el.closest("[data-doc-page]") ? `${urlPathname}#${h.el.dataset.docAnchor ?? h.id}` : `#${h.id}`,
|
|
554
|
+
"data-toc-target": h.id,
|
|
554
555
|
onClick: (e) => scrollToHeading(e, h.id),
|
|
555
556
|
"data-level": h.level,
|
|
556
557
|
className: "toc-link",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useRef, useState, useEffect, useLayoutEffect } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { useDocPath } from "../lib/reading.js";
|
|
4
4
|
import { findPage } from "../lib/navigation.js";
|
|
5
5
|
import { siteConfig } from "../site-config.js";
|
|
6
6
|
import { useMediaQuery } from "../lib/use-media-query.js";
|
|
@@ -36,7 +36,7 @@ const SEARCH_MAX_W = 860;
|
|
|
36
36
|
const SEARCH_GUTTER = 24;
|
|
37
37
|
const SEARCH_INSET = `max(${SEARCH_GUTTER}px, calc((100vw - ${SEARCH_MAX_W}px) / 2))`;
|
|
38
38
|
function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
|
|
39
|
-
const
|
|
39
|
+
const urlPathname = useDocPath();
|
|
40
40
|
const current = findPage(urlPathname);
|
|
41
41
|
const [showDeveloperLinks] = useHiddenToggle();
|
|
42
42
|
const hasTabs = TABS.length > 0;
|
|
@@ -14,6 +14,9 @@ export declare const mdxComponents: {
|
|
|
14
14
|
h1: import('react').FC<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "ref">>;
|
|
15
15
|
h2: import('react').FC<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "ref">>;
|
|
16
16
|
h3: import('react').FC<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "ref">>;
|
|
17
|
+
h4: ({ id, ...props }: ComponentPropsWithoutRef<"h4">) => import("react").JSX.Element;
|
|
18
|
+
h5: ({ id, ...props }: ComponentPropsWithoutRef<"h4">) => import("react").JSX.Element;
|
|
19
|
+
h6: ({ id, ...props }: ComponentPropsWithoutRef<"h4">) => import("react").JSX.Element;
|
|
17
20
|
p: import('react').FC<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "ref">>;
|
|
18
21
|
ul: import('react').FC<Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "ref">>;
|
|
19
22
|
ol: import('react').FC<Omit<import('react').DetailedHTMLProps<import('react').OlHTMLAttributes<HTMLOListElement>, HTMLOListElement>, "ref">>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useReadingPage, readingHref } from "../lib/reading.js";
|
|
2
3
|
import { useContext, createContext, useState } from "react";
|
|
3
4
|
import { CodeBlock } from "./CodeBlock.js";
|
|
4
5
|
import { Table } from "./Table.js";
|
|
@@ -39,12 +40,23 @@ const CheckIcon = () => /* @__PURE__ */ jsx(
|
|
|
39
40
|
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
40
41
|
}
|
|
41
42
|
);
|
|
42
|
-
function HeadingAnchor({
|
|
43
|
+
function HeadingAnchor({
|
|
44
|
+
id,
|
|
45
|
+
label,
|
|
46
|
+
originalId
|
|
47
|
+
}) {
|
|
48
|
+
const page = useReadingPage();
|
|
43
49
|
const [copied, setCopied] = useState(false);
|
|
44
50
|
if (!id) return null;
|
|
45
|
-
const onClick = () => {
|
|
51
|
+
const onClick = (event) => {
|
|
52
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0)
|
|
53
|
+
return;
|
|
54
|
+
if (page) {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
document.getElementById(id)?.scrollIntoView();
|
|
57
|
+
}
|
|
46
58
|
if (typeof window === "undefined") return;
|
|
47
|
-
const url = `${window.location.origin}${window.location.pathname}#${id}`;
|
|
59
|
+
const url = `${window.location.origin}${page?.path ?? window.location.pathname}#${originalId ?? id}`;
|
|
48
60
|
navigator.clipboard?.writeText(url).catch(() => {
|
|
49
61
|
});
|
|
50
62
|
setCopied(true);
|
|
@@ -56,7 +68,7 @@ function HeadingAnchor({ id, label }) {
|
|
|
56
68
|
return /* @__PURE__ */ jsx(
|
|
57
69
|
"a",
|
|
58
70
|
{
|
|
59
|
-
href: `#${id}`,
|
|
71
|
+
href: page ? `${page.path}#${originalId ?? id}` : `#${id}`,
|
|
60
72
|
onClick,
|
|
61
73
|
"aria-label": copied ? "Link copied to clipboard" : label ? `Copy link to ${label}` : "Copy link to this section",
|
|
62
74
|
title: copied ? "Copied!" : "Copy link to this section",
|
|
@@ -102,98 +114,125 @@ function PreWrapper(props) {
|
|
|
102
114
|
}
|
|
103
115
|
);
|
|
104
116
|
}
|
|
105
|
-
const H2 = ({ id, children, style, ...rest }) =>
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
const H2 = ({ id, children, style, ...rest }) => {
|
|
118
|
+
const page = useReadingPage();
|
|
119
|
+
const originalId = id;
|
|
120
|
+
if (id && page?.prefix) id = page.prefix + id;
|
|
121
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
122
|
+
id && /* @__PURE__ */ jsx(
|
|
123
|
+
"span",
|
|
124
|
+
{
|
|
125
|
+
id,
|
|
126
|
+
"data-doc-anchor": originalId,
|
|
127
|
+
"aria-hidden": true,
|
|
128
|
+
"data-toc-anchor": true,
|
|
129
|
+
"data-toc-level": "2",
|
|
130
|
+
style: {
|
|
131
|
+
display: "block",
|
|
132
|
+
height: 0,
|
|
133
|
+
marginTop: 16,
|
|
134
|
+
scrollMarginTop: 56
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
/* @__PURE__ */ jsxs(
|
|
139
|
+
"h2",
|
|
140
|
+
{
|
|
141
|
+
...rest,
|
|
142
|
+
className: "flex items-center text-doc-template-ink group -mx-[18px] px-[18px] lg:-mx-[56px] lg:px-[56px]",
|
|
143
|
+
style: {
|
|
144
|
+
position: "sticky",
|
|
145
|
+
top: 40,
|
|
146
|
+
zIndex: 3,
|
|
147
|
+
fontFamily: "var(--font-doc-template-ui)",
|
|
148
|
+
fontSize: 22,
|
|
149
|
+
fontWeight: 600,
|
|
150
|
+
letterSpacing: "-0.018em",
|
|
151
|
+
marginBottom: 12,
|
|
152
|
+
paddingTop: 12,
|
|
153
|
+
paddingBottom: 8,
|
|
154
|
+
gap: 8,
|
|
155
|
+
lineHeight: 1.2,
|
|
156
|
+
// Let the actual page surface show through, including custom themes.
|
|
157
|
+
backgroundColor: "transparent",
|
|
158
|
+
backdropFilter: "saturate(140%) blur(8px)",
|
|
159
|
+
WebkitBackdropFilter: "saturate(140%) blur(8px)",
|
|
160
|
+
...style
|
|
161
|
+
},
|
|
162
|
+
children: [
|
|
163
|
+
children,
|
|
164
|
+
/* @__PURE__ */ jsx(HeadingAnchor, { originalId, id, label: flatten(children) })
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
] });
|
|
169
|
+
};
|
|
170
|
+
const H3 = ({ id, children, style, ...rest }) => {
|
|
171
|
+
const page = useReadingPage();
|
|
172
|
+
const originalId = id;
|
|
173
|
+
if (id && page?.prefix) id = page.prefix + id;
|
|
174
|
+
return /* @__PURE__ */ jsxs(
|
|
175
|
+
"h3",
|
|
108
176
|
{
|
|
109
177
|
id,
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
"
|
|
178
|
+
"data-doc-anchor": originalId,
|
|
179
|
+
...rest,
|
|
180
|
+
className: "flex items-center text-doc-template-ink group",
|
|
113
181
|
style: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
182
|
+
fontFamily: "var(--font-doc-template-ui)",
|
|
183
|
+
fontSize: 15,
|
|
184
|
+
fontWeight: 600,
|
|
185
|
+
letterSpacing: "-0.005em",
|
|
186
|
+
margin: "18px 0 6px",
|
|
187
|
+
gap: 8,
|
|
188
|
+
scrollMarginTop: 96,
|
|
189
|
+
...style
|
|
190
|
+
},
|
|
191
|
+
children: [
|
|
192
|
+
children,
|
|
193
|
+
/* @__PURE__ */ jsx(HeadingAnchor, { originalId, id, label: flatten(children) })
|
|
194
|
+
]
|
|
119
195
|
}
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
const H1 = ({ id, children, style, ...rest }) => {
|
|
199
|
+
const page = useReadingPage();
|
|
200
|
+
const originalId = id;
|
|
201
|
+
if (id && page?.prefix) id = page.prefix + id;
|
|
202
|
+
return /* @__PURE__ */ jsxs(
|
|
203
|
+
"h1",
|
|
123
204
|
{
|
|
205
|
+
id,
|
|
206
|
+
"data-doc-anchor": originalId,
|
|
124
207
|
...rest,
|
|
125
|
-
className: "flex items-center text-doc-template-ink group
|
|
208
|
+
className: "flex items-center text-doc-template-ink group",
|
|
126
209
|
style: {
|
|
127
|
-
position: "sticky",
|
|
128
|
-
top: 40,
|
|
129
|
-
zIndex: 3,
|
|
130
210
|
fontFamily: "var(--font-doc-template-ui)",
|
|
131
|
-
fontSize:
|
|
132
|
-
fontWeight:
|
|
133
|
-
letterSpacing: "-0.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
211
|
+
fontSize: 32,
|
|
212
|
+
fontWeight: 700,
|
|
213
|
+
letterSpacing: "-0.025em",
|
|
214
|
+
margin: "18px 0 10px",
|
|
215
|
+
paddingBottom: 24,
|
|
216
|
+
lineHeight: 1.1,
|
|
137
217
|
gap: 8,
|
|
138
|
-
lineHeight: 1.2,
|
|
139
|
-
// Let the actual page surface show through, including custom themes.
|
|
140
|
-
backgroundColor: "transparent",
|
|
141
|
-
backdropFilter: "saturate(140%) blur(8px)",
|
|
142
|
-
WebkitBackdropFilter: "saturate(140%) blur(8px)",
|
|
143
218
|
...style
|
|
144
219
|
},
|
|
145
220
|
children: [
|
|
146
221
|
children,
|
|
147
|
-
/* @__PURE__ */ jsx(HeadingAnchor, { id, label: flatten(children) })
|
|
222
|
+
/* @__PURE__ */ jsx(HeadingAnchor, { originalId, id, label: flatten(children) })
|
|
148
223
|
]
|
|
149
224
|
}
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
id,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
fontWeight: 600,
|
|
162
|
-
letterSpacing: "-0.005em",
|
|
163
|
-
margin: "18px 0 6px",
|
|
164
|
-
gap: 8,
|
|
165
|
-
scrollMarginTop: 96,
|
|
166
|
-
...style
|
|
167
|
-
},
|
|
168
|
-
children: [
|
|
169
|
-
children,
|
|
170
|
-
/* @__PURE__ */ jsx(HeadingAnchor, { id, label: flatten(children) })
|
|
171
|
-
]
|
|
172
|
-
}
|
|
173
|
-
);
|
|
174
|
-
const H1 = ({ id, children, style, ...rest }) => /* @__PURE__ */ jsxs(
|
|
175
|
-
"h1",
|
|
176
|
-
{
|
|
177
|
-
id,
|
|
178
|
-
...rest,
|
|
179
|
-
className: "flex items-center text-doc-template-ink group",
|
|
180
|
-
style: {
|
|
181
|
-
fontFamily: "var(--font-doc-template-ui)",
|
|
182
|
-
fontSize: 32,
|
|
183
|
-
fontWeight: 700,
|
|
184
|
-
letterSpacing: "-0.025em",
|
|
185
|
-
margin: "18px 0 10px",
|
|
186
|
-
paddingBottom: 24,
|
|
187
|
-
lineHeight: 1.1,
|
|
188
|
-
gap: 8,
|
|
189
|
-
...style
|
|
190
|
-
},
|
|
191
|
-
children: [
|
|
192
|
-
children,
|
|
193
|
-
/* @__PURE__ */ jsx(HeadingAnchor, { id, label: flatten(children) })
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
);
|
|
225
|
+
);
|
|
226
|
+
};
|
|
227
|
+
function scopedHeading(Tag) {
|
|
228
|
+
return function Heading({ id, ...props }) {
|
|
229
|
+
const page = useReadingPage();
|
|
230
|
+
return /* @__PURE__ */ jsx(Tag, { ...props, id: id && page?.prefix ? page.prefix + id : id, "data-doc-anchor": id });
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const H4 = scopedHeading("h4");
|
|
234
|
+
const H5 = scopedHeading("h5");
|
|
235
|
+
const H6 = scopedHeading("h6");
|
|
197
236
|
const BODY_FONT_SIZE = 14.5;
|
|
198
237
|
const BODY_LINE_HEIGHT = 1.65;
|
|
199
238
|
const P = ({ children, style, ...rest }) => /* @__PURE__ */ jsx(
|
|
@@ -246,7 +285,11 @@ const OL = ({ children, style, ...rest }) => /* @__PURE__ */ jsx(
|
|
|
246
285
|
}
|
|
247
286
|
);
|
|
248
287
|
const LI = ({ children, style, ...rest }) => /* @__PURE__ */ jsx("li", { ...rest, style: { marginBottom: 4, ...style }, children });
|
|
249
|
-
const Blockquote = ({
|
|
288
|
+
const Blockquote = ({
|
|
289
|
+
children,
|
|
290
|
+
style,
|
|
291
|
+
...rest
|
|
292
|
+
}) => /* @__PURE__ */ jsx(
|
|
250
293
|
"blockquote",
|
|
251
294
|
{
|
|
252
295
|
...rest,
|
|
@@ -260,19 +303,40 @@ const Blockquote = ({ children, style, ...rest }) => /* @__PURE__ */ jsx(
|
|
|
260
303
|
children
|
|
261
304
|
}
|
|
262
305
|
);
|
|
263
|
-
const A = ({
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
306
|
+
const A = ({
|
|
307
|
+
children,
|
|
308
|
+
style,
|
|
309
|
+
href,
|
|
310
|
+
onClick,
|
|
311
|
+
...rest
|
|
312
|
+
}) => {
|
|
313
|
+
const page = useReadingPage();
|
|
314
|
+
const local = page && href?.startsWith("#");
|
|
315
|
+
return /* @__PURE__ */ jsx(
|
|
316
|
+
"a",
|
|
317
|
+
{
|
|
318
|
+
...rest,
|
|
319
|
+
href: page ? readingHref(href, page.path) : href,
|
|
320
|
+
onClick: (event) => {
|
|
321
|
+
onClick?.(event);
|
|
322
|
+
if (!local || event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0)
|
|
323
|
+
return;
|
|
324
|
+
const target = document.getElementById(page.prefix + decodeURIComponent(href.slice(1)));
|
|
325
|
+
if (target) {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
target.scrollIntoView();
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
className: "text-doc-template-accent hover:[border-bottom-color:var(--color-doc-template-accent)]",
|
|
331
|
+
style: {
|
|
332
|
+
borderBottom: "1px solid color-mix(in srgb, var(--color-doc-template-accent) 35%, transparent)",
|
|
333
|
+
textDecoration: "none",
|
|
334
|
+
...style
|
|
335
|
+
},
|
|
336
|
+
children
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
};
|
|
276
340
|
const Th = ({ children, style, ...rest }) => /* @__PURE__ */ jsx(
|
|
277
341
|
"th",
|
|
278
342
|
{
|
|
@@ -299,7 +363,12 @@ const Td = ({ children, style, ...rest }) => /* @__PURE__ */ jsx(
|
|
|
299
363
|
children
|
|
300
364
|
}
|
|
301
365
|
);
|
|
302
|
-
const Code = ({
|
|
366
|
+
const Code = ({
|
|
367
|
+
className,
|
|
368
|
+
children,
|
|
369
|
+
style,
|
|
370
|
+
...rest
|
|
371
|
+
}) => {
|
|
303
372
|
const insidePre = useContext(InsidePreContext);
|
|
304
373
|
const isBlock = insidePre || !!className && /(?:shiki|language-|hljs)/.test(className);
|
|
305
374
|
if (isBlock) {
|
|
@@ -328,6 +397,9 @@ const mdxComponents = {
|
|
|
328
397
|
h1: H1,
|
|
329
398
|
h2: H2,
|
|
330
399
|
h3: H3,
|
|
400
|
+
h4: H4,
|
|
401
|
+
h5: H5,
|
|
402
|
+
h6: H6,
|
|
331
403
|
p: P,
|
|
332
404
|
ul: UL,
|
|
333
405
|
ol: OL,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DocPageLoader } from './lib/reading';
|
|
1
2
|
import { SiteConfig as _SiteConfig, SearchConfig as _SearchConfig } from './site-config';
|
|
2
3
|
import { PageFrontmatter as _PageFrontmatter } from './lib/navigation';
|
|
3
4
|
import { TabEntry as _TabEntry } from './lib/tabs';
|
|
@@ -47,6 +48,8 @@ export { Topbar } from './components/Topbar';
|
|
|
47
48
|
export { VersionBadge, type VersionBadgeProps } from './components/VersionBadge';
|
|
48
49
|
export { Layout, useMerge } from './renderer/Layout';
|
|
49
50
|
export interface InitDocsOptions {
|
|
51
|
+
/** Lazy MDX bodies for opt-in continuous reading. */
|
|
52
|
+
pageLoaders?: Record<string, DocPageLoader>;
|
|
50
53
|
/** Site branding, URLs, version chips, git hash. */
|
|
51
54
|
site: Partial<_SiteConfig>;
|
|
52
55
|
/** Metadata-only glob: `{ eager: true, query: '?frontmatter', import: 'default' }`.
|
|
@@ -75,3 +78,4 @@ export interface InitDocsOptions {
|
|
|
75
78
|
/** One call wires the whole shell: site config, navigation, search, tabs. */
|
|
76
79
|
export declare function initDocs(opts: InitDocsOptions): void;
|
|
77
80
|
export { ContentRow, type ContentRowProps } from './components/ContentRow';
|
|
81
|
+
export { nextReadingPage, pageLoader, type DocPageLoader } from './lib/reading';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { initPageLoaders } from "./lib/reading.js";
|
|
2
|
+
import { nextReadingPage, pageLoader } from "./lib/reading.js";
|
|
1
3
|
import { defineSiteConfig } from "./site-config.js";
|
|
2
4
|
import { siteConfig } from "./site-config.js";
|
|
3
5
|
import { initNavigation } from "./lib/navigation.js";
|
|
@@ -42,6 +44,7 @@ function initDocs(opts) {
|
|
|
42
44
|
initNavigation(modules, opts.sectionOrder ?? []);
|
|
43
45
|
initSearchIndex(opts.rawPages ?? {});
|
|
44
46
|
initTabs(opts.tabs ?? []);
|
|
47
|
+
initPageLoaders(opts.pageLoaders);
|
|
45
48
|
}
|
|
46
49
|
export {
|
|
47
50
|
Callout,
|
|
@@ -84,7 +87,9 @@ export {
|
|
|
84
87
|
internalTabs,
|
|
85
88
|
isExternalTab,
|
|
86
89
|
mdxComponents,
|
|
90
|
+
nextReadingPage,
|
|
87
91
|
normalizePath,
|
|
92
|
+
pageLoader,
|
|
88
93
|
pages,
|
|
89
94
|
rawMarkdown,
|
|
90
95
|
search,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
export type DocPageLoader = () => Promise<{
|
|
3
|
+
default: ComponentType;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function initPageLoaders(modules?: Record<string, DocPageLoader>): void;
|
|
6
|
+
export declare function pageLoader(path: string): DocPageLoader | undefined;
|
|
7
|
+
/** Reading follows visible sidebar order, stays in the current tab, and never
|
|
8
|
+
* enters hidden, noindex, fullscreen, or non-MDX/server-data pages. */
|
|
9
|
+
export declare function nextReadingPage(path: string): import('./navigation').PageMeta | undefined;
|
|
10
|
+
export declare const ReadingPathContext: import('react').Context<string | null>;
|
|
11
|
+
export declare function useDocPath(): string;
|
|
12
|
+
export declare const ReadingPageContext: import('react').Context<{
|
|
13
|
+
path: string;
|
|
14
|
+
prefix: string;
|
|
15
|
+
} | null>;
|
|
16
|
+
export declare function useReadingPage(): {
|
|
17
|
+
path: string;
|
|
18
|
+
prefix: string;
|
|
19
|
+
} | null;
|
|
20
|
+
/** Resolve authored relative links as if this article were opened on its own. */
|
|
21
|
+
export declare function readingHref(href: string | undefined, path: string): string | undefined;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useContext, createContext } from "react";
|
|
2
|
+
import { usePageContext } from "vike-react/usePageContext";
|
|
3
|
+
import { groupedVisiblePages, normalizePath } from "./navigation.js";
|
|
4
|
+
import { tabForUrl } from "./tabs.js";
|
|
5
|
+
const loaders = /* @__PURE__ */ new Map();
|
|
6
|
+
function initPageLoaders(modules = {}) {
|
|
7
|
+
loaders.clear();
|
|
8
|
+
for (const [file, load] of Object.entries(modules)) {
|
|
9
|
+
const slug = file.replace(/^.*?\bpages\//, "").replace(/\/\+Page\.mdx$/, "");
|
|
10
|
+
loaders.set(slug === "index" ? "/" : `/${slug}`, load);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function pageLoader(path) {
|
|
14
|
+
return loaders.get(normalizePath(path));
|
|
15
|
+
}
|
|
16
|
+
function nextReadingPage(path) {
|
|
17
|
+
const list = groupedVisiblePages.flatMap((g) => g.items).filter((p) => !p.noindex && !p.fullscreen && tabForUrl(p.path) === tabForUrl(path));
|
|
18
|
+
const index = list.findIndex((p) => p.path === normalizePath(path));
|
|
19
|
+
const next = index >= 0 ? list[index + 1] : void 0;
|
|
20
|
+
return next && pageLoader(next.path) ? next : void 0;
|
|
21
|
+
}
|
|
22
|
+
const ReadingPathContext = createContext(null);
|
|
23
|
+
function useDocPath() {
|
|
24
|
+
const active = useContext(ReadingPathContext);
|
|
25
|
+
const page = usePageContext();
|
|
26
|
+
return active ?? page.urlPathname;
|
|
27
|
+
}
|
|
28
|
+
const ReadingPageContext = createContext(null);
|
|
29
|
+
function useReadingPage() {
|
|
30
|
+
return useContext(ReadingPageContext);
|
|
31
|
+
}
|
|
32
|
+
function readingHref(href, path) {
|
|
33
|
+
if (!href || /^(?:[a-z][a-z\d+.-]*:|\/)/i.test(href)) return href;
|
|
34
|
+
const url = new URL(href, `https://docs.invalid${path}`);
|
|
35
|
+
return url.pathname + url.search + url.hash;
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
ReadingPageContext,
|
|
39
|
+
ReadingPathContext,
|
|
40
|
+
initPageLoaders,
|
|
41
|
+
nextReadingPage,
|
|
42
|
+
pageLoader,
|
|
43
|
+
readingHref,
|
|
44
|
+
useDocPath,
|
|
45
|
+
useReadingPage
|
|
46
|
+
};
|
package/dist/renderer/Layout.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { ContinuousReading } from "../components/ContinuousReading.js";
|
|
3
|
+
import { pageLoader, ReadingPathContext, useDocPath } from "../lib/reading.js";
|
|
4
|
+
import { useState, useEffect, useMemo, useContext, createContext } from "react";
|
|
3
5
|
import { MDXProvider } from "@mdx-js/react";
|
|
4
6
|
import { usePageContext } from "vike-react/usePageContext";
|
|
5
7
|
import { ThemeProvider } from "../components/ThemeProvider.js";
|
|
@@ -15,7 +17,7 @@ const SPRING = "cubic-bezier(0.4, 0.7, 0.3, 1)";
|
|
|
15
17
|
const MergeContext = createContext(false);
|
|
16
18
|
const useMerge = () => useContext(MergeContext);
|
|
17
19
|
function PageBreadcrumb() {
|
|
18
|
-
const
|
|
20
|
+
const urlPathname = useDocPath();
|
|
19
21
|
const current = findPage(urlPathname);
|
|
20
22
|
const merged = useMerge();
|
|
21
23
|
if (!current) return null;
|
|
@@ -78,7 +80,7 @@ function H1MergeWatcher({ onChange }) {
|
|
|
78
80
|
return null;
|
|
79
81
|
}
|
|
80
82
|
function HeadSync() {
|
|
81
|
-
const
|
|
83
|
+
const urlPathname = useDocPath();
|
|
82
84
|
useEffect(() => {
|
|
83
85
|
if (typeof document === "undefined") return;
|
|
84
86
|
const current = findPage(urlPathname);
|
|
@@ -111,7 +113,10 @@ function HeadSync() {
|
|
|
111
113
|
}
|
|
112
114
|
function Layout({ children }) {
|
|
113
115
|
const { urlPathname } = usePageContext();
|
|
116
|
+
const [activePath, setActivePath] = useState(urlPathname);
|
|
117
|
+
useEffect(() => setActivePath(urlPathname), [urlPathname]);
|
|
114
118
|
const current = findPage(urlPathname);
|
|
119
|
+
const continuous = siteConfig.continuousReading && !!pageLoader(urlPathname) && !current?.noindex && !current?.hidden;
|
|
115
120
|
const isFullscreen = current?.fullscreen === true;
|
|
116
121
|
const [searchOpen, setSearchOpen] = useState(false);
|
|
117
122
|
const [searchQuery, setSearchQuery] = useState("");
|
|
@@ -124,7 +129,7 @@ function Layout({ children }) {
|
|
|
124
129
|
}),
|
|
125
130
|
[]
|
|
126
131
|
);
|
|
127
|
-
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(MDXProvider, { components: mergedMdxComponents, children: /* @__PURE__ */ jsxs(MergeContext.Provider, { value: merged, children: [
|
|
132
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(MDXProvider, { components: mergedMdxComponents, children: /* @__PURE__ */ jsx(ReadingPathContext.Provider, { value: continuous ? activePath : null, children: /* @__PURE__ */ jsxs(MergeContext.Provider, { value: merged, children: [
|
|
128
133
|
/* @__PURE__ */ jsx(
|
|
129
134
|
Topbar,
|
|
130
135
|
{
|
|
@@ -151,7 +156,7 @@ function Layout({ children }) {
|
|
|
151
156
|
className: isFullscreen ? "doc-content w-full min-w-0 h-full overflow-auto p-4" : "doc-content w-full min-w-0 px-[18px] pb-20 lg:px-[56px] lg:pb-[120px] lg:max-w-[760px]",
|
|
152
157
|
children: [
|
|
153
158
|
!isFullscreen && /* @__PURE__ */ jsx(PageBreadcrumb, {}),
|
|
154
|
-
children,
|
|
159
|
+
continuous && !isFullscreen ? /* @__PURE__ */ jsx(ContinuousReading, { path: urlPathname, onActive: setActivePath, children }, urlPathname) : children,
|
|
155
160
|
!isFullscreen && /* @__PURE__ */ jsx("div", { "data-pagefind-ignore": true, children: /* @__PURE__ */ jsx(DocFooter, {}) })
|
|
156
161
|
]
|
|
157
162
|
}
|
|
@@ -170,7 +175,7 @@ function Layout({ children }) {
|
|
|
170
175
|
),
|
|
171
176
|
!isFullscreen && /* @__PURE__ */ jsx(H1MergeWatcher, { onChange: setMerged }),
|
|
172
177
|
/* @__PURE__ */ jsx(HeadSync, {})
|
|
173
|
-
] }) }) });
|
|
178
|
+
] }) }) }) });
|
|
174
179
|
}
|
|
175
180
|
export {
|
|
176
181
|
Layout,
|
package/dist/site-config.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface SearchConfig {
|
|
|
40
40
|
mergeIndexes?: MergeIndexDef[];
|
|
41
41
|
}
|
|
42
42
|
export interface SiteConfig {
|
|
43
|
+
/** Offer a Keep scrolling control. Requires initDocs.pageLoaders. Default false. */
|
|
44
|
+
continuousReading?: boolean;
|
|
43
45
|
/** Brand name in the top-left of the shell (e.g. "DreamLake"). */
|
|
44
46
|
brand: string;
|
|
45
47
|
/** Muted secondary label after the brand (e.g. "Dockit"). */
|
package/dist/styles.css
CHANGED
|
@@ -468,3 +468,20 @@
|
|
|
468
468
|
/* Touch has no hover-away state: leave room so actions never mask code. */
|
|
469
469
|
[data-code-block]:has(> .dockit-code-controls) > div:last-child { padding-top: 30px; }
|
|
470
470
|
}
|
|
471
|
+
|
|
472
|
+
/* Preview layout="split": source left, live render right; stacked when the
|
|
473
|
+
frame is narrower than 560px. The render pane is a size container so a
|
|
474
|
+
demo's container queries follow the pane, not the page. */
|
|
475
|
+
.dockit-preview[data-preview-layout='split'] { container: dockit-preview / inline-size; }
|
|
476
|
+
.dockit-preview-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
|
|
477
|
+
.dockit-preview-split-source { border-right: 1px solid var(--color-doc-template-faint); overflow-x: auto; }
|
|
478
|
+
.dockit-preview-split-render { container-type: inline-size; }
|
|
479
|
+
@container dockit-preview (max-width: 560px) {
|
|
480
|
+
.dockit-preview-split { grid-template-columns: minmax(0, 1fr); }
|
|
481
|
+
.dockit-preview-split-source { border-right: 0; border-bottom: 1px solid var(--color-doc-template-faint); }
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.doc-reading-toggle { display:flex; align-items:center; gap:8px; font-size:12px; color:var(--color-doc-template-muted); margin:12px 0; }
|
|
485
|
+
.doc-reading-page { border-top:1px solid var(--color-doc-template-faint); margin-top:64px; padding-top:24px; }
|
|
486
|
+
.doc-reading-permalink, .doc-reading-next { font-size:12px; color:var(--color-doc-template-muted); }
|
|
487
|
+
.doc-reading-next { min-height:56px; margin-top:32px; }
|
package/package.json
CHANGED