@deckspec/renderer 0.1.0 → 0.1.2

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 (50) hide show
  1. package/dist/compile-tsx.d.ts +19 -0
  2. package/dist/compile-tsx.d.ts.map +1 -0
  3. package/dist/compile-tsx.js +101 -0
  4. package/dist/compile-tsx.js.map +1 -0
  5. package/dist/dashboard-css.d.ts +2 -0
  6. package/dist/dashboard-css.d.ts.map +1 -0
  7. package/dist/dashboard-css.js +419 -0
  8. package/dist/dashboard-css.js.map +1 -0
  9. package/dist/dashboard-js.d.ts +2 -0
  10. package/dist/dashboard-js.d.ts.map +1 -0
  11. package/dist/dashboard-js.js +15 -0
  12. package/dist/dashboard-js.js.map +1 -0
  13. package/dist/index.d.ts +8 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +8 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/render-dashboard.d.ts +35 -0
  18. package/dist/render-dashboard.d.ts.map +1 -0
  19. package/dist/render-dashboard.js +96 -0
  20. package/dist/render-dashboard.js.map +1 -0
  21. package/dist/render-deck.d.ts +17 -0
  22. package/dist/render-deck.d.ts.map +1 -0
  23. package/dist/render-deck.js +117 -0
  24. package/dist/render-deck.js.map +1 -0
  25. package/dist/render-slide.d.ts +15 -0
  26. package/dist/render-slide.d.ts.map +1 -0
  27. package/dist/render-slide.js +32 -0
  28. package/dist/render-slide.js.map +1 -0
  29. package/dist/render-theme-detail.d.ts +18 -0
  30. package/dist/render-theme-detail.d.ts.map +1 -0
  31. package/dist/render-theme-detail.js +104 -0
  32. package/dist/render-theme-detail.js.map +1 -0
  33. package/dist/resolve-assets.d.ts +10 -0
  34. package/dist/resolve-assets.d.ts.map +1 -0
  35. package/dist/resolve-assets.js +48 -0
  36. package/dist/resolve-assets.js.map +1 -0
  37. package/dist/theme.d.ts +63 -0
  38. package/dist/theme.d.ts.map +1 -0
  39. package/dist/theme.js +52 -0
  40. package/dist/theme.js.map +1 -0
  41. package/dist/viewer-css.d.ts +11 -0
  42. package/dist/viewer-css.d.ts.map +1 -0
  43. package/dist/viewer-css.js +281 -0
  44. package/dist/viewer-css.js.map +1 -0
  45. package/dist/viewer-js.d.ts +13 -0
  46. package/dist/viewer-js.d.ts.map +1 -0
  47. package/dist/viewer-js.js +233 -0
  48. package/dist/viewer-js.js.map +1 -0
  49. package/package.json +7 -3
  50. package/tsconfig.json +0 -14
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Compiles a .tsx file on-the-fly using esbuild and returns
3
+ * the path to the compiled ESM module that can be dynamically imported.
4
+ *
5
+ * Used for deck-local patterns that are authored as .tsx but need
6
+ * to be executable at runtime without a prior build step.
7
+ */
8
+ export declare function compileTsx(tsxPath: string): Promise<string>;
9
+ /**
10
+ * Compiles a .tsx file with caching. Returns the path to the compiled module.
11
+ * Call `clearCompileCache()` to invalidate (e.g. on file change).
12
+ */
13
+ export declare function compileTsxCached(tsxPath: string): Promise<string>;
14
+ /**
15
+ * Clears a specific entry or the entire compile cache.
16
+ * Also removes the temporary compiled files.
17
+ */
18
+ export declare function clearCompileCache(tsxPath?: string): Promise<void>;
19
+ //# sourceMappingURL=compile-tsx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-tsx.d.ts","sourceRoot":"","sources":["../src/compile-tsx.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiCjE;AAKD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOvE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BvE"}
@@ -0,0 +1,101 @@
1
+ import { build } from "esbuild";
2
+ import { mkdir, rm } from "node:fs/promises";
3
+ import { join, dirname } from "node:path";
4
+ import { createHash } from "node:crypto";
5
+ /**
6
+ * Returns a stable cache directory under the project root so that
7
+ * compiled modules can resolve node_modules (react, etc.) via
8
+ * standard Node resolution.
9
+ */
10
+ function cacheDir() {
11
+ return join(process.cwd(), ".deckspec-cache");
12
+ }
13
+ /**
14
+ * Compiles a .tsx file on-the-fly using esbuild and returns
15
+ * the path to the compiled ESM module that can be dynamically imported.
16
+ *
17
+ * Used for deck-local patterns that are authored as .tsx but need
18
+ * to be executable at runtime without a prior build step.
19
+ */
20
+ export async function compileTsx(tsxPath) {
21
+ // Use a hash of the source path for a stable, unique output name
22
+ const hash = createHash("md5").update(tsxPath).digest("hex").slice(0, 12);
23
+ const outDir = join(cacheDir(), hash);
24
+ await mkdir(outDir, { recursive: true });
25
+ const outFile = join(outDir, "index.mjs");
26
+ await build({
27
+ entryPoints: [tsxPath],
28
+ outfile: outFile,
29
+ bundle: true,
30
+ format: "esm",
31
+ platform: "node",
32
+ jsx: "automatic",
33
+ // Mark peer deps and heavy icon libraries as external —
34
+ // they're resolved from project node_modules
35
+ external: [
36
+ "react",
37
+ "react-dom",
38
+ "react/jsx-runtime",
39
+ "lucide-react",
40
+ "@phosphor-icons/react",
41
+ "recharts",
42
+ ],
43
+ // Allow resolving theme _lib and other deps from the source directory
44
+ nodePaths: [
45
+ join(process.cwd(), "node_modules"),
46
+ dirname(dirname(tsxPath)),
47
+ ],
48
+ logLevel: "warning",
49
+ });
50
+ return outFile;
51
+ }
52
+ /** Cache: source path → compiled module path */
53
+ const compiledCache = new Map();
54
+ /**
55
+ * Compiles a .tsx file with caching. Returns the path to the compiled module.
56
+ * Call `clearCompileCache()` to invalidate (e.g. on file change).
57
+ */
58
+ export async function compileTsxCached(tsxPath) {
59
+ const cached = compiledCache.get(tsxPath);
60
+ if (cached)
61
+ return cached;
62
+ const compiled = await compileTsx(tsxPath);
63
+ compiledCache.set(tsxPath, compiled);
64
+ return compiled;
65
+ }
66
+ /**
67
+ * Clears a specific entry or the entire compile cache.
68
+ * Also removes the temporary compiled files.
69
+ */
70
+ export async function clearCompileCache(tsxPath) {
71
+ if (tsxPath) {
72
+ const cached = compiledCache.get(tsxPath);
73
+ if (cached) {
74
+ compiledCache.delete(tsxPath);
75
+ try {
76
+ await rm(dirname(cached), { recursive: true, force: true });
77
+ }
78
+ catch {
79
+ // best-effort cleanup
80
+ }
81
+ }
82
+ }
83
+ else {
84
+ for (const compiled of compiledCache.values()) {
85
+ try {
86
+ await rm(dirname(compiled), { recursive: true, force: true });
87
+ }
88
+ catch {
89
+ // best-effort cleanup
90
+ }
91
+ }
92
+ compiledCache.clear();
93
+ try {
94
+ await rm(cacheDir(), { recursive: true, force: true });
95
+ }
96
+ catch {
97
+ // best-effort cleanup
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=compile-tsx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-tsx.js","sourceRoot":"","sources":["../src/compile-tsx.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const dashboardCSS = "\n/* ================================================================ */\n/* Reset */\n/* ================================================================ */\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n/* ================================================================ */\n/* Body */\n/* ================================================================ */\nbody {\n background: #fff;\n color: #1a1a1a;\n font-family: system-ui, -apple-system, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n min-height: 100vh;\n}\n\n/* ================================================================ */\n/* Layout */\n/* ================================================================ */\n.dashboard {\n max-width: 800px;\n margin: 0 auto;\n padding: 2.5rem 1.5rem;\n}\n\n/* ================================================================ */\n/* Navigation */\n/* ================================================================ */\n.page-nav {\n margin-bottom: 1rem;\n}\n\n.page-nav a {\n color: #737373;\n text-decoration: none;\n font-size: 0.85rem;\n}\n\n.page-nav a:hover {\n color: #1a1a1a;\n}\n\n/* ================================================================ */\n/* Page Title */\n/* ================================================================ */\n.page-title {\n font-size: 1.5rem;\n font-weight: 700;\n color: #1a1a1a;\n margin-bottom: 2rem;\n}\n\n/* ================================================================ */\n/* Sections */\n/* ================================================================ */\n.section {\n margin-bottom: 2.5rem;\n}\n\n.section-title {\n font-size: 0.85rem;\n font-weight: 600;\n color: #737373;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-bottom: 0.75rem;\n}\n\n/* ================================================================ */\n/* List Group (shared by themes & decks on Home) */\n/* ================================================================ */\n.list-group {\n border: 1px solid #e5e5e5;\n border-radius: 0.5rem;\n overflow: hidden;\n}\n\n.list-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.875rem 1rem;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.list-row:last-child {\n border-bottom: none;\n}\n\n.list-row-link {\n text-decoration: none;\n color: inherit;\n transition: background 0.1s;\n}\n\n.list-row-link:hover {\n background: #fafafa;\n}\n\n.list-row-left {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n min-width: 0;\n}\n\n.list-row-right {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n.list-row-text {\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n min-width: 0;\n}\n\n.list-row-name {\n font-size: 0.95rem;\n font-weight: 600;\n color: #1a1a1a;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.list-row-meta {\n font-size: 0.75rem;\n color: #a3a3a3;\n}\n\n.list-row-arrow {\n color: #d4d4d4;\n font-size: 1.2rem;\n flex-shrink: 0;\n}\n\n/* ================================================================ */\n/* Color Dots (Theme row on Home) */\n/* ================================================================ */\n.color-dots {\n display: flex;\n gap: 0;\n}\n\n.color-dot {\n width: 24px;\n height: 24px;\n border-radius: 50%;\n border: 2px solid #fff;\n box-shadow: 0 0 0 1px #e5e5e5;\n flex-shrink: 0;\n}\n\n.color-dot + .color-dot {\n margin-left: -6px;\n}\n\n/* ================================================================ */\n/* Deck Thumbnail (Deck row on Home) */\n/* ================================================================ */\n.deck-thumb {\n width: 64px;\n height: 36px;\n border-radius: 0.25rem;\n overflow: hidden;\n border: 1px solid #e5e5e5;\n flex-shrink: 0;\n background: var(--color-background, #f4f4f4);\n}\n\n.deck-thumb-inner {\n transform-origin: top left;\n transform: scale(calc(64 / 1200));\n width: 1200px;\n height: 675px;\n pointer-events: none;\n}\n\n.deck-thumb-inner .slide {\n width: 1200px;\n height: 675px;\n}\n\n.deck-thumb-empty {\n background: #f5f5f5;\n}\n\n/* ================================================================ */\n/* Approval Chip (Deck row) */\n/* ================================================================ */\n.approval-chip {\n font-size: 0.7rem;\n font-weight: 600;\n color: #737373;\n background: #f5f5f5;\n padding: 0.15rem 0.5rem;\n border-radius: 1rem;\n white-space: nowrap;\n}\n\n.approval-chip.approval-done {\n background: #dcfce7;\n color: #166534;\n}\n\n/* ================================================================ */\n/* Theme Description (Theme Detail page) */\n/* ================================================================ */\n.theme-description {\n font-size: 0.9rem;\n color: #525252;\n line-height: 1.7;\n margin-bottom: 2rem;\n white-space: pre-line;\n}\n\n/* ================================================================ */\n/* Color Grid (Theme Detail) */\n/* ================================================================ */\n.color-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n}\n\n.color-swatch {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n\n.color-swatch-circle {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: 1px solid #e5e5e5;\n flex-shrink: 0;\n}\n\n.color-swatch-info {\n display: flex;\n flex-direction: column;\n}\n\n.color-swatch-name {\n font-size: 0.8rem;\n font-weight: 600;\n color: #1a1a1a;\n}\n\n.color-swatch-hex {\n font-size: 0.7rem;\n color: #a3a3a3;\n font-family: ui-monospace, monospace;\n}\n\n/* ================================================================ */\n/* Typography Samples (Theme Detail) */\n/* ================================================================ */\n.typo-list {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.typo-row {\n display: flex;\n align-items: baseline;\n gap: 1rem;\n}\n\n.typo-label {\n font-size: 0.7rem;\n font-weight: 600;\n color: #737373;\n width: 2.5rem;\n flex-shrink: 0;\n font-family: ui-monospace, monospace;\n}\n\n.typo-meta {\n font-size: 0.7rem;\n color: #a3a3a3;\n width: 7rem;\n flex-shrink: 0;\n}\n\n.typo-sample {\n color: #1a1a1a;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ================================================================ */\n/* Spacing Bars (Theme Detail) */\n/* ================================================================ */\n.spacing-list {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.spacing-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.spacing-bar {\n height: 8px;\n background: #e5e5e5;\n border-radius: 2px;\n}\n\n.spacing-label {\n font-size: 0.7rem;\n color: #a3a3a3;\n font-family: ui-monospace, monospace;\n}\n\n/* ================================================================ */\n/* Pattern Grid (Theme Detail) */\n/* ================================================================ */\n.pattern-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 0.75rem;\n}\n\n.pattern-card {\n border: 1px solid #e5e5e5;\n border-radius: 0.375rem;\n overflow: hidden;\n background: #fff;\n}\n\n.pattern-thumb {\n aspect-ratio: 16 / 9;\n overflow: hidden;\n background: var(--color-background, #f4f4f4);\n position: relative;\n}\n\n.pattern-thumb-inner {\n transform-origin: top left;\n --thumb-scale: 0.155;\n transform: scale(var(--thumb-scale));\n width: 1200px;\n height: 675px;\n pointer-events: none;\n}\n\n.pattern-thumb-inner .slide,\n.pattern-thumb-inner .slide-pad,\n.pattern-thumb-inner .slide-stack,\n.pattern-thumb-inner .slide-center,\n.pattern-thumb-inner .slide-white {\n width: 1200px;\n height: 675px;\n}\n\n.pattern-thumb-empty {\n background: #f5f5f5;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.pattern-thumb-empty::after {\n content: \"\";\n width: 24px;\n height: 24px;\n border: 2px dashed #d4d4d4;\n border-radius: 0.25rem;\n}\n\n.pattern-card-name {\n display: block;\n padding: 0.375rem 0.5rem;\n font-size: 0.7rem;\n color: #525252;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ================================================================ */\n/* Count Badge */\n/* ================================================================ */\n.count-badge {\n font-size: 0.7rem;\n font-weight: 600;\n color: #a3a3a3;\n background: #f5f5f5;\n padding: 0.1rem 0.4rem;\n border-radius: 1rem;\n margin-left: 0.375rem;\n text-transform: none;\n letter-spacing: 0;\n}\n\n/* ================================================================ */\n/* Empty State */\n/* ================================================================ */\n.empty-state {\n text-align: center;\n padding: 2rem 1rem;\n color: #a3a3a3;\n font-size: 0.85rem;\n}\n";
2
+ //# sourceMappingURL=dashboard-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-css.d.ts","sourceRoot":"","sources":["../src/dashboard-css.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,mhTAiaxB,CAAC"}
@@ -0,0 +1,419 @@
1
+ export const dashboardCSS = /* css */ `
2
+ /* ================================================================ */
3
+ /* Reset */
4
+ /* ================================================================ */
5
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
6
+
7
+ /* ================================================================ */
8
+ /* Body */
9
+ /* ================================================================ */
10
+ body {
11
+ background: #fff;
12
+ color: #1a1a1a;
13
+ font-family: system-ui, -apple-system, sans-serif;
14
+ -webkit-font-smoothing: antialiased;
15
+ -moz-osx-font-smoothing: grayscale;
16
+ min-height: 100vh;
17
+ }
18
+
19
+ /* ================================================================ */
20
+ /* Layout */
21
+ /* ================================================================ */
22
+ .dashboard {
23
+ max-width: 800px;
24
+ margin: 0 auto;
25
+ padding: 2.5rem 1.5rem;
26
+ }
27
+
28
+ /* ================================================================ */
29
+ /* Navigation */
30
+ /* ================================================================ */
31
+ .page-nav {
32
+ margin-bottom: 1rem;
33
+ }
34
+
35
+ .page-nav a {
36
+ color: #737373;
37
+ text-decoration: none;
38
+ font-size: 0.85rem;
39
+ }
40
+
41
+ .page-nav a:hover {
42
+ color: #1a1a1a;
43
+ }
44
+
45
+ /* ================================================================ */
46
+ /* Page Title */
47
+ /* ================================================================ */
48
+ .page-title {
49
+ font-size: 1.5rem;
50
+ font-weight: 700;
51
+ color: #1a1a1a;
52
+ margin-bottom: 2rem;
53
+ }
54
+
55
+ /* ================================================================ */
56
+ /* Sections */
57
+ /* ================================================================ */
58
+ .section {
59
+ margin-bottom: 2.5rem;
60
+ }
61
+
62
+ .section-title {
63
+ font-size: 0.85rem;
64
+ font-weight: 600;
65
+ color: #737373;
66
+ text-transform: uppercase;
67
+ letter-spacing: 0.05em;
68
+ margin-bottom: 0.75rem;
69
+ }
70
+
71
+ /* ================================================================ */
72
+ /* List Group (shared by themes & decks on Home) */
73
+ /* ================================================================ */
74
+ .list-group {
75
+ border: 1px solid #e5e5e5;
76
+ border-radius: 0.5rem;
77
+ overflow: hidden;
78
+ }
79
+
80
+ .list-row {
81
+ display: flex;
82
+ align-items: center;
83
+ justify-content: space-between;
84
+ padding: 0.875rem 1rem;
85
+ border-bottom: 1px solid #f0f0f0;
86
+ }
87
+
88
+ .list-row:last-child {
89
+ border-bottom: none;
90
+ }
91
+
92
+ .list-row-link {
93
+ text-decoration: none;
94
+ color: inherit;
95
+ transition: background 0.1s;
96
+ }
97
+
98
+ .list-row-link:hover {
99
+ background: #fafafa;
100
+ }
101
+
102
+ .list-row-left {
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 0.75rem;
106
+ min-width: 0;
107
+ }
108
+
109
+ .list-row-right {
110
+ display: flex;
111
+ align-items: center;
112
+ gap: 0.5rem;
113
+ flex-shrink: 0;
114
+ }
115
+
116
+ .list-row-text {
117
+ display: flex;
118
+ flex-direction: column;
119
+ gap: 0.125rem;
120
+ min-width: 0;
121
+ }
122
+
123
+ .list-row-name {
124
+ font-size: 0.95rem;
125
+ font-weight: 600;
126
+ color: #1a1a1a;
127
+ white-space: nowrap;
128
+ overflow: hidden;
129
+ text-overflow: ellipsis;
130
+ }
131
+
132
+ .list-row-meta {
133
+ font-size: 0.75rem;
134
+ color: #a3a3a3;
135
+ }
136
+
137
+ .list-row-arrow {
138
+ color: #d4d4d4;
139
+ font-size: 1.2rem;
140
+ flex-shrink: 0;
141
+ }
142
+
143
+ /* ================================================================ */
144
+ /* Color Dots (Theme row on Home) */
145
+ /* ================================================================ */
146
+ .color-dots {
147
+ display: flex;
148
+ gap: 0;
149
+ }
150
+
151
+ .color-dot {
152
+ width: 24px;
153
+ height: 24px;
154
+ border-radius: 50%;
155
+ border: 2px solid #fff;
156
+ box-shadow: 0 0 0 1px #e5e5e5;
157
+ flex-shrink: 0;
158
+ }
159
+
160
+ .color-dot + .color-dot {
161
+ margin-left: -6px;
162
+ }
163
+
164
+ /* ================================================================ */
165
+ /* Deck Thumbnail (Deck row on Home) */
166
+ /* ================================================================ */
167
+ .deck-thumb {
168
+ width: 64px;
169
+ height: 36px;
170
+ border-radius: 0.25rem;
171
+ overflow: hidden;
172
+ border: 1px solid #e5e5e5;
173
+ flex-shrink: 0;
174
+ background: var(--color-background, #f4f4f4);
175
+ }
176
+
177
+ .deck-thumb-inner {
178
+ transform-origin: top left;
179
+ transform: scale(calc(64 / 1200));
180
+ width: 1200px;
181
+ height: 675px;
182
+ pointer-events: none;
183
+ }
184
+
185
+ .deck-thumb-inner .slide {
186
+ width: 1200px;
187
+ height: 675px;
188
+ }
189
+
190
+ .deck-thumb-empty {
191
+ background: #f5f5f5;
192
+ }
193
+
194
+ /* ================================================================ */
195
+ /* Approval Chip (Deck row) */
196
+ /* ================================================================ */
197
+ .approval-chip {
198
+ font-size: 0.7rem;
199
+ font-weight: 600;
200
+ color: #737373;
201
+ background: #f5f5f5;
202
+ padding: 0.15rem 0.5rem;
203
+ border-radius: 1rem;
204
+ white-space: nowrap;
205
+ }
206
+
207
+ .approval-chip.approval-done {
208
+ background: #dcfce7;
209
+ color: #166534;
210
+ }
211
+
212
+ /* ================================================================ */
213
+ /* Theme Description (Theme Detail page) */
214
+ /* ================================================================ */
215
+ .theme-description {
216
+ font-size: 0.9rem;
217
+ color: #525252;
218
+ line-height: 1.7;
219
+ margin-bottom: 2rem;
220
+ white-space: pre-line;
221
+ }
222
+
223
+ /* ================================================================ */
224
+ /* Color Grid (Theme Detail) */
225
+ /* ================================================================ */
226
+ .color-grid {
227
+ display: flex;
228
+ flex-wrap: wrap;
229
+ gap: 1rem;
230
+ }
231
+
232
+ .color-swatch {
233
+ display: flex;
234
+ align-items: center;
235
+ gap: 0.625rem;
236
+ }
237
+
238
+ .color-swatch-circle {
239
+ width: 40px;
240
+ height: 40px;
241
+ border-radius: 50%;
242
+ border: 1px solid #e5e5e5;
243
+ flex-shrink: 0;
244
+ }
245
+
246
+ .color-swatch-info {
247
+ display: flex;
248
+ flex-direction: column;
249
+ }
250
+
251
+ .color-swatch-name {
252
+ font-size: 0.8rem;
253
+ font-weight: 600;
254
+ color: #1a1a1a;
255
+ }
256
+
257
+ .color-swatch-hex {
258
+ font-size: 0.7rem;
259
+ color: #a3a3a3;
260
+ font-family: ui-monospace, monospace;
261
+ }
262
+
263
+ /* ================================================================ */
264
+ /* Typography Samples (Theme Detail) */
265
+ /* ================================================================ */
266
+ .typo-list {
267
+ display: flex;
268
+ flex-direction: column;
269
+ gap: 0.75rem;
270
+ }
271
+
272
+ .typo-row {
273
+ display: flex;
274
+ align-items: baseline;
275
+ gap: 1rem;
276
+ }
277
+
278
+ .typo-label {
279
+ font-size: 0.7rem;
280
+ font-weight: 600;
281
+ color: #737373;
282
+ width: 2.5rem;
283
+ flex-shrink: 0;
284
+ font-family: ui-monospace, monospace;
285
+ }
286
+
287
+ .typo-meta {
288
+ font-size: 0.7rem;
289
+ color: #a3a3a3;
290
+ width: 7rem;
291
+ flex-shrink: 0;
292
+ }
293
+
294
+ .typo-sample {
295
+ color: #1a1a1a;
296
+ white-space: nowrap;
297
+ overflow: hidden;
298
+ text-overflow: ellipsis;
299
+ }
300
+
301
+ /* ================================================================ */
302
+ /* Spacing Bars (Theme Detail) */
303
+ /* ================================================================ */
304
+ .spacing-list {
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: 0.5rem;
308
+ }
309
+
310
+ .spacing-item {
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 0.75rem;
314
+ }
315
+
316
+ .spacing-bar {
317
+ height: 8px;
318
+ background: #e5e5e5;
319
+ border-radius: 2px;
320
+ }
321
+
322
+ .spacing-label {
323
+ font-size: 0.7rem;
324
+ color: #a3a3a3;
325
+ font-family: ui-monospace, monospace;
326
+ }
327
+
328
+ /* ================================================================ */
329
+ /* Pattern Grid (Theme Detail) */
330
+ /* ================================================================ */
331
+ .pattern-grid {
332
+ display: grid;
333
+ grid-template-columns: repeat(4, 1fr);
334
+ gap: 0.75rem;
335
+ }
336
+
337
+ .pattern-card {
338
+ border: 1px solid #e5e5e5;
339
+ border-radius: 0.375rem;
340
+ overflow: hidden;
341
+ background: #fff;
342
+ }
343
+
344
+ .pattern-thumb {
345
+ aspect-ratio: 16 / 9;
346
+ overflow: hidden;
347
+ background: var(--color-background, #f4f4f4);
348
+ position: relative;
349
+ }
350
+
351
+ .pattern-thumb-inner {
352
+ transform-origin: top left;
353
+ --thumb-scale: 0.155;
354
+ transform: scale(var(--thumb-scale));
355
+ width: 1200px;
356
+ height: 675px;
357
+ pointer-events: none;
358
+ }
359
+
360
+ .pattern-thumb-inner .slide,
361
+ .pattern-thumb-inner .slide-pad,
362
+ .pattern-thumb-inner .slide-stack,
363
+ .pattern-thumb-inner .slide-center,
364
+ .pattern-thumb-inner .slide-white {
365
+ width: 1200px;
366
+ height: 675px;
367
+ }
368
+
369
+ .pattern-thumb-empty {
370
+ background: #f5f5f5;
371
+ display: flex;
372
+ align-items: center;
373
+ justify-content: center;
374
+ }
375
+
376
+ .pattern-thumb-empty::after {
377
+ content: "";
378
+ width: 24px;
379
+ height: 24px;
380
+ border: 2px dashed #d4d4d4;
381
+ border-radius: 0.25rem;
382
+ }
383
+
384
+ .pattern-card-name {
385
+ display: block;
386
+ padding: 0.375rem 0.5rem;
387
+ font-size: 0.7rem;
388
+ color: #525252;
389
+ white-space: nowrap;
390
+ overflow: hidden;
391
+ text-overflow: ellipsis;
392
+ }
393
+
394
+ /* ================================================================ */
395
+ /* Count Badge */
396
+ /* ================================================================ */
397
+ .count-badge {
398
+ font-size: 0.7rem;
399
+ font-weight: 600;
400
+ color: #a3a3a3;
401
+ background: #f5f5f5;
402
+ padding: 0.1rem 0.4rem;
403
+ border-radius: 1rem;
404
+ margin-left: 0.375rem;
405
+ text-transform: none;
406
+ letter-spacing: 0;
407
+ }
408
+
409
+ /* ================================================================ */
410
+ /* Empty State */
411
+ /* ================================================================ */
412
+ .empty-state {
413
+ text-align: center;
414
+ padding: 2rem 1rem;
415
+ color: #a3a3a3;
416
+ font-size: 0.85rem;
417
+ }
418
+ `;
419
+ //# sourceMappingURL=dashboard-css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-css.js","sourceRoot":"","sources":["../src/dashboard-css.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiarC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const dashboardJS = "\n(function() {\n /* -- SSE live reload --------------------------------------------- */\n if (typeof EventSource !== 'undefined') {\n var es = new EventSource('/events');\n es.addEventListener('reload', function() {\n location.reload();\n });\n es.onerror = function() {\n // Reconnect handled automatically by EventSource\n };\n }\n})();\n";
2
+ //# sourceMappingURL=dashboard-js.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-js.d.ts","sourceRoot":"","sources":["../src/dashboard-js.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,sXAavB,CAAC"}
@@ -0,0 +1,15 @@
1
+ export const dashboardJS = /* js */ `
2
+ (function() {
3
+ /* -- SSE live reload --------------------------------------------- */
4
+ if (typeof EventSource !== 'undefined') {
5
+ var es = new EventSource('/events');
6
+ es.addEventListener('reload', function() {
7
+ location.reload();
8
+ });
9
+ es.onerror = function() {
10
+ // Reconnect handled automatically by EventSource
11
+ };
12
+ }
13
+ })();
14
+ `;
15
+ //# sourceMappingURL=dashboard-js.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-js.js","sourceRoot":"","sources":["../src/dashboard-js.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;;;;;;;;;;;;;CAanC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { loadThemeTokens, loadThemeCSS, resolveThemePatternsDir, resolveThemePatternsSrcDir, extractThemeName, type ThemeTokens, } from "./theme.js";
2
+ export { renderSlide, type RenderSlideContext } from "./render-slide.js";
3
+ export { resolveAssets, sanitizeSvg, type AssetFieldSpec, } from "./resolve-assets.js";
4
+ export { renderDeck } from "./render-deck.js";
5
+ export { renderDashboard, type DeckWithPreviews, type SlidePreview, type ThemeSummary, } from "./render-dashboard.js";
6
+ export { renderThemeDetail } from "./render-theme-detail.js";
7
+ export { compileTsx, compileTsxCached, clearCompileCache, } from "./compile-tsx.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,uBAAuB,EACvB,0BAA0B,EAC1B,gBAAgB,EAChB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,aAAa,EACb,WAAW,EACX,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { loadThemeTokens, loadThemeCSS, resolveThemePatternsDir, resolveThemePatternsSrcDir, extractThemeName, } from "./theme.js";
2
+ export { renderSlide } from "./render-slide.js";
3
+ export { resolveAssets, sanitizeSvg, } from "./resolve-assets.js";
4
+ export { renderDeck } from "./render-deck.js";
5
+ export { renderDashboard, } from "./render-dashboard.js";
6
+ export { renderThemeDetail } from "./render-theme-detail.js";
7
+ export { compileTsx, compileTsxCached, clearCompileCache, } from "./compile-tsx.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,uBAAuB,EACvB,0BAA0B,EAC1B,gBAAgB,GAEjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EACL,aAAa,EACb,WAAW,GAEZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,eAAe,GAIhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { DeckSummary } from "@deckspec/dsl";
2
+ export interface SlidePreview {
3
+ index: number;
4
+ state: string;
5
+ html: string;
6
+ file?: string;
7
+ }
8
+ export interface DeckWithPreviews {
9
+ summary: DeckSummary;
10
+ slidePreviews: SlidePreview[];
11
+ /** Last modified date of deck.yaml (ISO string or undefined) */
12
+ mtime?: string;
13
+ }
14
+ export interface ThemeSummary {
15
+ name: string;
16
+ displayName: string;
17
+ patternCount: number;
18
+ /** Key colors for visual identification (3-4 swatches) */
19
+ colors: {
20
+ name: string;
21
+ hex: string;
22
+ }[];
23
+ }
24
+ interface DashboardOptions {
25
+ /** "interactive" enables approve/reject buttons (dev server mode) */
26
+ mode: "static" | "interactive";
27
+ /** Theme CSS to embed for slide previews */
28
+ themeCSS?: string;
29
+ }
30
+ /**
31
+ * Renders the dashboard as a standalone HTML page.
32
+ */
33
+ export declare function renderDashboard(decks: DeckWithPreviews[], options?: DashboardOptions, themes?: ThemeSummary[]): string;
34
+ export {};
35
+ //# sourceMappingURL=render-dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-dashboard.d.ts","sourceRoot":"","sources":["../src/render-dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzC;AAED,UAAU,gBAAgB;IACxB,qEAAqE;IACrE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC;IAC/B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAgED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,gBAAgB,EAAE,EACzB,OAAO,GAAE,gBAAqC,EAC9C,MAAM,GAAE,YAAY,EAAO,GAC1B,MAAM,CAyCR"}