@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,150 @@
1
+ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ const DAY_MS = 864e5;
4
+ function useSearchResize(hitCount, totalChars) {
5
+ const [panelH, setPanelH] = useState(() => {
6
+ if (typeof window === "undefined") return null;
7
+ try {
8
+ const raw = JSON.parse(localStorage.getItem("palette-h") ?? "");
9
+ if (Date.now() - raw.ts > DAY_MS) {
10
+ localStorage.removeItem("palette-h");
11
+ return null;
12
+ }
13
+ return Number.isFinite(raw.v) && raw.v > 0 ? raw.v : null;
14
+ } catch {
15
+ return null;
16
+ }
17
+ });
18
+ const [isResizing, setIsResizing] = useState(false);
19
+ const edgeRef = useRef(null);
20
+ const originRef = useRef({ x: 0, y: 0, w: 0, h: 0 });
21
+ useEffect(() => {
22
+ function onMove(e) {
23
+ if (!edgeRef.current) return;
24
+ const dy = e.clientY - originRef.current.y;
25
+ setPanelH(Math.max(200, Math.min(originRef.current.h + dy, window.innerHeight - 60)));
26
+ }
27
+ function onUp() {
28
+ if (edgeRef.current) {
29
+ edgeRef.current = null;
30
+ setIsResizing(false);
31
+ document.body.style.userSelect = "";
32
+ if (panelH != null) localStorage.setItem("palette-h", JSON.stringify({ v: panelH, ts: Date.now() }));
33
+ }
34
+ }
35
+ window.addEventListener("mousemove", onMove);
36
+ window.addEventListener("mouseup", onUp);
37
+ return () => {
38
+ window.removeEventListener("mousemove", onMove);
39
+ window.removeEventListener("mouseup", onUp);
40
+ };
41
+ }, [panelH]);
42
+ const maxVh = typeof window !== "undefined" ? window.innerHeight * 0.7 : 540;
43
+ const effectiveH = panelH ?? (() => {
44
+ const rowH = Math.max(hitCount, 1) * 48 + 44;
45
+ const charH = 120 + Math.min(totalChars * 0.3, 420);
46
+ return Math.max(250, Math.min(Math.max(rowH, charH), maxVh, 540));
47
+ })();
48
+ function startResize(edge, e) {
49
+ const panel = e.currentTarget.closest("[data-palette-panel]");
50
+ if (!panel) return;
51
+ const rect = panel.getBoundingClientRect();
52
+ edgeRef.current = edge;
53
+ originRef.current = { x: e.clientX, y: e.clientY, w: rect.width, h: rect.height };
54
+ setIsResizing(true);
55
+ document.body.style.userSelect = "none";
56
+ }
57
+ function resetHeight() {
58
+ setPanelH(null);
59
+ localStorage.removeItem("palette-h");
60
+ }
61
+ return { panelH, effectiveH, isResizing, startResize, resetHeight };
62
+ }
63
+ function SearchResizeHandles({ startResize, resetHeight }) {
64
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
65
+ /* @__PURE__ */ jsx("style", { children: `
66
+ .palette-resize .palette-resize-pill {
67
+ opacity: 0;
68
+ transition: opacity 0.15s ease;
69
+ }
70
+ .palette-resize:hover .palette-resize-pill {
71
+ opacity: 0.45;
72
+ }
73
+ ` }),
74
+ /* @__PURE__ */ jsx(
75
+ "div",
76
+ {
77
+ className: "palette-resize",
78
+ onMouseDown: (e) => startResize("bottom", e),
79
+ onDoubleClick: resetHeight,
80
+ style: {
81
+ position: "absolute",
82
+ bottom: 0,
83
+ left: 32,
84
+ right: 32,
85
+ height: 10,
86
+ cursor: "ns-resize",
87
+ zIndex: 10
88
+ },
89
+ children: /* @__PURE__ */ jsx(
90
+ "div",
91
+ {
92
+ className: "palette-resize-pill",
93
+ style: {
94
+ position: "absolute",
95
+ bottom: 3,
96
+ left: "50%",
97
+ transform: "translateX(-50%)",
98
+ width: 48,
99
+ height: 4,
100
+ borderRadius: 9999,
101
+ background: "var(--color-doc-template-muted)"
102
+ }
103
+ }
104
+ )
105
+ }
106
+ ),
107
+ /* @__PURE__ */ jsx(
108
+ "div",
109
+ {
110
+ className: "palette-resize",
111
+ onMouseDown: (e) => startResize("corner", e),
112
+ onDoubleClick: resetHeight,
113
+ style: {
114
+ position: "absolute",
115
+ bottom: 0,
116
+ right: 0,
117
+ width: 24,
118
+ height: 24,
119
+ cursor: "nwse-resize",
120
+ zIndex: 11
121
+ },
122
+ children: /* @__PURE__ */ jsx(
123
+ "svg",
124
+ {
125
+ className: "palette-resize-pill",
126
+ width: "10",
127
+ height: "10",
128
+ viewBox: "0 0 10 10",
129
+ overflow: "visible",
130
+ style: { position: "absolute", bottom: 5, right: 5 },
131
+ children: /* @__PURE__ */ jsx(
132
+ "path",
133
+ {
134
+ d: "M 9 0 A 9 9 0 0 1 0 9",
135
+ stroke: "var(--color-doc-template-muted)",
136
+ strokeWidth: "4",
137
+ strokeLinecap: "round",
138
+ fill: "none"
139
+ }
140
+ )
141
+ }
142
+ )
143
+ }
144
+ )
145
+ ] });
146
+ }
147
+ export {
148
+ SearchResizeHandles,
149
+ useSearchResize
150
+ };
@@ -0,0 +1 @@
1
+ export declare function Sidebar(): import("react").JSX.Element;
@@ -0,0 +1,134 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState, useEffect } from "react";
3
+ import { usePageContext } from "vike-react/usePageContext";
4
+ import { groupedPages, groupedVisiblePages } from "../lib/navigation.js";
5
+ import { useHiddenToggle } from "../lib/use-hidden-toggle.js";
6
+ import { tabForUrl, urlInTab } from "../lib/tabs.js";
7
+ const SIDEBAR_KEY = "sidebar-collapsed";
8
+ function loadCollapsed() {
9
+ if (typeof window === "undefined") return /* @__PURE__ */ new Set();
10
+ try {
11
+ return new Set(JSON.parse(localStorage.getItem(SIDEBAR_KEY) || "[]"));
12
+ } catch {
13
+ return /* @__PURE__ */ new Set();
14
+ }
15
+ }
16
+ function Sidebar() {
17
+ const { urlPathname } = usePageContext();
18
+ const [showHidden] = useHiddenToggle();
19
+ const allGroups = showHidden ? groupedPages : groupedVisiblePages;
20
+ const activeTab = tabForUrl(urlPathname);
21
+ const groups = useMemo(
22
+ () => allGroups.map((g) => ({
23
+ ...g,
24
+ items: g.items.filter((i) => urlInTab(i.path, activeTab))
25
+ })).filter((g) => g.items.length > 0),
26
+ [allGroups, activeTab]
27
+ );
28
+ const [collapsed, setCollapsed] = useState(loadCollapsed);
29
+ function toggle(label) {
30
+ setCollapsed((prev) => {
31
+ const next = new Set(prev);
32
+ if (next.has(label)) next.delete(label);
33
+ else next.add(label);
34
+ localStorage.setItem(SIDEBAR_KEY, JSON.stringify([...next]));
35
+ return next;
36
+ });
37
+ }
38
+ useEffect(() => {
39
+ const g = groups.find((g2) => g2.items.some((i) => i.path === urlPathname));
40
+ if (g?.label && collapsed.has(g.label)) {
41
+ setCollapsed((prev) => {
42
+ const next = new Set(prev);
43
+ next.delete(g.label);
44
+ localStorage.setItem(SIDEBAR_KEY, JSON.stringify([...next]));
45
+ return next;
46
+ });
47
+ }
48
+ }, [urlPathname]);
49
+ return /* @__PURE__ */ jsx(
50
+ "aside",
51
+ {
52
+ "aria-label": "Sections",
53
+ className: "hidden md:flex sticky overflow-y-auto flex-col",
54
+ style: { top: 40, height: "calc(100vh - 40px)", padding: "22px 12px 32px 18px", gap: 2 },
55
+ children: groups.map((group) => {
56
+ const isFolded = group.label ? collapsed.has(group.label) : false;
57
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", style: { gap: 1, marginBottom: isFolded ? 4 : 14, transition: "margin-bottom 0.2s ease" }, children: [
58
+ group.label && /* @__PURE__ */ jsxs(
59
+ "button",
60
+ {
61
+ type: "button",
62
+ onClick: () => toggle(group.label),
63
+ className: "group sidebar-section",
64
+ "data-folded": isFolded || void 0,
65
+ children: [
66
+ /* @__PURE__ */ jsx("span", { children: group.label }),
67
+ /* @__PURE__ */ jsx(
68
+ "span",
69
+ {
70
+ className: isFolded ? "opacity-60" : "opacity-0 group-hover:opacity-60 transition-opacity",
71
+ style: { fontSize: 10, fontWeight: 400, lineHeight: 1, flexShrink: 0 },
72
+ children: isFolded ? "+" : "−"
73
+ }
74
+ ),
75
+ /* @__PURE__ */ jsx("span", { style: { marginLeft: "auto", opacity: 0.85 }, children: String(group.items.length).padStart(2, "0") })
76
+ ]
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsx("div", { style: {
80
+ display: "grid",
81
+ gridTemplateRows: isFolded ? "0fr" : "1fr",
82
+ transition: "grid-template-rows 0.2s ease"
83
+ }, children: /* @__PURE__ */ jsx("div", { style: { overflow: "hidden", minHeight: 0 }, children: group.items.map((item) => /* @__PURE__ */ jsxs(
84
+ "a",
85
+ {
86
+ href: item.path,
87
+ "aria-current": item.path === urlPathname ? "page" : void 0,
88
+ className: "sidebar-link",
89
+ children: [
90
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, minWidth: 0 }, children: item.title }),
91
+ item.hidden && /* @__PURE__ */ jsx(
92
+ "span",
93
+ {
94
+ "aria-hidden": true,
95
+ title: "Internal — only visible when dev mode is on (Cmd+Shift+D)",
96
+ style: { display: "inline-flex", alignItems: "center", color: "var(--color-doc-template-warn)", flexShrink: 0, pointerEvents: "none" },
97
+ children: /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
98
+ /* @__PURE__ */ jsx("rect", { x: "5", y: "11", width: "14", height: "10", rx: "2" }),
99
+ /* @__PURE__ */ jsx("path", { d: "M8 11V7a4 4 0 0 1 7.5-1.2" })
100
+ ] })
101
+ }
102
+ ),
103
+ item.draft && /* @__PURE__ */ jsx(
104
+ "span",
105
+ {
106
+ "aria-label": "Draft — awaiting review",
107
+ title: "Draft — awaiting review",
108
+ style: {
109
+ fontFamily: "var(--font-doc-template-mono)",
110
+ fontSize: 8.5,
111
+ fontWeight: 600,
112
+ letterSpacing: "0.08em",
113
+ padding: "1px 5px",
114
+ borderRadius: 3,
115
+ color: "var(--color-doc-template-warn)",
116
+ background: "var(--color-doc-template-warn-soft)",
117
+ border: "1px solid color-mix(in srgb, var(--color-doc-template-warn) 30%, transparent)",
118
+ flexShrink: 0
119
+ },
120
+ children: "DRAFT"
121
+ }
122
+ )
123
+ ]
124
+ },
125
+ item.path
126
+ )) }) })
127
+ ] }, group.label || "_");
128
+ })
129
+ }
130
+ );
131
+ }
132
+ export {
133
+ Sidebar
134
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Loads /test-results.json (served from docs/public/) and renders a status
3
+ * table for one section. Pass `kind="suites"` for the unit-test suites or
4
+ * `kind="examples"` for the example smoke runs.
5
+ *
6
+ * Used standalone on /status and inline in API/concept docs to surface
7
+ * "is this section's tests green right now?" with a deep link to logs.
8
+ */
9
+ export declare function StatusTable({ kind }: {
10
+ kind?: 'suites' | 'examples';
11
+ }): import("react").JSX.Element;
12
+ /**
13
+ * Inline single-suite status badge for embedding in API docs. Example:
14
+ * <TestStatus suite="lakeshore-controlplane" />
15
+ */
16
+ export declare function TestStatus({ suite, example }: {
17
+ suite?: string;
18
+ example?: string;
19
+ }): import("react").JSX.Element;
@@ -0,0 +1,251 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ const STATUS_COLOR = {
4
+ pass: "oklch(62% .15 145)",
5
+ fail: "oklch(58% .19 25)",
6
+ skip: "oklch(60% .02 250)",
7
+ pending: "oklch(70% .12 75)"
8
+ };
9
+ function StatusDot({ status }) {
10
+ return /* @__PURE__ */ jsx(
11
+ "span",
12
+ {
13
+ "aria-label": status,
14
+ title: status,
15
+ style: {
16
+ display: "inline-block",
17
+ width: 8,
18
+ height: 8,
19
+ borderRadius: "50%",
20
+ background: STATUS_COLOR[status] ?? "var(--color-doc-template-muted)",
21
+ marginRight: 8,
22
+ verticalAlign: "middle"
23
+ }
24
+ }
25
+ );
26
+ }
27
+ function StatusBadge({ status }) {
28
+ const color = STATUS_COLOR[status] ?? "var(--color-doc-template-muted)";
29
+ return /* @__PURE__ */ jsxs(
30
+ "span",
31
+ {
32
+ style: {
33
+ display: "inline-flex",
34
+ alignItems: "center",
35
+ gap: 6,
36
+ padding: "2px 8px",
37
+ borderRadius: 4,
38
+ background: `color-mix(in srgb, ${color} 12%, transparent)`,
39
+ color,
40
+ fontFamily: "var(--font-doc-template-mono)",
41
+ fontSize: 11,
42
+ fontWeight: 600,
43
+ textTransform: "uppercase",
44
+ letterSpacing: "0.08em"
45
+ },
46
+ children: [
47
+ /* @__PURE__ */ jsx(StatusDot, { status }),
48
+ status
49
+ ]
50
+ }
51
+ );
52
+ }
53
+ function fmtDuration(s) {
54
+ if (s == null) return "—";
55
+ if (s < 1) return `${Math.round(s * 1e3)}ms`;
56
+ if (s < 60) return `${s.toFixed(1)}s`;
57
+ return `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
58
+ }
59
+ function relativeTime(iso) {
60
+ const then = new Date(iso).getTime();
61
+ const now = Date.now();
62
+ const diff = Math.max(0, Math.round((now - then) / 1e3));
63
+ if (diff < 60) return `${diff}s ago`;
64
+ if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
65
+ if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
66
+ return `${Math.floor(diff / 86400)}d ago`;
67
+ }
68
+ const cellStyle = {
69
+ padding: "9px 10px",
70
+ verticalAlign: "top",
71
+ borderBottom: "1px solid var(--color-doc-template-faint)",
72
+ fontSize: 13
73
+ };
74
+ const monoStyle = {
75
+ fontFamily: "var(--font-doc-template-mono)",
76
+ fontSize: 12,
77
+ color: "var(--color-doc-template-muted)"
78
+ };
79
+ function StatusTable({ kind = "suites" }) {
80
+ const [data, setData] = useState(null);
81
+ const [error, setError] = useState(null);
82
+ useEffect(() => {
83
+ fetch("/test-results.json", { cache: "no-store" }).then((r) => {
84
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
85
+ return r.json();
86
+ }).then(setData).catch((e) => setError(String(e)));
87
+ }, []);
88
+ if (error) {
89
+ return /* @__PURE__ */ jsxs(
90
+ "div",
91
+ {
92
+ style: {
93
+ padding: 12,
94
+ border: "1px solid var(--color-doc-template-faint)",
95
+ borderRadius: 8,
96
+ color: "var(--color-doc-template-muted)",
97
+ fontSize: 13
98
+ },
99
+ children: [
100
+ "Could not load test results: ",
101
+ error
102
+ ]
103
+ }
104
+ );
105
+ }
106
+ if (!data) {
107
+ return /* @__PURE__ */ jsx("div", { style: { color: "var(--color-doc-template-muted)", fontSize: 13, padding: 12 }, children: "Loading test results…" });
108
+ }
109
+ const items = kind === "suites" ? data.suites : data.examples;
110
+ if (items.length === 0) {
111
+ return /* @__PURE__ */ jsxs("div", { style: { color: "var(--color-doc-template-muted)", fontSize: 13, padding: 12 }, children: [
112
+ "No ",
113
+ kind,
114
+ " reported yet. Run",
115
+ " ",
116
+ /* @__PURE__ */ jsx("code", { children: "uv run lakeshore-examples/test_runner.py" }),
117
+ " to populate."
118
+ ] });
119
+ }
120
+ return /* @__PURE__ */ jsxs("div", { children: [
121
+ /* @__PURE__ */ jsxs(
122
+ "div",
123
+ {
124
+ style: {
125
+ display: "flex",
126
+ justifyContent: "space-between",
127
+ alignItems: "baseline",
128
+ marginBottom: 8,
129
+ fontSize: 12,
130
+ color: "var(--color-doc-template-muted)"
131
+ },
132
+ children: [
133
+ /* @__PURE__ */ jsxs("span", { children: [
134
+ items.length,
135
+ " ",
136
+ kind,
137
+ data.status === "seed" && /* @__PURE__ */ jsx(
138
+ "span",
139
+ {
140
+ style: {
141
+ marginLeft: 8,
142
+ padding: "1px 6px",
143
+ background: "color-mix(in srgb, oklch(70% .12 75) 15%, transparent)",
144
+ color: "oklch(60% .14 75)",
145
+ borderRadius: 4,
146
+ fontFamily: "var(--font-doc-template-mono)"
147
+ },
148
+ title: data.note,
149
+ children: "seed data"
150
+ }
151
+ )
152
+ ] }),
153
+ /* @__PURE__ */ jsxs("span", { style: monoStyle, title: data.generated_at, children: [
154
+ "updated ",
155
+ relativeTime(data.generated_at)
156
+ ] })
157
+ ]
158
+ }
159
+ ),
160
+ /* @__PURE__ */ jsxs("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
161
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
162
+ /* @__PURE__ */ jsx("th", { style: { ...cellStyle, ...monoStyle, textAlign: "left", textTransform: "uppercase", letterSpacing: "0.12em", fontSize: 10 }, children: "Status" }),
163
+ /* @__PURE__ */ jsx("th", { style: { ...cellStyle, ...monoStyle, textAlign: "left", textTransform: "uppercase", letterSpacing: "0.12em", fontSize: 10 }, children: kind === "suites" ? "Suite" : "Example" }),
164
+ /* @__PURE__ */ jsx("th", { style: { ...cellStyle, ...monoStyle, textAlign: "left", textTransform: "uppercase", letterSpacing: "0.12em", fontSize: 10 }, children: kind === "suites" ? "Command" : "Description" }),
165
+ /* @__PURE__ */ jsx("th", { style: { ...cellStyle, ...monoStyle, textAlign: "right", textTransform: "uppercase", letterSpacing: "0.12em", fontSize: 10 }, children: "Tests" }),
166
+ /* @__PURE__ */ jsx("th", { style: { ...cellStyle, ...monoStyle, textAlign: "right", textTransform: "uppercase", letterSpacing: "0.12em", fontSize: 10 }, children: "Time" })
167
+ ] }) }),
168
+ /* @__PURE__ */ jsx("tbody", { children: kind === "suites" ? items.map((s) => /* @__PURE__ */ jsxs("tr", { children: [
169
+ /* @__PURE__ */ jsx("td", { style: cellStyle, children: /* @__PURE__ */ jsx(StatusBadge, { status: s.status }) }),
170
+ /* @__PURE__ */ jsxs("td", { style: cellStyle, children: [
171
+ s.doc_link ? /* @__PURE__ */ jsx(
172
+ "a",
173
+ {
174
+ href: s.doc_link,
175
+ className: "text-doc-template-accent",
176
+ style: {
177
+ borderBottom: "1px solid color-mix(in srgb, var(--color-doc-template-accent) 35%, transparent)",
178
+ textDecoration: "none"
179
+ },
180
+ children: s.name
181
+ }
182
+ ) : s.name,
183
+ /* @__PURE__ */ jsxs("div", { style: monoStyle, children: [
184
+ s.cwd,
185
+ "/"
186
+ ] })
187
+ ] }),
188
+ /* @__PURE__ */ jsxs("td", { style: { ...cellStyle, ...monoStyle }, children: [
189
+ s.command,
190
+ s.reason && /* @__PURE__ */ jsx("div", { style: { color: "var(--color-doc-template-muted)", marginTop: 2 }, children: s.reason })
191
+ ] }),
192
+ /* @__PURE__ */ jsx("td", { style: { ...cellStyle, textAlign: "right" }, children: s.tests ? /* @__PURE__ */ jsxs("span", { style: monoStyle, children: [
193
+ /* @__PURE__ */ jsx("span", { style: { color: STATUS_COLOR.pass }, children: s.tests.pass }),
194
+ s.tests.fail > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
195
+ " / ",
196
+ /* @__PURE__ */ jsx("span", { style: { color: STATUS_COLOR.fail }, children: s.tests.fail })
197
+ ] }),
198
+ s.tests.skip > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
199
+ " / ",
200
+ /* @__PURE__ */ jsx("span", { style: { color: STATUS_COLOR.skip }, children: s.tests.skip })
201
+ ] })
202
+ ] }) : /* @__PURE__ */ jsx("span", { style: monoStyle, children: "—" }) }),
203
+ /* @__PURE__ */ jsx("td", { style: { ...cellStyle, ...monoStyle, textAlign: "right" }, children: fmtDuration(s.duration_s) })
204
+ ] }, s.id)) : items.map((e) => /* @__PURE__ */ jsxs("tr", { children: [
205
+ /* @__PURE__ */ jsx("td", { style: cellStyle, children: /* @__PURE__ */ jsx(StatusBadge, { status: e.status }) }),
206
+ /* @__PURE__ */ jsx("td", { style: cellStyle, children: /* @__PURE__ */ jsx(
207
+ "a",
208
+ {
209
+ href: e.source_link,
210
+ target: "_blank",
211
+ rel: "noopener",
212
+ className: "text-doc-template-accent",
213
+ style: {
214
+ borderBottom: "1px solid color-mix(in srgb, var(--color-doc-template-accent) 35%, transparent)",
215
+ textDecoration: "none"
216
+ },
217
+ children: e.id
218
+ }
219
+ ) }),
220
+ /* @__PURE__ */ jsxs("td", { style: { ...cellStyle, fontSize: 13 }, children: [
221
+ e.description || e.title,
222
+ e.reason && /* @__PURE__ */ jsx("div", { style: { color: "var(--color-doc-template-muted)", marginTop: 2, fontSize: 12 }, children: e.reason })
223
+ ] }),
224
+ /* @__PURE__ */ jsx("td", { style: { ...cellStyle, ...monoStyle, textAlign: "right" }, children: e.needs_cp ? "needs CP" : "local" }),
225
+ /* @__PURE__ */ jsx("td", { style: { ...cellStyle, ...monoStyle, textAlign: "right" }, children: fmtDuration(e.duration_s) })
226
+ ] }, e.id)) })
227
+ ] })
228
+ ] });
229
+ }
230
+ function TestStatus({ suite, example }) {
231
+ const [data, setData] = useState(null);
232
+ useEffect(() => {
233
+ fetch("/test-results.json", { cache: "no-store" }).then((r) => r.json()).then(setData).catch(() => {
234
+ });
235
+ }, []);
236
+ if (!data) {
237
+ return /* @__PURE__ */ jsx("span", { style: monoStyle, children: "loading…" });
238
+ }
239
+ const item = suite ? data.suites.find((s) => s.id === suite) : example ? data.examples.find((e) => e.id === example) : null;
240
+ if (!item) {
241
+ return /* @__PURE__ */ jsx("span", { style: monoStyle, children: "unknown" });
242
+ }
243
+ return /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 8 }, children: [
244
+ /* @__PURE__ */ jsx(StatusBadge, { status: item.status }),
245
+ /* @__PURE__ */ jsx("span", { style: monoStyle, title: data.generated_at, children: relativeTime(data.generated_at) })
246
+ ] });
247
+ }
248
+ export {
249
+ StatusTable,
250
+ TestStatus
251
+ };
@@ -0,0 +1 @@
1
+ export declare function TOC(): import("react").JSX.Element | null;