@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.
Files changed (66) hide show
  1. package/dist/components/Callout.d.ts +11 -0
  2. package/dist/components/Callout.js +101 -0
  3. package/dist/components/ClientOnly.d.ts +4 -0
  4. package/dist/components/ClientOnly.js +11 -0
  5. package/dist/components/CodeBlock.d.ts +13 -0
  6. package/dist/components/CodeBlock.js +155 -0
  7. package/dist/components/DocFooter.d.ts +1 -0
  8. package/dist/components/DocFooter.js +63 -0
  9. package/dist/components/Preview.d.ts +16 -0
  10. package/dist/components/Preview.js +220 -0
  11. package/dist/components/SearchPalette.d.ts +8 -0
  12. package/dist/components/SearchPalette.js +678 -0
  13. package/dist/components/SearchResize.d.ts +11 -0
  14. package/dist/components/SearchResize.js +150 -0
  15. package/dist/components/Sidebar.d.ts +1 -0
  16. package/dist/components/Sidebar.js +134 -0
  17. package/dist/components/StatusTable.d.ts +19 -0
  18. package/dist/components/StatusTable.js +251 -0
  19. package/dist/components/TOC.d.ts +1 -0
  20. package/dist/components/TOC.js +674 -0
  21. package/dist/components/TabStrip.d.ts +8 -0
  22. package/dist/components/TabStrip.js +105 -0
  23. package/dist/components/ThemeProvider.d.ts +11 -0
  24. package/dist/components/ThemeProvider.js +40 -0
  25. package/dist/components/ThemeToggle.d.ts +2 -0
  26. package/dist/components/ThemeToggle.js +109 -0
  27. package/dist/components/Topbar.d.ts +9 -0
  28. package/dist/components/Topbar.js +818 -0
  29. package/dist/components/mdx-components.d.ts +30 -0
  30. package/dist/components/mdx-components.js +346 -0
  31. package/dist/index.d.ts +61 -0
  32. package/dist/index.js +81 -0
  33. package/dist/lib/navigation.d.ts +80 -0
  34. package/dist/lib/navigation.js +57 -0
  35. package/dist/lib/pagefind-search.d.ts +21 -0
  36. package/dist/lib/pagefind-search.js +201 -0
  37. package/dist/lib/search-index.d.ts +43 -0
  38. package/dist/lib/search-index.js +112 -0
  39. package/dist/lib/tabs.d.ts +23 -0
  40. package/dist/lib/tabs.js +30 -0
  41. package/dist/lib/use-hidden-toggle.d.ts +15 -0
  42. package/dist/lib/use-hidden-toggle.js +23 -0
  43. package/dist/lib/use-line-numbers.d.ts +9 -0
  44. package/dist/lib/use-line-numbers.js +7 -0
  45. package/dist/lib/use-local-storage.d.ts +15 -0
  46. package/dist/lib/use-local-storage.js +58 -0
  47. package/dist/lib/use-media-query.d.ts +5 -0
  48. package/dist/lib/use-media-query.js +16 -0
  49. package/dist/renderer/Layout.d.ts +5 -0
  50. package/dist/renderer/Layout.js +170 -0
  51. package/dist/renderer/onRenderClient.d.ts +1 -0
  52. package/dist/renderer/onRenderClient.js +23 -0
  53. package/dist/renderer/onRenderHtml.d.ts +5 -0
  54. package/dist/renderer/onRenderHtml.js +44 -0
  55. package/dist/site-config.d.ts +61 -0
  56. package/dist/site-config.js +21 -0
  57. package/dist/styles.css +310 -0
  58. package/dist/vike.d.ts +12 -0
  59. package/dist/vike.js +8 -0
  60. package/dist/vite.d.ts +2 -0
  61. package/dist/vite.js +80 -0
  62. package/package.json +82 -0
  63. package/templates/netlify.example.toml +33 -0
  64. package/templates/set-version.mjs +70 -0
  65. package/templates/version-branch.sh +16 -0
  66. package/templates/versions.example.json +15 -0
@@ -0,0 +1,170 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useState, useContext, createContext, useEffect } from "react";
3
+ import { MDXProvider } from "@mdx-js/react";
4
+ import { usePageContext } from "vike-react/usePageContext";
5
+ import { ThemeProvider } from "../components/ThemeProvider.js";
6
+ import { Topbar } from "../components/Topbar.js";
7
+ import { Sidebar } from "../components/Sidebar.js";
8
+ import { TOC } from "../components/TOC.js";
9
+ import { DocFooter } from "../components/DocFooter.js";
10
+ import { SearchPalette } from "../components/SearchPalette.js";
11
+ import { mdxComponents } from "../components/mdx-components.js";
12
+ import { pages } from "../lib/navigation.js";
13
+ import { siteConfig } from "../site-config.js";
14
+ const SPRING = "cubic-bezier(0.4, 0.7, 0.3, 1)";
15
+ const MergeContext = createContext(false);
16
+ const useMerge = () => useContext(MergeContext);
17
+ function PageBreadcrumb() {
18
+ const { urlPathname } = usePageContext();
19
+ const current = pages.find((p) => p.path === urlPathname);
20
+ const merged = useMerge();
21
+ if (!current) return null;
22
+ return /* @__PURE__ */ jsxs(
23
+ "nav",
24
+ {
25
+ "data-pagefind-ignore": true,
26
+ "aria-label": "Breadcrumb",
27
+ className: "flex items-center text-doc-template-muted uppercase",
28
+ style: {
29
+ gap: 6,
30
+ fontFamily: "var(--font-doc-template-mono)",
31
+ fontSize: 10,
32
+ fontWeight: 500,
33
+ letterSpacing: "0.04em",
34
+ height: 36,
35
+ margin: "8px 0 0",
36
+ opacity: merged ? 0 : 1,
37
+ transform: merged ? "translateY(-6px)" : "translateY(0)",
38
+ pointerEvents: merged ? "none" : "auto",
39
+ transition: `opacity 0.25s ease, transform 0.25s ${SPRING}`
40
+ },
41
+ children: [
42
+ current.section && /* @__PURE__ */ jsxs(Fragment, { children: [
43
+ /* @__PURE__ */ jsx("span", { children: current.section }),
44
+ /* @__PURE__ */ jsx("span", { style: { opacity: 0.5 }, children: "/" })
45
+ ] }),
46
+ /* @__PURE__ */ jsx("span", { className: "text-doc-template-ink", children: current.title })
47
+ ]
48
+ }
49
+ );
50
+ }
51
+ function H1MergeWatcher({ onChange }) {
52
+ useEffect(() => {
53
+ const TOPBAR_H = 40;
54
+ let scheduled = false;
55
+ let merged = false;
56
+ function check() {
57
+ scheduled = false;
58
+ const h1 = document.querySelector("main.doc-content h1");
59
+ const next = h1 ? h1.getBoundingClientRect().bottom < TOPBAR_H + 8 : false;
60
+ if (next !== merged) {
61
+ merged = next;
62
+ onChange(merged);
63
+ }
64
+ }
65
+ function onScroll() {
66
+ if (scheduled) return;
67
+ scheduled = true;
68
+ requestAnimationFrame(check);
69
+ }
70
+ check();
71
+ window.addEventListener("scroll", onScroll, { passive: true });
72
+ window.addEventListener("resize", onScroll);
73
+ return () => {
74
+ window.removeEventListener("scroll", onScroll);
75
+ window.removeEventListener("resize", onScroll);
76
+ };
77
+ }, [onChange]);
78
+ return null;
79
+ }
80
+ function HeadSync() {
81
+ const { urlPathname } = usePageContext();
82
+ useEffect(() => {
83
+ if (typeof document === "undefined") return;
84
+ const current = pages.find((p) => p.path === urlPathname);
85
+ document.title = current ? `${current.title} — ${siteConfig.brand}` : siteConfig.brand;
86
+ const desc = current?.description ?? "";
87
+ let tag = document.querySelector('meta[name="description"]');
88
+ if (desc) {
89
+ if (!tag) {
90
+ tag = document.createElement("meta");
91
+ tag.name = "description";
92
+ document.head.appendChild(tag);
93
+ }
94
+ tag.content = desc;
95
+ } else if (tag) {
96
+ tag.remove();
97
+ }
98
+ let robotsTag = document.querySelector('meta[name="robots"]');
99
+ if (current?.noindex) {
100
+ if (!robotsTag) {
101
+ robotsTag = document.createElement("meta");
102
+ robotsTag.name = "robots";
103
+ document.head.appendChild(robotsTag);
104
+ }
105
+ robotsTag.content = "noindex, nofollow";
106
+ } else if (robotsTag) {
107
+ robotsTag.remove();
108
+ }
109
+ }, [urlPathname]);
110
+ return null;
111
+ }
112
+ function Layout({ children }) {
113
+ const { urlPathname } = usePageContext();
114
+ const current = pages.find((p) => p.path === urlPathname);
115
+ const isFullscreen = current?.fullscreen === true;
116
+ const [searchOpen, setSearchOpen] = useState(false);
117
+ const [searchQuery, setSearchQuery] = useState("");
118
+ const [merged, setMerged] = useState(false);
119
+ const [sidebarOpen, setSidebarOpen] = useState(false);
120
+ return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(MDXProvider, { components: mdxComponents, children: /* @__PURE__ */ jsxs(MergeContext.Provider, { value: merged, children: [
121
+ /* @__PURE__ */ jsx(
122
+ Topbar,
123
+ {
124
+ searchOpen,
125
+ onOpenSearch: () => setSearchOpen(true),
126
+ onCloseSearch: () => setSearchOpen(false),
127
+ query: searchQuery,
128
+ setQuery: setSearchQuery
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsxs(
132
+ "div",
133
+ {
134
+ className: isFullscreen ? "grid items-start mx-auto grid-cols-[minmax(0,1fr)] md:grid-cols-[240px_minmax(0,1fr)]" : "grid items-start mx-auto min-h-screen grid-cols-[minmax(0,1fr)] md:grid-cols-[240px_minmax(0,1fr)] lg:grid-cols-[240px_minmax(0,1fr)_240px]",
135
+ style: isFullscreen ? { height: "calc(100vh - 40px)" } : { maxWidth: 1320 },
136
+ children: [
137
+ /* @__PURE__ */ jsx(Sidebar, {}),
138
+ /* @__PURE__ */ jsxs(
139
+ "main",
140
+ {
141
+ ...current?.noindex ? {} : { "data-pagefind-body": true },
142
+ ...current?.hidden ? { "data-pagefind-meta": "hidden:true" } : {},
143
+ 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]",
144
+ children: [
145
+ !isFullscreen && /* @__PURE__ */ jsx(PageBreadcrumb, {}),
146
+ children,
147
+ !isFullscreen && /* @__PURE__ */ jsx("div", { "data-pagefind-ignore": true, children: /* @__PURE__ */ jsx(DocFooter, {}) })
148
+ ]
149
+ }
150
+ ),
151
+ !isFullscreen && /* @__PURE__ */ jsx(TOC, {})
152
+ ]
153
+ }
154
+ ),
155
+ /* @__PURE__ */ jsx(
156
+ SearchPalette,
157
+ {
158
+ open: searchOpen,
159
+ onClose: () => setSearchOpen(false),
160
+ query: searchQuery
161
+ }
162
+ ),
163
+ !isFullscreen && /* @__PURE__ */ jsx(H1MergeWatcher, { onChange: setMerged }),
164
+ /* @__PURE__ */ jsx(HeadSync, {})
165
+ ] }) }) });
166
+ }
167
+ export {
168
+ Layout,
169
+ useMerge
170
+ };
@@ -0,0 +1 @@
1
+ export declare function onRenderClient(pageContext: any): Promise<void>;
@@ -0,0 +1,23 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import ReactDOM from "react-dom/client";
3
+ import { Layout } from "./Layout.js";
4
+ import { PageContextProvider } from "vike-react/usePageContext";
5
+ let root = null;
6
+ async function onRenderClient(pageContext) {
7
+ const { Page, pageProps } = pageContext;
8
+ const container = document.getElementById("root");
9
+ const tree = /* @__PURE__ */ jsx(PageContextProvider, { pageContext, children: /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsx(Page, { ...pageProps }) }) });
10
+ if (!root) {
11
+ if (container.innerHTML !== "") {
12
+ root = ReactDOM.hydrateRoot(container, tree);
13
+ } else {
14
+ root = ReactDOM.createRoot(container);
15
+ root.render(tree);
16
+ }
17
+ } else {
18
+ root.render(tree);
19
+ }
20
+ }
21
+ export {
22
+ onRenderClient
23
+ };
@@ -0,0 +1,5 @@
1
+ import { escapeInject } from 'vike/server';
2
+ export declare function onRenderHtml(pageContext: any): Promise<{
3
+ documentHtml: ReturnType<typeof escapeInject>;
4
+ pageContext: Record<string, unknown>;
5
+ }>;
@@ -0,0 +1,44 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import ReactDOMServer from "react-dom/server";
3
+ import { Layout } from "./Layout.js";
4
+ import { PageContextProvider } from "vike-react/usePageContext";
5
+ import { dangerouslySkipEscape, escapeInject } from "vike/server";
6
+ import { pages } from "../lib/navigation.js";
7
+ import { siteConfig } from "../site-config.js";
8
+ async function onRenderHtml(pageContext) {
9
+ const { Page, pageProps, urlPathname } = pageContext;
10
+ const html = ReactDOMServer.renderToString(
11
+ /* @__PURE__ */ jsx(PageContextProvider, { pageContext, children: /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsx(Page, { ...pageProps }) }) })
12
+ );
13
+ const current = pages.find((p) => p.path === urlPathname);
14
+ const title = current ? `${current.title} — ${siteConfig.brand}` : siteConfig.brand;
15
+ const description = current?.description ?? "";
16
+ const mdHref = current && !current.noindex ? current.path === "/" ? "/index.md" : `${current.path}.md` : null;
17
+ const themeScript = dangerouslySkipEscape(
18
+ `<script>(function(){try{var raw=localStorage.getItem('doc:theme');var t=raw;try{t=JSON.parse(raw);}catch(_){}var d=document.documentElement;if(t==='light'){d.setAttribute('data-theme','light');}else if(t==='dark'){d.setAttribute('data-theme','dark');}else{d.setAttribute('data-theme',window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');}}catch(e){}})()<\/script>`
19
+ );
20
+ return {
21
+ documentHtml: escapeInject`<!DOCTYPE html>
22
+ <html lang="en">
23
+ <head>
24
+ <meta charset="UTF-8" />
25
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
26
+ ${themeScript}
27
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
28
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
29
+ <link href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700&family=Fira+Code:wght@400;500;600&display=swap" rel="stylesheet" />
30
+ <title>${title}</title>
31
+ ${description ? escapeInject`<meta name="description" content="${description}" />` : ""}
32
+ ${current?.noindex ? escapeInject`<meta name="robots" content="noindex, nofollow" />` : ""}
33
+ ${mdHref ? escapeInject`<link rel="alternate" type="text/markdown" href="${mdHref}" />` : ""}
34
+ </head>
35
+ <body>
36
+ <div id="root">${dangerouslySkipEscape(html)}</div>
37
+ </body>
38
+ </html>`,
39
+ pageContext: {}
40
+ };
41
+ }
42
+ export {
43
+ onRenderHtml
44
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Site-level configuration singleton.
3
+ *
4
+ * The library ships neutral defaults; the consuming site overrides them by
5
+ * calling `defineSiteConfig()` (usually via `initDocs()`) from its
6
+ * `site.config.ts` — imported for its side effect *before* the renderer
7
+ * entries run, so every component sees the final values.
8
+ *
9
+ * The object is mutated in place (never reassigned) so components that did
10
+ * `import { siteConfig }` keep a live reference.
11
+ */
12
+ /** One version chip in the topbar's brand cluster: `[ label | v<version> ]`.
13
+ * With `dropdown: true` the version segment opens a popover listing the
14
+ * deploys from `/versions.json`. */
15
+ export interface VersionChip {
16
+ label: string;
17
+ version: string;
18
+ dropdown?: boolean;
19
+ }
20
+ export interface SiteConfig {
21
+ /** Brand name in the top-left of the shell (e.g. "DreamLake"). */
22
+ brand: string;
23
+ /** Muted secondary label after the brand (e.g. "Dockit"). */
24
+ subtitle: string;
25
+ /** Drives the GitHub link in the top-right of the header. Set to an
26
+ * empty string to hide the icon. */
27
+ repoUrl: string;
28
+ /** Repo + branch that actually hosts the docs pages (the workspace repo,
29
+ * not the product `repoUrl` above). Drives the rail's "Edit this page" /
30
+ * "Report an issue" links. */
31
+ docsRepoUrl: string;
32
+ docsBranch: string;
33
+ /** Leftmost crumb in both the page-top and merged-topbar breadcrumbs.
34
+ * Set to an empty string to omit the root crumb entirely. */
35
+ breadcrumbRoot: string;
36
+ /** Public origin the site is deployed at. Used to build absolute URLs in
37
+ * the LLM-readable artifacts (llms.txt, llms-full.txt, the skill). */
38
+ url: string;
39
+ /** Importable agent-skill name. Drives `skills/<skill>/` at the repo root
40
+ * and the downloadable `<skill>.zip`. */
41
+ skill: string;
42
+ /** One-line product summary. Becomes the blockquote in llms.txt and the
43
+ * skill description. Keep it tight — it's what an LLM reads first. */
44
+ summary: string;
45
+ /** Curated task phrases for the generated agent-skill's "Use when:" trigger
46
+ * list in `gen-llms.mjs` (e.g. "theming the docs shell", "wiring Netlify
47
+ * deploys"). When unset, the generator falls back to the site's section
48
+ * names. */
49
+ skillTriggers?: string[];
50
+ /** Version chips rendered next to the brand in the topbar. */
51
+ versionChips?: VersionChip[];
52
+ /** Short git hash chip in the topbar. Omit to hide the chip. */
53
+ gitHash?: string;
54
+ /** Repo-relative directory holding `pages/` — used to build the TOC's
55
+ * "Edit this page" link (`<docsRepoUrl>/edit/<docsBranch>/<docsPagesPath>/…`).
56
+ * Defaults to 'docs/pages'. */
57
+ docsPagesPath?: string;
58
+ }
59
+ export declare const siteConfig: SiteConfig;
60
+ /** Merge site-provided values into the singleton (mutates in place). */
61
+ export declare function defineSiteConfig(cfg: Partial<SiteConfig>): void;
@@ -0,0 +1,21 @@
1
+ const siteConfig = {
2
+ brand: "Docs",
3
+ subtitle: "",
4
+ repoUrl: "",
5
+ docsRepoUrl: "",
6
+ docsBranch: "main",
7
+ breadcrumbRoot: "",
8
+ url: "",
9
+ skill: "",
10
+ summary: "",
11
+ versionChips: [],
12
+ gitHash: "",
13
+ docsPagesPath: "docs/pages"
14
+ };
15
+ function defineSiteConfig(cfg) {
16
+ Object.assign(siteConfig, cfg);
17
+ }
18
+ export {
19
+ defineSiteConfig,
20
+ siteConfig
21
+ };
@@ -0,0 +1,310 @@
1
+ /* ─────────────────────────────────────────────────────────────────
2
+ @dreamlake/dockit — shell styles. Import from the consuming site's
3
+ app.css AFTER tailwindcss:
4
+
5
+ @import "tailwindcss";
6
+ @import "@dreamlake/dockit/styles.css";
7
+
8
+ The @source below is resolved relative to this file. It is copied to
9
+ dist/styles.css at build time, where it makes Tailwind scan the
10
+ package's compiled JS (dist/) for utility-class usage, so classes
11
+ used only inside dockit components are always generated.
12
+ ───────────────────────────────────────────────────────────────── */
13
+ @source "./";
14
+
15
+ /* ─────────────────────────────────────────────────────────────────
16
+ Prefixed theme tokens — one-to-one with the dreamlake palette so
17
+ utility classes (bg-doc-template-bg, text-doc-template-ink, etc.)
18
+ produce pixel-identical output. The --doc-template- prefix isolates
19
+ us from any consuming library or app's tokens.
20
+ ───────────────────────────────────────────────────────────────── */
21
+ @theme {
22
+ --color-doc-template-bg: #fffefa;
23
+ --color-doc-template-panel: #fcfbf7;
24
+ --color-doc-template-rail: #fcfbf7;
25
+ --color-doc-template-code: #faf8f1;
26
+ --color-doc-template-ink: #1a1a1a;
27
+ --color-doc-template-muted: #6b6b6b;
28
+ --color-doc-template-faint: rgb(0 0 0 / 0.08);
29
+ --color-doc-template-faint-strong: rgb(0 0 0 / 0.16);
30
+ --color-doc-template-chip: rgb(0 0 0 / 0.04);
31
+ --color-doc-template-search: #f5f4f0;
32
+ --color-doc-template-selected: #d9e6f7;
33
+ --color-doc-template-accent: #23aaff;
34
+ --color-doc-template-accent-soft: rgb(35 170 255 / 0.09);
35
+ --color-doc-template-warn: #d68b3a;
36
+ --color-doc-template-warn-soft: rgb(214 139 58 / 0.10);
37
+ --color-doc-template-rail-stroke: #d8d4c8;
38
+
39
+ --font-doc-template-ui: "Inter Tight", ui-sans-serif, system-ui, sans-serif;
40
+ --font-doc-template-mono: "Fira Code", ui-monospace, SFMono-Regular, Menlo, monospace;
41
+
42
+ --radius-doc-template: 10px;
43
+ --radius-doc-template-sm: 6px;
44
+ }
45
+
46
+ /* Dark-mode overrides — same custom property names get re-declared so
47
+ every utility instantly swaps without us touching JSX. Tailwind v4 emits
48
+ @theme tokens as plain CSS vars, so attribute-selector overrides work. */
49
+ [data-theme='dark'] {
50
+ --color-doc-template-bg: #2e2e35;
51
+ --color-doc-template-panel: #2e2e35;
52
+ --color-doc-template-rail: #2b2b31;
53
+ --color-doc-template-code: #2c2c33;
54
+ --color-doc-template-ink: #ececec;
55
+ --color-doc-template-muted: #8a8a8a;
56
+ --color-doc-template-faint: rgb(255 255 255 / 0.09);
57
+ --color-doc-template-faint-strong: rgb(255 255 255 / 0.20);
58
+ --color-doc-template-chip: rgb(255 255 255 / 0.05);
59
+ --color-doc-template-search: #36363c;
60
+ --color-doc-template-selected: #3d4856;
61
+ --color-doc-template-accent-soft: rgb(35 170 255 / 0.18);
62
+ --color-doc-template-warn-soft: rgb(214 139 58 / 0.18);
63
+ --color-doc-template-rail-stroke: #45454d;
64
+ }
65
+
66
+ /* `dark:*` Tailwind variants hook the same [data-theme="dark"] attribute
67
+ the FOUC script in +onRenderHtml.tsx sets. */
68
+ @custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *));
69
+
70
+ @layer base {
71
+ /* Tailwind's default font-sans is ui-sans-serif. We want Inter Tight
72
+ without minting a Tailwind font token, so set on body once. */
73
+ body {
74
+ font-family: var(--font-doc-template-ui);
75
+ background: var(--color-doc-template-bg);
76
+ color: var(--color-doc-template-ink);
77
+ /* Match the dreamlake design's text rendering — without these, Inter
78
+ Tight defaults to subpixel AA which reads chunkier than the design. */
79
+ -webkit-font-smoothing: antialiased;
80
+ -moz-osx-font-smoothing: grayscale;
81
+ text-rendering: optimizeLegibility;
82
+ /* Inter stylistic sets used by the design:
83
+ - ss01: open digit alternates (cleaner 4 / 6 / 9)
84
+ - cv11: single-storey g
85
+ These slim the look noticeably. */
86
+ font-feature-settings: 'ss01', 'cv11';
87
+ }
88
+ code, pre, kbd, .font-mono {
89
+ font-family: var(--font-doc-template-mono);
90
+ }
91
+ }
92
+
93
+ /* Shiki dual-theme bridge — the only mandatory non-utility rule, since
94
+ shiki authors its own <pre><code>…</code></pre> markup we don't
95
+ render directly. Per-token color only — never paint backgrounds, so
96
+ the cream wrapper (`.codeblock` border + bg) is the lone visible
97
+ surface. Setting bg on every span produces white token rectangles
98
+ on top of the cream surface, which reads as a second border. */
99
+ .shiki, .shiki span { color: var(--shiki-light); }
100
+ [data-theme='dark'] .shiki,
101
+ [data-theme='dark'] .shiki span { color: var(--shiki-dark); }
102
+ .shiki {
103
+ background: transparent !important;
104
+ margin: 0;
105
+ padding: 14px 16px;
106
+ font-family: var(--font-doc-template-mono);
107
+ font-size: 12.5px;
108
+ line-height: 1.3;
109
+ overflow-x: auto;
110
+ }
111
+
112
+ /* Pagefind excerpt highlights — matches the inline highlight style
113
+ used by the SearchPalette's custom `highlight()` function. */
114
+ .pagefind-excerpt mark {
115
+ background: color-mix(in srgb, var(--color-doc-template-accent) 18%, transparent);
116
+ color: var(--color-doc-template-ink);
117
+ font-weight: 600;
118
+ border-radius: 2px;
119
+ padding: 0 1px;
120
+ }
121
+
122
+
123
+ /* Preview body in the search palette — scale the full rendered page
124
+ content to fit the narrow preview pane. */
125
+ .preview-body {
126
+ font-size: 100%;
127
+ line-height: 1.55;
128
+ color: color-mix(in srgb, var(--color-doc-template-ink) 80%, transparent);
129
+ }
130
+ .preview-body h1::before { content: '# '; }
131
+ .preview-body h2::before { content: '## '; }
132
+ .preview-body h3::before { content: '### '; }
133
+ .preview-body h1, .preview-body h2, .preview-body h3 {
134
+ all: unset;
135
+ display: block;
136
+ font-size: inherit;
137
+ font-weight: 600;
138
+ margin: 8px 0 4px;
139
+ }
140
+ .preview-body p { margin: 0 0 8px; }
141
+ .preview-body ul, .preview-body ol { margin: 0 0 8px; padding-left: 18px; }
142
+ .preview-body pre {
143
+ font-size: 10.5px;
144
+ line-height: 1.3;
145
+ padding: 8px 10px;
146
+ margin: 0 0 8px;
147
+ border-radius: 6px;
148
+ overflow-x: auto;
149
+ background: var(--color-doc-template-code);
150
+ }
151
+ .preview-body code { font-size: 0.92em; }
152
+ .preview-body img { max-width: 100%; border-radius: 4px; }
153
+ .preview-body table { font-size: 11px; border-collapse: collapse; width: 100%; margin: 0 0 8px; }
154
+ .preview-body th, .preview-body td { padding: 4px 8px; border: 1px solid var(--color-doc-template-faint); }
155
+ .preview-body a { color: var(--color-doc-template-accent); text-decoration: none; pointer-events: none; }
156
+
157
+ /* Trim the last child's bottom margin so the callout's / blockquote's
158
+ own padding doesn't stack on top of a paragraph's `margin-bottom: 14px`.
159
+ The MDX <P> wrapper sets that margin as an inline style, so we need
160
+ !important to win the specificity battle. */
161
+ .doc-callout-body > *:last-child,
162
+ .doc-content blockquote > *:last-child {
163
+ margin-bottom: 0 !important;
164
+ }
165
+
166
+ /* Mute the list-marker color to match dreamlake (default markers
167
+ inherit `color` which would be the ink color — too prominent). */
168
+ .doc-content li::marker {
169
+ color: var(--color-doc-template-muted);
170
+ }
171
+
172
+ /* ─────────────────────────────────────────────────────────────────
173
+ Optional line numbers — toggled by the `:set nu` button in the
174
+ CodeBlock / Preview header. The toggle flips `data-line-numbers`
175
+ on the wrapper; an inline-block `::before` on each Shiki `.line`
176
+ prepends the counter. Keeping `.line` inline (the default) means
177
+ we don't disturb the natural `\n`-driven line breaks Shiki emits
178
+ between line spans — so the no-numbers state stays correct. */
179
+ [data-line-numbers='on'] .shiki code { counter-reset: cl-ln; }
180
+ /* ─────────────────────────────────────────────────────────────────
181
+ Sidebar nav links — pure CSS highlights, no inline style objects.
182
+ ───────────────────────────────────────────────────────────────── */
183
+ .sidebar-link {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 8px;
187
+ padding: 5px 10px;
188
+ font-family: var(--font-doc-template-ui);
189
+ font-size: 12.5px;
190
+ font-weight: 500;
191
+ letter-spacing: -0.005em;
192
+ line-height: 1.25;
193
+ color: var(--color-doc-template-ink);
194
+ text-decoration: none;
195
+ border-radius: var(--radius-doc-template);
196
+ transition: background 0.1s ease;
197
+ }
198
+ .sidebar-link:hover {
199
+ background: color-mix(in srgb, var(--color-doc-template-ink) 5%, transparent);
200
+ }
201
+ .sidebar-link[aria-current='page'] {
202
+ font-weight: 600;
203
+ background: var(--color-doc-template-selected);
204
+ }
205
+
206
+ /* Section header button */
207
+ .sidebar-section {
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 6px;
211
+ width: 100%;
212
+ padding: 6px 10px 4px;
213
+ font-family: var(--font-doc-template-mono);
214
+ font-size: 10.5px;
215
+ font-weight: 600;
216
+ letter-spacing: 0.08em;
217
+ text-transform: uppercase;
218
+ color: var(--color-doc-template-muted);
219
+ opacity: 0.7;
220
+ background: none;
221
+ border: none;
222
+ text-align: left;
223
+ cursor: pointer;
224
+ transition: opacity 0.1s ease, color 0.1s ease;
225
+ }
226
+ .sidebar-section:hover { opacity: 0.85; }
227
+ .sidebar-section[data-folded]:hover {
228
+ opacity: 0.9;
229
+ color: var(--color-doc-template-ink);
230
+ }
231
+
232
+ /* TOC link — CSS-only active/hover */
233
+ .toc-link {
234
+ display: flex;
235
+ align-items: center;
236
+ text-decoration: none;
237
+ color: var(--color-doc-template-muted);
238
+ font-family: var(--font-doc-template-ui);
239
+ font-size: 12.5px;
240
+ font-weight: 500;
241
+ line-height: 1.35;
242
+ letter-spacing: -0.005em;
243
+ padding: 5px 10px 5px 8px;
244
+ transition: color 0.12s ease;
245
+ }
246
+ .toc-link:hover { color: var(--color-doc-template-ink); }
247
+ .toc-link[aria-current='location'] {
248
+ color: var(--color-doc-template-accent);
249
+ font-weight: 600;
250
+ }
251
+ .toc-link[aria-current='location']:hover {
252
+ color: var(--color-doc-template-accent);
253
+ }
254
+ .toc-link[data-level='3'] {
255
+ font-family: var(--font-doc-template-mono);
256
+ font-size: 10.5px;
257
+ text-transform: lowercase;
258
+ letter-spacing: 0.005em;
259
+ }
260
+
261
+ .toc-fold-toggle {
262
+ display: inline-flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ width: 16px;
266
+ height: 16px;
267
+ flex-shrink: 0;
268
+ border-radius: 3px;
269
+ cursor: pointer;
270
+ opacity: 0.5;
271
+ transition: opacity 0.1s ease;
272
+ }
273
+ .toc-fold-toggle:hover { opacity: 1; }
274
+
275
+ [data-line-numbers='on'] .shiki .line::before {
276
+ counter-increment: cl-ln;
277
+ content: counter(cl-ln);
278
+ display: inline-block;
279
+ /* number column + gap-to-border + 1px rule + gap-to-code */
280
+ width: 2em;
281
+ padding-right: 0.6em;
282
+ margin-right: 0.9em;
283
+ border-right: 1px solid var(--color-doc-template-faint);
284
+ text-align: right;
285
+ color: color-mix(in srgb, var(--color-doc-template-ink) 28%, transparent);
286
+ font-variant-numeric: tabular-nums;
287
+ user-select: none;
288
+ pointer-events: none;
289
+ }
290
+
291
+ /* Version-switcher popover: container fades+slides in, then each row
292
+ cascades in with a small per-index stagger via inline animation-delay. */
293
+ @keyframes popover-in {
294
+ from { opacity: 0; transform: translateY(-4px) scale(0.985); }
295
+ to { opacity: 1; transform: translateY(0) scale(1); }
296
+ }
297
+ @keyframes popover-entry-in {
298
+ from { opacity: 0; transform: translateY(-3px); }
299
+ to { opacity: 1; transform: translateY(0); }
300
+ }
301
+ @keyframes popover-wedge-in {
302
+ from { opacity: 0; transform: translateY(-2px); }
303
+ to { opacity: 1; transform: translateY(0); }
304
+ }
305
+ /* Theme toggle (single-button): the current-theme icon springs in when
306
+ the theme changes — a quick rotate+scale settle. */
307
+ @keyframes theme-icon-pop {
308
+ from { opacity: 0; transform: scale(0.6) rotate(-90deg); }
309
+ to { opacity: 1; transform: scale(1) rotate(0deg); }
310
+ }
package/dist/vike.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Vike page config for a dockit site. The consuming site re-exports this
3
+ * from its own `renderer/+config.ts`:
4
+ *
5
+ * export { default } from '@dreamlake/dockit/vike'
6
+ */
7
+ declare const _default: {
8
+ passToClient: string[];
9
+ clientRouting: boolean;
10
+ prerender: boolean;
11
+ };
12
+ export default _default;
package/dist/vike.js ADDED
@@ -0,0 +1,8 @@
1
+ const vike = {
2
+ passToClient: ["pageProps", "urlPathname"],
3
+ clientRouting: true,
4
+ prerender: true
5
+ };
6
+ export {
7
+ vike as default
8
+ };
package/dist/vite.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { PluginOption } from 'vite';
2
+ export declare function dockit(): PluginOption[];