@nendlabs/docpage 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,832 @@
1
+ var __create = Object.create;
2
+ var __getProtoOf = Object.getPrototypeOf;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __toESM = (mod, isNodeMode, target) => {
7
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
8
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
9
+ for (let key of __getOwnPropNames(mod))
10
+ if (!__hasOwnProp.call(to, key))
11
+ __defProp(to, key, {
12
+ get: () => mod[key],
13
+ enumerable: true
14
+ });
15
+ return to;
16
+ };
17
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
18
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
19
+ }) : x)(function(x) {
20
+ if (typeof require !== "undefined")
21
+ return require.apply(this, arguments);
22
+ throw Error('Dynamic require of "' + x + '" is not supported');
23
+ });
24
+
25
+ // src/cn.ts
26
+ import { clsx } from "clsx";
27
+ import { twMerge } from "tailwind-merge";
28
+ function cn(...inputs) {
29
+ return twMerge(clsx(inputs));
30
+ }
31
+ // src/docpage.tsx
32
+ import { ArrowRight } from "lucide-react";
33
+ import {
34
+ Children,
35
+ isValidElement,
36
+ useEffect as useEffect5,
37
+ useMemo as useMemo4,
38
+ useState as useState4
39
+ } from "react";
40
+ import { MDXProvider } from "@mdx-js/react";
41
+
42
+ // src/components/api-tabs.tsx
43
+ import { useMemo as useMemo2, useState } from "react";
44
+
45
+ // src/components/code-block.tsx
46
+ import hljs from "highlight.js/lib/core";
47
+ import bash from "highlight.js/lib/languages/bash";
48
+ import diff from "highlight.js/lib/languages/diff";
49
+ import javascript from "highlight.js/lib/languages/javascript";
50
+ import json from "highlight.js/lib/languages/json";
51
+ import typescript from "highlight.js/lib/languages/typescript";
52
+ import yaml from "highlight.js/lib/languages/yaml";
53
+ import { useEffect, useMemo, useRef } from "react";
54
+ import { jsxDEV } from "react/jsx-dev-runtime";
55
+ var registered = false;
56
+ function registerLanguagesOnce() {
57
+ if (registered)
58
+ return;
59
+ hljs.registerLanguage("bash", bash);
60
+ hljs.registerLanguage("sh", bash);
61
+ hljs.registerLanguage("shell", bash);
62
+ hljs.registerLanguage("diff", diff);
63
+ hljs.registerLanguage("javascript", javascript);
64
+ hljs.registerLanguage("js", javascript);
65
+ hljs.registerLanguage("typescript", typescript);
66
+ hljs.registerLanguage("ts", typescript);
67
+ hljs.registerLanguage("json", json);
68
+ hljs.registerLanguage("yaml", yaml);
69
+ hljs.registerLanguage("yml", yaml);
70
+ registered = true;
71
+ }
72
+ function CodeBlock({
73
+ code,
74
+ language,
75
+ caption,
76
+ className,
77
+ preClassName,
78
+ codeClassName
79
+ }) {
80
+ const codeRef = useRef(null);
81
+ const languageClass = useMemo(() => {
82
+ if (!language)
83
+ return;
84
+ return language.startsWith("language-") ? language : `language-${language}`;
85
+ }, [language]);
86
+ useEffect(() => {
87
+ registerLanguagesOnce();
88
+ const el = codeRef.current;
89
+ if (!el)
90
+ return;
91
+ try {
92
+ if (el.dataset.highlighted) {
93
+ delete el.dataset.highlighted;
94
+ }
95
+ hljs.highlightElement(el);
96
+ } catch (error) {
97
+ if (import.meta.env?.DEV) {
98
+ console.error("docpage: highlight.js failed", error);
99
+ }
100
+ }
101
+ }, [code, languageClass]);
102
+ return /* @__PURE__ */ jsxDEV("figure", {
103
+ className: cn("docpage-code", className),
104
+ children: [
105
+ /* @__PURE__ */ jsxDEV("pre", {
106
+ className: cn("bg-muted/40 overflow-x-auto whitespace-pre-wrap rounded p-3 text-xs leading-6", preClassName),
107
+ children: /* @__PURE__ */ jsxDEV("code", {
108
+ ref: codeRef,
109
+ className: cn("hljs", languageClass, codeClassName),
110
+ children: code
111
+ }, undefined, false, undefined, this)
112
+ }, undefined, false, undefined, this),
113
+ caption ? /* @__PURE__ */ jsxDEV("figcaption", {
114
+ className: "mt-2 text-xs text-muted-foreground",
115
+ children: caption
116
+ }, undefined, false, undefined, this) : null
117
+ ]
118
+ }, undefined, true, undefined, this);
119
+ }
120
+
121
+ // src/components/api-tabs.tsx
122
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
123
+ function getInitialTabId(tabs, defaultTabId) {
124
+ if (defaultTabId && tabs.some((tab) => tab.id === defaultTabId)) {
125
+ return defaultTabId;
126
+ }
127
+ return tabs[0]?.id ?? "";
128
+ }
129
+ function getTabLabel(tab) {
130
+ if (tab.label)
131
+ return tab.label;
132
+ return tab.id.toUpperCase();
133
+ }
134
+ function ApiTabs({ tabs, defaultTabId, className }) {
135
+ const [activeId, setActiveId] = useState(() => getInitialTabId(tabs, defaultTabId));
136
+ const activeTab = useMemo2(() => {
137
+ return tabs.find((tab) => tab.id === activeId) ?? tabs[0];
138
+ }, [tabs, activeId]);
139
+ if (!activeTab)
140
+ return null;
141
+ return /* @__PURE__ */ jsxDEV2("div", {
142
+ className: cn("docpage-api space-y-3", className),
143
+ children: [
144
+ /* @__PURE__ */ jsxDEV2("div", {
145
+ className: "inline-flex rounded border border-border/80 bg-background/60 p-1",
146
+ children: tabs.map((tab) => {
147
+ const isActive = activeTab.id === tab.id;
148
+ return /* @__PURE__ */ jsxDEV2("button", {
149
+ type: "button",
150
+ onClick: () => setActiveId(tab.id),
151
+ className: cn("rounded px-3 py-1 text-[11px] font-semibold tracking-[0.12em] transition-colors", isActive ? "bg-foreground text-background" : "text-muted-foreground hover:text-foreground"),
152
+ "aria-pressed": isActive,
153
+ "data-docpage-tab": tab.id,
154
+ children: getTabLabel(tab)
155
+ }, tab.id, false, undefined, this);
156
+ })
157
+ }, undefined, false, undefined, this),
158
+ /* @__PURE__ */ jsxDEV2(CodeBlock, {
159
+ code: activeTab.code,
160
+ language: activeTab.language ?? activeTab.id,
161
+ preClassName: "text-xs"
162
+ }, undefined, false, undefined, this)
163
+ ]
164
+ }, undefined, true, undefined, this);
165
+ }
166
+
167
+ // src/components/mermaid.tsx
168
+ import { useEffect as useEffect2, useId, useRef as useRef2 } from "react";
169
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
170
+ function Mermaid({ chart }) {
171
+ const ref = useRef2(null);
172
+ const ridRaw = useId();
173
+ const rid = ridRaw.replace(/:/g, "");
174
+ useEffect2(() => {
175
+ let cancelled = false;
176
+ const mql = typeof window !== "undefined" && window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
177
+ async function render() {
178
+ try {
179
+ const mermaid = (await import("mermaid")).default;
180
+ const theme = mql?.matches ? "dark" : "default";
181
+ mermaid.initialize({ startOnLoad: false, theme });
182
+ const { svg } = await mermaid.render(`mmd-${rid}`, chart);
183
+ if (!cancelled && ref.current) {
184
+ ref.current.innerHTML = svg;
185
+ }
186
+ } catch (error) {
187
+ if (ref.current) {
188
+ const safeChart = chart.replaceAll("<", "&lt;");
189
+ ref.current.innerHTML = `<pre class="text-xs p-3 rounded bg-muted/40 overflow-x-auto">${safeChart}</pre>`;
190
+ }
191
+ if (import.meta.env?.DEV) {
192
+ console.error("docpage: failed to render mermaid", error);
193
+ }
194
+ }
195
+ }
196
+ render();
197
+ const onChange = () => {
198
+ if (!cancelled)
199
+ render();
200
+ };
201
+ mql?.addEventListener?.("change", onChange);
202
+ return () => {
203
+ cancelled = true;
204
+ mql?.removeEventListener?.("change", onChange);
205
+ };
206
+ }, [chart, rid]);
207
+ return /* @__PURE__ */ jsxDEV3("div", {
208
+ ref,
209
+ "data-docpage-mermaid": true
210
+ }, undefined, false, undefined, this);
211
+ }
212
+
213
+ // src/hooks/use-active-scroll-section-ids.tsx
214
+ import { useEffect as useEffect3, useMemo as useMemo3, useState as useState2 } from "react";
215
+ function getInitialActiveId(ids) {
216
+ if (typeof window === "undefined") {
217
+ return ids[0] ?? "";
218
+ }
219
+ const hash = window.location.hash.replace("#", "");
220
+ return hash && ids.includes(hash) ? hash : ids[0] ?? "";
221
+ }
222
+ function useActiveScrollSectionIds(ids, options) {
223
+ const memoIds = useMemo3(() => ids.filter(Boolean), [ids]);
224
+ const [active, setActive] = useState2(() => getInitialActiveId(memoIds));
225
+ useEffect3(() => {
226
+ if (memoIds.length === 0)
227
+ return;
228
+ const observer = new IntersectionObserver((entries) => {
229
+ const visible = entries.filter((entry) => entry.isIntersecting).sort((a, b) => a.boundingClientRect.top > b.boundingClientRect.top ? 1 : -1);
230
+ if (!visible[0])
231
+ return;
232
+ const id = visible[0].target.id;
233
+ if (!id)
234
+ return;
235
+ setActive((prev) => prev === id ? prev : id);
236
+ }, {
237
+ rootMargin: options?.rootMargin ?? "-20% 0px -70% 0px",
238
+ threshold: options?.threshold ?? [0, 1]
239
+ });
240
+ memoIds.forEach((id) => {
241
+ const el = document.getElementById(id);
242
+ if (el)
243
+ observer.observe(el);
244
+ });
245
+ return () => observer.disconnect();
246
+ }, [memoIds, options?.rootMargin, options?.threshold]);
247
+ useEffect3(() => {
248
+ if (!options?.syncToUrl || !active)
249
+ return;
250
+ const current = window.location.hash.replace("#", "");
251
+ if (current !== active) {
252
+ history.replaceState(null, "", `#${active}`);
253
+ }
254
+ }, [active, options?.syncToUrl]);
255
+ return active;
256
+ }
257
+
258
+ // src/hooks/use-color-scheme.tsx
259
+ import { useEffect as useEffect4, useState as useState3 } from "react";
260
+ function getInitialScheme() {
261
+ if (typeof window === "undefined" || !window.matchMedia)
262
+ return "light";
263
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
264
+ }
265
+ function useColorScheme() {
266
+ const [scheme, setScheme] = useState3(() => getInitialScheme());
267
+ useEffect4(() => {
268
+ if (!window.matchMedia)
269
+ return;
270
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
271
+ const update = (event) => {
272
+ if (event) {
273
+ setScheme(event.matches ? "dark" : "light");
274
+ return;
275
+ }
276
+ setScheme(mql.matches ? "dark" : "light");
277
+ };
278
+ update();
279
+ mql.addEventListener?.("change", update);
280
+ return () => mql.removeEventListener?.("change", update);
281
+ }, []);
282
+ return scheme;
283
+ }
284
+
285
+ // src/docpage.tsx
286
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
287
+ var TOKEN_VAR_MAP = {
288
+ background: "background",
289
+ foreground: "foreground",
290
+ card: "card",
291
+ cardForeground: "card-foreground",
292
+ popover: "popover",
293
+ popoverForeground: "popover-foreground",
294
+ primary: "primary",
295
+ primaryForeground: "primary-foreground",
296
+ secondary: "secondary",
297
+ secondaryForeground: "secondary-foreground",
298
+ muted: "muted",
299
+ mutedForeground: "muted-foreground",
300
+ accent: "accent",
301
+ accentForeground: "accent-foreground",
302
+ destructive: "destructive",
303
+ destructiveForeground: "destructive-foreground",
304
+ border: "border",
305
+ input: "input",
306
+ ring: "ring",
307
+ chart1: "chart-1",
308
+ chart2: "chart-2",
309
+ chart3: "chart-3",
310
+ chart4: "chart-4",
311
+ chart5: "chart-5",
312
+ radius: "radius"
313
+ };
314
+ function setTokenVars(style, tokens, scheme) {
315
+ if (!tokens)
316
+ return;
317
+ Object.keys(tokens).forEach((key) => {
318
+ const value = tokens[key];
319
+ if (!value)
320
+ return;
321
+ const varKey = TOKEN_VAR_MAP[key];
322
+ style[`--docpage-${varKey}-${scheme}`] = value;
323
+ });
324
+ }
325
+ function themeToStyle(config) {
326
+ const style = {};
327
+ setTokenVars(style, config.theme?.light, "light");
328
+ setTokenVars(style, config.theme?.dark, "dark");
329
+ return style;
330
+ }
331
+ function startCaseId(id) {
332
+ const withSpaces = id.replace(/[-_]/g, " ").trim();
333
+ if (!withSpaces)
334
+ return id;
335
+ return withSpaces.replace(/\b\w/g, (c) => c.toUpperCase());
336
+ }
337
+ function deriveToc(config) {
338
+ if (config.toc && config.toc.length > 0)
339
+ return config.toc;
340
+ return config.sections.map((section) => {
341
+ const labelFromTitle = typeof section.title === "string" ? section.title : undefined;
342
+ return {
343
+ id: section.id,
344
+ label: section.label ?? labelFromTitle ?? startCaseId(section.id)
345
+ };
346
+ });
347
+ }
348
+ function useIsWide(minWidthPx) {
349
+ const [isWide, setIsWide] = useState4(() => {
350
+ if (typeof window === "undefined" || !window.matchMedia)
351
+ return true;
352
+ return window.matchMedia(`(min-width: ${minWidthPx}px)`).matches;
353
+ });
354
+ useEffect5(() => {
355
+ if (!window.matchMedia)
356
+ return;
357
+ const mql = window.matchMedia(`(min-width: ${minWidthPx}px)`);
358
+ const update = (event) => {
359
+ if (event) {
360
+ setIsWide(event.matches);
361
+ return;
362
+ }
363
+ setIsWide(mql.matches);
364
+ };
365
+ update();
366
+ mql.addEventListener?.("change", update);
367
+ return () => mql.removeEventListener?.("change", update);
368
+ }, [minWidthPx]);
369
+ return isWide;
370
+ }
371
+ function Container({ children }) {
372
+ return /* @__PURE__ */ jsxDEV4("div", {
373
+ className: "mx-auto w-full max-w-6xl px-4 sm:px-6 lg:px-8",
374
+ children
375
+ }, undefined, false, undefined, this);
376
+ }
377
+ function Prose({ children }) {
378
+ return /* @__PURE__ */ jsxDEV4("div", {
379
+ className: cn("docpage-prose mx-auto max-w-3xl text-base leading-7 text-foreground/80", "[&>section>h2]:text-foreground [&_p]:text-foreground/80 [&_li]:text-foreground/80", "[&>section>h2]:mb-6 [&>section>h2]:text-2xl [&>section>h2]:font-semibold [&>section>h2]:tracking-tight", "[&>section>p]:my-4 [&_code]:font-mono [&_code]:text-[0.85em]", "[&_pre]:rounded [&_pre]:p-0 [&_pre]:text-xs [&_pre]:leading-6"),
380
+ children
381
+ }, undefined, false, undefined, this);
382
+ }
383
+ function getCalloutToneClasses(tone) {
384
+ switch (tone) {
385
+ case "info":
386
+ return "border-primary/30 bg-primary/5";
387
+ case "warn":
388
+ return "border-amber-500/40 bg-amber-500/10";
389
+ case "danger":
390
+ return "border-destructive/50 bg-destructive/10";
391
+ case "neutral":
392
+ default:
393
+ return "border-border/70 bg-muted/20";
394
+ }
395
+ }
396
+ function renderBlock(block) {
397
+ switch (block.kind) {
398
+ case "p":
399
+ return /* @__PURE__ */ jsxDEV4("p", {
400
+ className: "my-4",
401
+ children: block.text
402
+ }, undefined, false, undefined, this);
403
+ case "ul":
404
+ return /* @__PURE__ */ jsxDEV4("ul", {
405
+ className: "marker:text-muted-foreground list-disc pl-6",
406
+ children: block.items.map((item, index) => /* @__PURE__ */ jsxDEV4("li", {
407
+ className: "my-2",
408
+ children: item
409
+ }, index, false, undefined, this))
410
+ }, undefined, false, undefined, this);
411
+ case "ol":
412
+ return /* @__PURE__ */ jsxDEV4("ol", {
413
+ className: "marker:text-muted-foreground list-decimal pl-6",
414
+ children: block.items.map((item, index) => /* @__PURE__ */ jsxDEV4("li", {
415
+ className: "my-2",
416
+ children: item
417
+ }, index, false, undefined, this))
418
+ }, undefined, false, undefined, this);
419
+ case "labeled-list":
420
+ return /* @__PURE__ */ jsxDEV4("ul", {
421
+ className: "marker:text-muted-foreground list-disc pl-6",
422
+ children: block.items.map((item, index) => /* @__PURE__ */ jsxDEV4("li", {
423
+ className: "my-2",
424
+ children: [
425
+ /* @__PURE__ */ jsxDEV4("strong", {
426
+ children: [
427
+ item.label,
428
+ ":"
429
+ ]
430
+ }, undefined, true, undefined, this),
431
+ " ",
432
+ item.text
433
+ ]
434
+ }, index, true, undefined, this))
435
+ }, undefined, false, undefined, this);
436
+ case "code":
437
+ return /* @__PURE__ */ jsxDEV4("div", {
438
+ className: "my-6",
439
+ children: /* @__PURE__ */ jsxDEV4(CodeBlock, {
440
+ code: block.code,
441
+ language: block.language,
442
+ caption: block.caption
443
+ }, undefined, false, undefined, this)
444
+ }, undefined, false, undefined, this);
445
+ case "pre":
446
+ return /* @__PURE__ */ jsxDEV4("pre", {
447
+ className: "bg-muted/40 my-6 whitespace-pre-wrap rounded p-3 text-xs",
448
+ children: block.code
449
+ }, undefined, false, undefined, this);
450
+ case "mermaid":
451
+ return /* @__PURE__ */ jsxDEV4("figure", {
452
+ className: "my-6",
453
+ children: [
454
+ /* @__PURE__ */ jsxDEV4("div", {
455
+ className: "bg-background rounded border border-border/80 p-4",
456
+ children: /* @__PURE__ */ jsxDEV4(Mermaid, {
457
+ chart: block.chart
458
+ }, undefined, false, undefined, this)
459
+ }, undefined, false, undefined, this),
460
+ block.caption ? /* @__PURE__ */ jsxDEV4("figcaption", {
461
+ className: "mt-2 text-xs text-muted-foreground",
462
+ children: block.caption
463
+ }, undefined, false, undefined, this) : null
464
+ ]
465
+ }, undefined, true, undefined, this);
466
+ case "callout":
467
+ return /* @__PURE__ */ jsxDEV4("div", {
468
+ className: cn("my-6 rounded-lg border p-4", getCalloutToneClasses(block.tone)),
469
+ children: [
470
+ block.title ? /* @__PURE__ */ jsxDEV4("div", {
471
+ className: "text-sm font-semibold text-foreground",
472
+ children: block.title
473
+ }, undefined, false, undefined, this) : null,
474
+ /* @__PURE__ */ jsxDEV4("div", {
475
+ className: cn("text-sm leading-relaxed", block.title ? "mt-1" : undefined),
476
+ children: block.body
477
+ }, undefined, false, undefined, this)
478
+ ]
479
+ }, undefined, true, undefined, this);
480
+ case "node":
481
+ return /* @__PURE__ */ jsxDEV4("div", {
482
+ className: "my-4",
483
+ children: block.node
484
+ }, undefined, false, undefined, this);
485
+ default:
486
+ return null;
487
+ }
488
+ }
489
+ function getLanguageFromClassName(className) {
490
+ if (!className)
491
+ return;
492
+ if (className.startsWith("language-")) {
493
+ return className.replace("language-", "");
494
+ }
495
+ return className;
496
+ }
497
+ function toCodeString(value) {
498
+ if (typeof value === "string")
499
+ return value;
500
+ if (typeof value === "number" || typeof value === "boolean")
501
+ return String(value);
502
+ if (value == null)
503
+ return "";
504
+ return String(value);
505
+ }
506
+ function MdxCodeBlockPre(props) {
507
+ const child = Children.count(props.children) === 1 ? Children.only(props.children) : null;
508
+ if (child && isValidElement(child)) {
509
+ const codeChild = child;
510
+ const language = getLanguageFromClassName(codeChild.props.className);
511
+ const code = toCodeString(codeChild.props.children);
512
+ return /* @__PURE__ */ jsxDEV4(CodeBlock, {
513
+ code,
514
+ language
515
+ }, undefined, false, undefined, this);
516
+ }
517
+ return /* @__PURE__ */ jsxDEV4("pre", {
518
+ ...props,
519
+ className: cn("bg-muted/40 overflow-x-auto whitespace-pre-wrap rounded p-3 text-xs leading-6", props.className)
520
+ }, undefined, false, undefined, this);
521
+ }
522
+ function buildMdxComponents(section) {
523
+ const defaults = {
524
+ pre: MdxCodeBlockPre
525
+ };
526
+ return {
527
+ ...defaults,
528
+ ...section.components ?? {}
529
+ };
530
+ }
531
+ function getSectionTitle(section, tocMap) {
532
+ if (section.title)
533
+ return section.title;
534
+ const fromToc = tocMap.get(section.id);
535
+ return fromToc ?? startCaseId(section.id);
536
+ }
537
+ function SectionHeading({
538
+ title,
539
+ titleBorder
540
+ }) {
541
+ return /* @__PURE__ */ jsxDEV4("h2", {
542
+ className: cn("mb-8 mt-12 text-2xl font-semibold tracking-tight first:mt-0", titleBorder ? "border-muted border-b pb-2" : "pb-2"),
543
+ children: title
544
+ }, undefined, false, undefined, this);
545
+ }
546
+ function Nav({ config }) {
547
+ const [scrolled, setScrolled] = useState4(false);
548
+ useEffect5(() => {
549
+ const onScroll = () => setScrolled(window.scrollY > 8);
550
+ onScroll();
551
+ window.addEventListener("scroll", onScroll, { passive: true });
552
+ return () => window.removeEventListener("scroll", onScroll);
553
+ }, []);
554
+ const signInLabel = config.nav?.signInLabel ?? "sign in";
555
+ const signInHref = config.nav?.signInHref ?? "/login";
556
+ return /* @__PURE__ */ jsxDEV4("div", {
557
+ className: cn("sticky top-0 z-40 w-full backdrop-blur", scrolled ? "border-b border-border/80 bg-background/80" : "bg-background/60"),
558
+ "data-docpage-nav": true,
559
+ children: /* @__PURE__ */ jsxDEV4(Container, {
560
+ children: /* @__PURE__ */ jsxDEV4("div", {
561
+ className: "flex h-14 items-center justify-between",
562
+ children: [
563
+ /* @__PURE__ */ jsxDEV4(Brand, {
564
+ brand: config.brand
565
+ }, undefined, false, undefined, this),
566
+ config.nav?.rightSlot ? config.nav.rightSlot : /* @__PURE__ */ jsxDEV4("a", {
567
+ href: signInHref,
568
+ className: cn("group inline-flex items-center rounded-md border border-border/80 px-3 py-1.5 text-xs font-semibold uppercase tracking-[0.2em]", "text-foreground transition hover:border-foreground/60 hover:bg-foreground hover:text-background"),
569
+ "data-docpage-signin": true,
570
+ children: [
571
+ signInLabel,
572
+ /* @__PURE__ */ jsxDEV4(ArrowRight, {
573
+ className: "ml-1 h-4 w-4 transition-transform group-hover:translate-x-0.5"
574
+ }, undefined, false, undefined, this)
575
+ ]
576
+ }, undefined, true, undefined, this)
577
+ ]
578
+ }, undefined, true, undefined, this)
579
+ }, undefined, false, undefined, this)
580
+ }, undefined, false, undefined, this);
581
+ }
582
+ function Brand({ brand }) {
583
+ const content = brand.logo ? /* @__PURE__ */ jsxDEV4("div", {
584
+ className: "flex items-center gap-2",
585
+ children: brand.logo
586
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV4("span", {
587
+ className: "text-sm font-semibold tracking-[0.2em] uppercase",
588
+ children: brand.name
589
+ }, undefined, false, undefined, this);
590
+ if (!brand.href)
591
+ return content;
592
+ return /* @__PURE__ */ jsxDEV4("a", {
593
+ href: brand.href,
594
+ className: "inline-flex items-center text-foreground",
595
+ "data-docpage-brand": true,
596
+ children: content
597
+ }, undefined, false, undefined, this);
598
+ }
599
+ function Toc({
600
+ entries,
601
+ activeId,
602
+ title
603
+ }) {
604
+ return /* @__PURE__ */ jsxDEV4("nav", {
605
+ "aria-label": "Table of contents",
606
+ className: "text-sm",
607
+ "data-docpage-toc": true,
608
+ children: [
609
+ /* @__PURE__ */ jsxDEV4("div", {
610
+ className: "mb-2 font-medium text-foreground",
611
+ children: title
612
+ }, undefined, false, undefined, this),
613
+ /* @__PURE__ */ jsxDEV4("ol", {
614
+ className: "space-y-1",
615
+ children: entries.map((entry) => {
616
+ const isActive = activeId === entry.id;
617
+ return /* @__PURE__ */ jsxDEV4("li", {
618
+ children: /* @__PURE__ */ jsxDEV4("a", {
619
+ href: `#${entry.id}`,
620
+ className: cn("block rounded px-2 py-1 transition-colors", isActive ? "font-semibold text-foreground" : "text-muted-foreground hover:text-foreground"),
621
+ onClick: () => history.replaceState(null, "", `#${entry.id}`),
622
+ "data-docpage-toc-link": entry.id,
623
+ "aria-current": isActive ? "true" : undefined,
624
+ children: entry.label
625
+ }, undefined, false, undefined, this)
626
+ }, entry.id, false, undefined, this);
627
+ })
628
+ }, undefined, false, undefined, this)
629
+ ]
630
+ }, undefined, true, undefined, this);
631
+ }
632
+ function Header({ config }) {
633
+ return /* @__PURE__ */ jsxDEV4(Container, {
634
+ children: /* @__PURE__ */ jsxDEV4("header", {
635
+ className: "py-12",
636
+ "data-docpage-header": true,
637
+ children: [
638
+ config.header.kicker ? /* @__PURE__ */ jsxDEV4("div", {
639
+ className: "mb-3 text-xs font-semibold uppercase tracking-[0.3em] text-muted-foreground",
640
+ children: config.header.kicker
641
+ }, undefined, false, undefined, this) : null,
642
+ /* @__PURE__ */ jsxDEV4("h1", {
643
+ className: "mb-2 text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl",
644
+ children: config.header.title
645
+ }, undefined, false, undefined, this),
646
+ config.header.subtitle ? /* @__PURE__ */ jsxDEV4("p", {
647
+ className: "max-w-2xl text-lg text-muted-foreground",
648
+ children: config.header.subtitle
649
+ }, undefined, false, undefined, this) : null
650
+ ]
651
+ }, undefined, true, undefined, this)
652
+ }, undefined, false, undefined, this);
653
+ }
654
+ function renderSection(section, tocMap) {
655
+ const title = getSectionTitle(section, tocMap);
656
+ switch (section.kind) {
657
+ case "prose":
658
+ return /* @__PURE__ */ jsxDEV4("section", {
659
+ id: section.id,
660
+ className: cn("scroll-mt-24", section.className),
661
+ "data-docpage-section": section.id,
662
+ children: [
663
+ !section.hideTitle ? /* @__PURE__ */ jsxDEV4(SectionHeading, {
664
+ title,
665
+ titleBorder: section.titleBorder
666
+ }, undefined, false, undefined, this) : null,
667
+ /* @__PURE__ */ jsxDEV4("div", {
668
+ className: "space-y-4",
669
+ children: section.blocks.map((block, index) => /* @__PURE__ */ jsxDEV4("div", {
670
+ children: renderBlock(block)
671
+ }, index, false, undefined, this))
672
+ }, undefined, false, undefined, this)
673
+ ]
674
+ }, section.id, true, undefined, this);
675
+ case "api":
676
+ return /* @__PURE__ */ jsxDEV4("section", {
677
+ id: section.id,
678
+ className: cn("scroll-mt-24", section.className),
679
+ "data-docpage-section": section.id,
680
+ children: [
681
+ !section.hideTitle ? /* @__PURE__ */ jsxDEV4(SectionHeading, {
682
+ title,
683
+ titleBorder: section.titleBorder
684
+ }, undefined, false, undefined, this) : null,
685
+ section.intro ? /* @__PURE__ */ jsxDEV4("p", {
686
+ className: "mt-4",
687
+ children: section.intro
688
+ }, undefined, false, undefined, this) : null,
689
+ /* @__PURE__ */ jsxDEV4("div", {
690
+ className: "mt-4",
691
+ children: /* @__PURE__ */ jsxDEV4(ApiTabs, {
692
+ tabs: section.tabs,
693
+ defaultTabId: section.defaultTabId
694
+ }, undefined, false, undefined, this)
695
+ }, undefined, false, undefined, this)
696
+ ]
697
+ }, section.id, true, undefined, this);
698
+ case "mdx": {
699
+ const components = buildMdxComponents(section);
700
+ return /* @__PURE__ */ jsxDEV4("section", {
701
+ id: section.id,
702
+ className: cn("scroll-mt-24", section.className),
703
+ "data-docpage-section": section.id,
704
+ children: [
705
+ !section.hideTitle ? /* @__PURE__ */ jsxDEV4(SectionHeading, {
706
+ title,
707
+ titleBorder: section.titleBorder
708
+ }, undefined, false, undefined, this) : null,
709
+ /* @__PURE__ */ jsxDEV4("div", {
710
+ className: "docpage-mdx",
711
+ children: /* @__PURE__ */ jsxDEV4(MDXProvider, {
712
+ components,
713
+ children: /* @__PURE__ */ jsxDEV4(section.Component, {}, undefined, false, undefined, this)
714
+ }, undefined, false, undefined, this)
715
+ }, undefined, false, undefined, this)
716
+ ]
717
+ }, section.id, true, undefined, this);
718
+ }
719
+ default:
720
+ return null;
721
+ }
722
+ }
723
+ function Footer({ config }) {
724
+ const footer = config.footer;
725
+ if (!footer)
726
+ return null;
727
+ const year = new Date().getFullYear();
728
+ return /* @__PURE__ */ jsxDEV4("footer", {
729
+ className: "border-t border-border/80 py-10 text-sm text-muted-foreground",
730
+ "data-docpage-footer": true,
731
+ children: /* @__PURE__ */ jsxDEV4(Container, {
732
+ children: /* @__PURE__ */ jsxDEV4("div", {
733
+ className: "flex flex-col items-start justify-between gap-4 md:flex-row md:items-center",
734
+ children: [
735
+ footer.links && footer.links.length > 0 ? /* @__PURE__ */ jsxDEV4("div", {
736
+ className: "flex flex-wrap items-center gap-4",
737
+ children: footer.links.map((link) => /* @__PURE__ */ jsxDEV4("a", {
738
+ className: "hover:text-foreground",
739
+ href: link.href,
740
+ children: link.label
741
+ }, link.href, false, undefined, this))
742
+ }, undefined, false, undefined, this) : null,
743
+ /* @__PURE__ */ jsxDEV4("div", {
744
+ className: "flex flex-col gap-1 md:items-end",
745
+ children: [
746
+ /* @__PURE__ */ jsxDEV4("div", {
747
+ children: [
748
+ "© ",
749
+ year,
750
+ " ",
751
+ footer.copyrightName ?? config.brand.name
752
+ ]
753
+ }, undefined, true, undefined, this),
754
+ footer.note ? /* @__PURE__ */ jsxDEV4("div", {
755
+ className: "text-xs",
756
+ children: footer.note
757
+ }, undefined, false, undefined, this) : null
758
+ ]
759
+ }, undefined, true, undefined, this)
760
+ ]
761
+ }, undefined, true, undefined, this)
762
+ }, undefined, false, undefined, this)
763
+ }, undefined, false, undefined, this);
764
+ }
765
+ function DocPage({ config, className }) {
766
+ const tocEntries = useMemo4(() => deriveToc(config), [config]);
767
+ const tocIds = tocEntries.map((entry) => entry.id);
768
+ const tocTitle = config.tocTitle ?? "Contents";
769
+ const tocMap = useMemo4(() => {
770
+ return new Map(tocEntries.map((entry) => [entry.id, entry.label]));
771
+ }, [tocEntries]);
772
+ const tocActiveId = useActiveScrollSectionIds(tocIds, {
773
+ rootMargin: config.options?.tocRootMargin,
774
+ threshold: config.options?.tocThreshold,
775
+ syncToUrl: config.options?.syncTocToUrl ?? true
776
+ });
777
+ const tocMinWidthPx = config.options?.tocMinWidthPx ?? 768;
778
+ const isWide = useIsWide(tocMinWidthPx);
779
+ const scheme = useColorScheme();
780
+ const themeStyle = themeToStyle(config);
781
+ const mergedStyle = { ...themeStyle, ...config.style ?? {} };
782
+ return /* @__PURE__ */ jsxDEV4("div", {
783
+ className: cn("docpage min-h-[100dvh] bg-background text-foreground", config.className, className),
784
+ style: mergedStyle,
785
+ "data-docpage": true,
786
+ "data-docpage-theme": scheme,
787
+ children: [
788
+ /* @__PURE__ */ jsxDEV4(Nav, {
789
+ config
790
+ }, undefined, false, undefined, this),
791
+ /* @__PURE__ */ jsxDEV4(Header, {
792
+ config
793
+ }, undefined, false, undefined, this),
794
+ /* @__PURE__ */ jsxDEV4(Container, {
795
+ children: /* @__PURE__ */ jsxDEV4("div", {
796
+ className: "grid grid-cols-1 gap-10 md:grid-cols-[260px_minmax(0,1fr)]",
797
+ "data-docpage-body": true,
798
+ children: [
799
+ /* @__PURE__ */ jsxDEV4("aside", {
800
+ className: "hidden max-h-[calc(100vh-7rem)] overflow-auto pr-4 md:sticky md:top-24 md:block",
801
+ style: isWide ? undefined : { display: "none" },
802
+ children: /* @__PURE__ */ jsxDEV4(Toc, {
803
+ entries: tocEntries,
804
+ activeId: tocActiveId,
805
+ title: tocTitle
806
+ }, undefined, false, undefined, this)
807
+ }, undefined, false, undefined, this),
808
+ /* @__PURE__ */ jsxDEV4("main", {
809
+ className: "pb-24",
810
+ children: /* @__PURE__ */ jsxDEV4(Prose, {
811
+ children: config.sections.map((section) => renderSection(section, tocMap))
812
+ }, undefined, false, undefined, this)
813
+ }, undefined, false, undefined, this)
814
+ ]
815
+ }, undefined, true, undefined, this)
816
+ }, undefined, false, undefined, this),
817
+ /* @__PURE__ */ jsxDEV4(Footer, {
818
+ config
819
+ }, undefined, false, undefined, this)
820
+ ]
821
+ }, undefined, true, undefined, this);
822
+ }
823
+ export {
824
+ useColorScheme,
825
+ useActiveScrollSectionIds,
826
+ cn,
827
+ Mermaid,
828
+ MdxCodeBlockPre,
829
+ DocPage,
830
+ CodeBlock,
831
+ ApiTabs
832
+ };