@sanity-labs/slides 0.0.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.
Files changed (224) hide show
  1. package/README.md +241 -0
  2. package/SKILL.md +119 -0
  3. package/dist/cli.d.ts +38 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +386 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/components.d.ts +179 -0
  8. package/dist/core/components.d.ts.map +1 -0
  9. package/dist/core/components.js +40 -0
  10. package/dist/core/components.js.map +1 -0
  11. package/dist/core/fake-runtime.d.ts +138 -0
  12. package/dist/core/fake-runtime.d.ts.map +1 -0
  13. package/dist/core/fake-runtime.js +210 -0
  14. package/dist/core/fake-runtime.js.map +1 -0
  15. package/dist/core/font-resolver.d.ts +28 -0
  16. package/dist/core/font-resolver.d.ts.map +1 -0
  17. package/dist/core/font-resolver.js +30 -0
  18. package/dist/core/font-resolver.js.map +1 -0
  19. package/dist/core/geometry.d.ts +71 -0
  20. package/dist/core/geometry.d.ts.map +1 -0
  21. package/dist/core/geometry.js +44 -0
  22. package/dist/core/geometry.js.map +1 -0
  23. package/dist/core/index.d.ts +19 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +20 -0
  26. package/dist/core/index.js.map +1 -0
  27. package/dist/core/manifest.d.ts +123 -0
  28. package/dist/core/manifest.d.ts.map +1 -0
  29. package/dist/core/manifest.js +43 -0
  30. package/dist/core/manifest.js.map +1 -0
  31. package/dist/core/op-translator-pptx.d.ts +150 -0
  32. package/dist/core/op-translator-pptx.d.ts.map +1 -0
  33. package/dist/core/op-translator-pptx.js +245 -0
  34. package/dist/core/op-translator-pptx.js.map +1 -0
  35. package/dist/core/pptx-runtime.d.ts +103 -0
  36. package/dist/core/pptx-runtime.d.ts.map +1 -0
  37. package/dist/core/pptx-runtime.js +405 -0
  38. package/dist/core/pptx-runtime.js.map +1 -0
  39. package/dist/core/reconciler.d.ts +113 -0
  40. package/dist/core/reconciler.d.ts.map +1 -0
  41. package/dist/core/reconciler.js +453 -0
  42. package/dist/core/reconciler.js.map +1 -0
  43. package/dist/core/runtime.d.ts +161 -0
  44. package/dist/core/runtime.d.ts.map +1 -0
  45. package/dist/core/runtime.js +11 -0
  46. package/dist/core/runtime.js.map +1 -0
  47. package/dist/core/template.d.ts +32 -0
  48. package/dist/core/template.d.ts.map +1 -0
  49. package/dist/core/template.js +3 -0
  50. package/dist/core/template.js.map +1 -0
  51. package/dist/dev/auto-examples.d.ts +6 -0
  52. package/dist/dev/auto-examples.d.ts.map +1 -0
  53. package/dist/dev/auto-examples.js +79 -0
  54. package/dist/dev/auto-examples.js.map +1 -0
  55. package/dist/dev/bin/slides-dev.d.ts +3 -0
  56. package/dist/dev/bin/slides-dev.d.ts.map +1 -0
  57. package/dist/dev/bin/slides-dev.js +87 -0
  58. package/dist/dev/bin/slides-dev.js.map +1 -0
  59. package/dist/dev/bin/slides-dev.mjs +24 -0
  60. package/dist/dev/compose-deck.d.ts +18 -0
  61. package/dist/dev/compose-deck.d.ts.map +1 -0
  62. package/dist/dev/compose-deck.js +19 -0
  63. package/dist/dev/compose-deck.js.map +1 -0
  64. package/dist/dev/deck-viewer.d.ts +19 -0
  65. package/dist/dev/deck-viewer.d.ts.map +1 -0
  66. package/dist/dev/deck-viewer.js +237 -0
  67. package/dist/dev/deck-viewer.js.map +1 -0
  68. package/dist/dev/dev-server/client/entry.d.ts +2 -0
  69. package/dist/dev/dev-server/client/entry.d.ts.map +1 -0
  70. package/dist/dev/dev-server/client/entry.js +12 -0
  71. package/dist/dev/dev-server/client/entry.js.map +1 -0
  72. package/dist/dev/dev-server/output.d.ts +8 -0
  73. package/dist/dev/dev-server/output.d.ts.map +1 -0
  74. package/dist/dev/dev-server/output.js +32 -0
  75. package/dist/dev/dev-server/output.js.map +1 -0
  76. package/dist/dev/dev-server/server-only-stub.d.ts +7 -0
  77. package/dist/dev/dev-server/server-only-stub.d.ts.map +1 -0
  78. package/dist/dev/dev-server/server-only-stub.js +12 -0
  79. package/dist/dev/dev-server/server-only-stub.js.map +1 -0
  80. package/dist/dev/dev-server/start.d.ts +14 -0
  81. package/dist/dev/dev-server/start.d.ts.map +1 -0
  82. package/dist/dev/dev-server/start.js +135 -0
  83. package/dist/dev/dev-server/start.js.map +1 -0
  84. package/dist/dev/index.d.ts +5 -0
  85. package/dist/dev/index.d.ts.map +1 -0
  86. package/dist/dev/index.js +5 -0
  87. package/dist/dev/index.js.map +1 -0
  88. package/dist/dev/lib/cn.d.ts +3 -0
  89. package/dist/dev/lib/cn.d.ts.map +1 -0
  90. package/dist/dev/lib/cn.js +3 -0
  91. package/dist/dev/lib/cn.js.map +1 -0
  92. package/dist/dev/slide-canvas.d.ts +12 -0
  93. package/dist/dev/slide-canvas.d.ts.map +1 -0
  94. package/dist/dev/slide-canvas.js +123 -0
  95. package/dist/dev/slide-canvas.js.map +1 -0
  96. package/dist/dev/styles.css +37 -0
  97. package/dist/dev/ui/icon-button.d.ts +12 -0
  98. package/dist/dev/ui/icon-button.d.ts.map +1 -0
  99. package/dist/dev/ui/icon-button.js +6 -0
  100. package/dist/dev/ui/icon-button.js.map +1 -0
  101. package/dist/dev/ui/kbd.d.ts +6 -0
  102. package/dist/dev/ui/kbd.d.ts.map +1 -0
  103. package/dist/dev/ui/kbd.js +4 -0
  104. package/dist/dev/ui/kbd.js.map +1 -0
  105. package/dist/dev/ui/text-button.d.ts +10 -0
  106. package/dist/dev/ui/text-button.d.ts.map +1 -0
  107. package/dist/dev/ui/text-button.js +6 -0
  108. package/dist/dev/ui/text-button.js.map +1 -0
  109. package/dist/dev/url-state.d.ts +7 -0
  110. package/dist/dev/url-state.d.ts.map +1 -0
  111. package/dist/dev/url-state.js +13 -0
  112. package/dist/dev/url-state.js.map +1 -0
  113. package/dist/dev/use-keyboard-nav.d.ts +17 -0
  114. package/dist/dev/use-keyboard-nav.d.ts.map +1 -0
  115. package/dist/dev/use-keyboard-nav.js +53 -0
  116. package/dist/dev/use-keyboard-nav.js.map +1 -0
  117. package/dist/index.d.ts +17 -0
  118. package/dist/index.d.ts.map +1 -0
  119. package/dist/index.js +17 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/mcp/errors.d.ts +57 -0
  122. package/dist/mcp/errors.d.ts.map +1 -0
  123. package/dist/mcp/errors.js +44 -0
  124. package/dist/mcp/errors.js.map +1 -0
  125. package/dist/mcp/index.d.ts +29 -0
  126. package/dist/mcp/index.d.ts.map +1 -0
  127. package/dist/mcp/index.js +29 -0
  128. package/dist/mcp/index.js.map +1 -0
  129. package/dist/mcp/naming.d.ts +37 -0
  130. package/dist/mcp/naming.d.ts.map +1 -0
  131. package/dist/mcp/naming.js +43 -0
  132. package/dist/mcp/naming.js.map +1 -0
  133. package/dist/mcp/render.d.ts +45 -0
  134. package/dist/mcp/render.d.ts.map +1 -0
  135. package/dist/mcp/render.js +77 -0
  136. package/dist/mcp/render.js.map +1 -0
  137. package/dist/mcp/schema.d.ts +54 -0
  138. package/dist/mcp/schema.d.ts.map +1 -0
  139. package/dist/mcp/schema.js +55 -0
  140. package/dist/mcp/schema.js.map +1 -0
  141. package/dist/mcp/server.d.ts +63 -0
  142. package/dist/mcp/server.d.ts.map +1 -0
  143. package/dist/mcp/server.js +196 -0
  144. package/dist/mcp/server.js.map +1 -0
  145. package/dist/scaffold/index.d.ts +39 -0
  146. package/dist/scaffold/index.d.ts.map +1 -0
  147. package/dist/scaffold/index.js +84 -0
  148. package/dist/scaffold/index.js.map +1 -0
  149. package/dist/scaffold/template-base/README.md +134 -0
  150. package/dist/scaffold/template-base/_gitignore +4 -0
  151. package/dist/scaffold/template-base/package.json +35 -0
  152. package/dist/scaffold/template-base/src/components/Cover.tsx +30 -0
  153. package/dist/scaffold/template-base/src/index.ts +27 -0
  154. package/dist/scaffold/template-base/src/preview.tsx +9 -0
  155. package/dist/scaffold/template-base/tsconfig.build.json +10 -0
  156. package/dist/scaffold/template-base/tsconfig.json +18 -0
  157. package/package.json +164 -0
  158. package/src/__tests__/fixtures/test-template/index.tsx +77 -0
  159. package/src/__tests__/pptx-mcp.test.ts +85 -0
  160. package/src/__tests__/pptx-smoke.test.ts +45 -0
  161. package/src/__tests__/preview.test.ts +28 -0
  162. package/src/cli.ts +426 -0
  163. package/src/core/__snapshots__/reconciler.test.ts.snap +320 -0
  164. package/src/core/components.test.ts +57 -0
  165. package/src/core/components.ts +196 -0
  166. package/src/core/fake-runtime.test.ts +174 -0
  167. package/src/core/fake-runtime.ts +302 -0
  168. package/src/core/font-resolver.ts +46 -0
  169. package/src/core/geometry.test.ts +58 -0
  170. package/src/core/geometry.ts +91 -0
  171. package/src/core/index.ts +69 -0
  172. package/src/core/manifest.test.ts +33 -0
  173. package/src/core/manifest.ts +150 -0
  174. package/src/core/op-translator-pptx.test.ts +204 -0
  175. package/src/core/op-translator-pptx.ts +365 -0
  176. package/src/core/pptx-runtime.test.ts +137 -0
  177. package/src/core/pptx-runtime.ts +504 -0
  178. package/src/core/reconciler.test.ts +644 -0
  179. package/src/core/reconciler.ts +603 -0
  180. package/src/core/runtime.ts +150 -0
  181. package/src/core/template.test.ts +136 -0
  182. package/src/core/template.ts +37 -0
  183. package/src/dev/auto-examples.ts +89 -0
  184. package/src/dev/bin/slides-dev.mjs +24 -0
  185. package/src/dev/bin/slides-dev.ts +101 -0
  186. package/src/dev/compose-deck.test.ts +68 -0
  187. package/src/dev/compose-deck.ts +40 -0
  188. package/src/dev/deck-viewer.tsx +677 -0
  189. package/src/dev/dev-server/client/entry.tsx +15 -0
  190. package/src/dev/dev-server/client/index.html +24 -0
  191. package/src/dev/dev-server/output.ts +37 -0
  192. package/src/dev/dev-server/server-only-stub.ts +12 -0
  193. package/src/dev/dev-server/start.ts +155 -0
  194. package/src/dev/index.ts +4 -0
  195. package/src/dev/lib/cn.ts +3 -0
  196. package/src/dev/slide-canvas.test.tsx +66 -0
  197. package/src/dev/slide-canvas.tsx +170 -0
  198. package/src/dev/styles.css +37 -0
  199. package/src/dev/ui/icon-button.tsx +31 -0
  200. package/src/dev/ui/kbd.tsx +20 -0
  201. package/src/dev/ui/text-button.tsx +31 -0
  202. package/src/dev/url-state.test.ts +22 -0
  203. package/src/dev/url-state.ts +17 -0
  204. package/src/dev/use-keyboard-nav.ts +64 -0
  205. package/src/index.ts +17 -0
  206. package/src/mcp/errors.test.ts +51 -0
  207. package/src/mcp/errors.ts +76 -0
  208. package/src/mcp/index.ts +45 -0
  209. package/src/mcp/naming.test.ts +39 -0
  210. package/src/mcp/naming.ts +49 -0
  211. package/src/mcp/render.ts +110 -0
  212. package/src/mcp/schema.test.ts +86 -0
  213. package/src/mcp/schema.ts +93 -0
  214. package/src/mcp/server.test.ts +309 -0
  215. package/src/mcp/server.ts +276 -0
  216. package/src/scaffold/index.ts +102 -0
  217. package/src/scaffold/template-base/README.md +134 -0
  218. package/src/scaffold/template-base/_gitignore +4 -0
  219. package/src/scaffold/template-base/package.json +35 -0
  220. package/src/scaffold/template-base/src/components/Cover.tsx +30 -0
  221. package/src/scaffold/template-base/src/index.ts +27 -0
  222. package/src/scaffold/template-base/src/preview.tsx +9 -0
  223. package/src/scaffold/template-base/tsconfig.build.json +10 -0
  224. package/src/scaffold/template-base/tsconfig.json +18 -0
package/dist/cli.js ADDED
@@ -0,0 +1,386 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `slidesctl` — the CLI bin shipped with `@sanity-labs/slides`.
4
+ *
5
+ * Subcommands:
6
+ *
7
+ * serve --template <path-or-specifier> [--output <dir>] [--name <id>]
8
+ * Start an MCP server over stdio. Exposes `slides_list`,
9
+ * `slides_add_<type>`, and `slides_create` derived from the
10
+ * loaded template.
11
+ *
12
+ * generate --template <path-or-specifier> [--output <dir>]
13
+ * Read `{ title, slides: [...] }` JSON from stdin and write
14
+ * the resulting `.pptx`. Prints the absolute path on stdout.
15
+ *
16
+ * list --template <path-or-specifier>
17
+ * Print every slide type the template exposes, with
18
+ * descriptions. Useful for humans inspecting a template
19
+ * without an MCP client.
20
+ *
21
+ * scaffold <dir> [--name <slug>]
22
+ * Scaffold a new template into <dir>. Replaces the old
23
+ * `npm create react-pptx-template` flow.
24
+ *
25
+ * skill [--path]
26
+ * Print the bundled `SKILL.md` to stdout (or its absolute
27
+ * path with `--path`). Paste into a Claude project to teach
28
+ * the model how to drive any react-pptx MCP server.
29
+ *
30
+ * The `--template` flag accepts:
31
+ * - A bare package specifier resolved from the current directory
32
+ * (e.g. `@acme/slide-template`).
33
+ * - A path to a built JS file (`./dist/index.js`).
34
+ * - A path to a directory containing `package.json` (the bin reads
35
+ * `main` / `exports['.']`).
36
+ */
37
+ import { readFileSync, realpathSync, statSync } from 'node:fs';
38
+ import { dirname, resolve as resolvePath } from 'node:path';
39
+ import { fileURLToPath, pathToFileURL } from 'node:url';
40
+ import { PptxSlidesRuntime } from './core/index.js';
41
+ import { renderSlides } from './mcp/render.js';
42
+ import { createSlideServer } from './mcp/server.js';
43
+ import { defaultName, scaffoldTemplate, validateName } from './scaffold/index.js';
44
+ const USAGE = `Usage: slidesctl <command> [options]
45
+
46
+ Commands:
47
+ serve Start an MCP server over stdio.
48
+ generate Read { title, slides } JSON from stdin, write a .pptx file.
49
+ list Print the slide types a template exposes.
50
+ scaffold Scaffold a new template into <dir>.
51
+ skill Print the bundled SKILL.md.
52
+
53
+ Options (serve / generate / list):
54
+ --template, -t <path> Template to load. Accepts a package name, a file
55
+ path, or a directory.
56
+ --output, -o <dir> Output directory for generated .pptx files
57
+ (serve/generate only; defaults to cwd).
58
+ --name, <id> MCP server name override (serve only).
59
+
60
+ Options (scaffold):
61
+ --name <slug> Template name (default: inferred from <dir>).
62
+
63
+ Options (skill):
64
+ --path Print SKILL.md's absolute path only.
65
+
66
+ Global:
67
+ --help, -h Show this message.
68
+ `;
69
+ const parseArgs = (argv) => {
70
+ const args = {
71
+ command: undefined,
72
+ positional: [],
73
+ template: undefined,
74
+ output: undefined,
75
+ name: undefined,
76
+ path: false,
77
+ help: false,
78
+ };
79
+ for (let i = 0; i < argv.length; i++) {
80
+ const arg = argv[i];
81
+ switch (arg) {
82
+ case '--help':
83
+ case '-h':
84
+ args.help = true;
85
+ break;
86
+ case '--template':
87
+ case '-t':
88
+ args.template = argv[++i];
89
+ break;
90
+ case '--output':
91
+ case '-o':
92
+ args.output = argv[++i];
93
+ break;
94
+ case '--name':
95
+ args.name = argv[++i];
96
+ break;
97
+ case '--path':
98
+ args.path = true;
99
+ break;
100
+ default:
101
+ if (arg === undefined)
102
+ break;
103
+ if (arg.startsWith('-'))
104
+ throw new CliError(`Unknown flag: ${arg}`);
105
+ if (args.command === undefined) {
106
+ args.command = arg;
107
+ }
108
+ else {
109
+ args.positional.push(arg);
110
+ }
111
+ }
112
+ }
113
+ return args;
114
+ };
115
+ class CliError extends Error {
116
+ exitCode;
117
+ constructor(message, exitCode = 2) {
118
+ super(message);
119
+ this.exitCode = exitCode;
120
+ this.name = 'CliError';
121
+ }
122
+ }
123
+ /**
124
+ * Resolve a `--template` argument to a Template instance.
125
+ *
126
+ * The template is the default export of the resolved module, or any named
127
+ * export that matches the Template shape (`name`, `components`, `canvas`).
128
+ */
129
+ const loadTemplate = async (spec) => {
130
+ const cwd = process.cwd();
131
+ let importTarget;
132
+ if (isAbsoluteOrRelative(spec)) {
133
+ const abs = resolvePath(cwd, spec);
134
+ let resolved;
135
+ try {
136
+ const stat = statSync(abs);
137
+ resolved = stat.isDirectory() ? resolveDirEntry(abs) : abs;
138
+ }
139
+ catch (err) {
140
+ throw new CliError(`Cannot read --template path "${spec}" (resolved to "${abs}"): ${describeError(err)}`);
141
+ }
142
+ importTarget = pathToFileURL(resolved).href;
143
+ }
144
+ else {
145
+ importTarget = resolveBareSpecifier(spec, cwd);
146
+ }
147
+ let mod;
148
+ try {
149
+ mod = await import(importTarget);
150
+ }
151
+ catch (err) {
152
+ throw new CliError(`Failed to import template "${spec}": ${describeError(err)}`);
153
+ }
154
+ const template = pickTemplate(mod);
155
+ if (!template) {
156
+ throw new CliError(`Module at "${spec}" does not export a Template (need an object with name + components).`);
157
+ }
158
+ return template;
159
+ };
160
+ const isAbsoluteOrRelative = (spec) => spec.startsWith('.') || spec.startsWith('/') || /^[A-Z]:\\/i.test(spec);
161
+ const resolveDirEntry = (dir) => {
162
+ const pkgPath = resolvePath(dir, 'package.json');
163
+ let pkg;
164
+ try {
165
+ pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
166
+ }
167
+ catch (err) {
168
+ throw new CliError(`Template directory "${dir}" has no readable package.json: ${describeError(err)}`);
169
+ }
170
+ const entry = pkg.module ?? pkg.main ?? exportsDefault(pkg.exports);
171
+ if (!entry) {
172
+ throw new CliError(`Template directory "${dir}" has no main/module/exports entry to import.`);
173
+ }
174
+ return resolvePath(dir, entry);
175
+ };
176
+ const exportsDefault = (exportsField) => {
177
+ if (typeof exportsField === 'string')
178
+ return exportsField;
179
+ if (exportsField && typeof exportsField === 'object') {
180
+ const dot = exportsField['.'];
181
+ if (typeof dot === 'string')
182
+ return dot;
183
+ if (dot && typeof dot === 'object') {
184
+ const sub = dot;
185
+ const candidate = sub['import'] ?? sub['default'] ?? sub['node'];
186
+ if (typeof candidate === 'string')
187
+ return candidate;
188
+ }
189
+ }
190
+ return undefined;
191
+ };
192
+ const resolveBareSpecifier = (spec, cwd) => {
193
+ // ESM resolution honours `exports.import` and other conditions that
194
+ // require.resolve() doesn't, which matters for templates that ship
195
+ // conditional exports. Anchor resolution at the user's cwd via a synthetic
196
+ // package.json URL so we look in their node_modules.
197
+ const parentUrl = pathToFileURL(resolvePath(cwd, 'package.json')).href;
198
+ try {
199
+ return import.meta.resolve(spec, parentUrl);
200
+ }
201
+ catch (err) {
202
+ throw new CliError(`Cannot resolve template "${spec}" from ${cwd}: ${describeError(err)}. ` +
203
+ `Install it as a dependency or pass a path with --template.`);
204
+ }
205
+ };
206
+ const pickTemplate = (mod) => {
207
+ if (!mod || typeof mod !== 'object')
208
+ return undefined;
209
+ const candidates = [];
210
+ const m = mod;
211
+ if (m['default'])
212
+ candidates.push(m['default']);
213
+ for (const [key, value] of Object.entries(m)) {
214
+ if (key === 'default')
215
+ continue;
216
+ candidates.push(value);
217
+ }
218
+ for (const c of candidates) {
219
+ if (isTemplate(c))
220
+ return c;
221
+ }
222
+ return undefined;
223
+ };
224
+ const isTemplate = (value) => {
225
+ if (!value || typeof value !== 'object')
226
+ return false;
227
+ const v = value;
228
+ return typeof v['name'] === 'string' && typeof v['components'] === 'object';
229
+ };
230
+ const newRuntime = (output) => new PptxSlidesRuntime({ outputDir: output ?? process.cwd() });
231
+ const runServe = async (args) => {
232
+ if (!args.template)
233
+ throw new CliError('serve requires --template <path-or-specifier>.');
234
+ const template = await loadTemplate(args.template);
235
+ const runtime = newRuntime(args.output);
236
+ const server = createSlideServer({
237
+ template,
238
+ runtime,
239
+ ...(args.name ? { serverInfo: { name: args.name, version: '0.1.0' } } : {}),
240
+ });
241
+ await server.start({ transport: 'stdio' });
242
+ };
243
+ const runList = async (args) => {
244
+ if (!args.template)
245
+ throw new CliError('list requires --template <path-or-specifier>.');
246
+ const template = await loadTemplate(args.template);
247
+ const lines = [`Template: ${template.name}`, '', 'Slide types:'];
248
+ for (const [name, tc] of Object.entries(template.components)) {
249
+ lines.push(` • ${name} — ${tc.description ?? '(no description)'}`);
250
+ }
251
+ process.stdout.write(lines.join('\n') + '\n');
252
+ };
253
+ const runGenerate = async (args) => {
254
+ if (!args.template)
255
+ throw new CliError('generate requires --template <path-or-specifier>.');
256
+ const template = await loadTemplate(args.template);
257
+ const runtime = newRuntime(args.output);
258
+ const raw = await readStdin();
259
+ if (raw.trim().length === 0) {
260
+ throw new CliError('generate: no input on stdin. Pipe JSON of { title, slides: [{ component, props }] }.');
261
+ }
262
+ let input;
263
+ try {
264
+ input = JSON.parse(raw);
265
+ }
266
+ catch (err) {
267
+ throw new CliError(`generate: invalid JSON on stdin: ${describeError(err)}`);
268
+ }
269
+ if (typeof input.title !== 'string' || !Array.isArray(input.slides)) {
270
+ throw new CliError('generate: input must be { title: string, slides: array }.');
271
+ }
272
+ const result = await renderSlides({
273
+ template,
274
+ runtime,
275
+ title: input.title,
276
+ slides: input.slides,
277
+ });
278
+ if (result.ok) {
279
+ process.stdout.write(`${result.filePath}\n`);
280
+ return;
281
+ }
282
+ throw new CliError(result.message, result.code === 'unknown_component' ? 3 : 2);
283
+ };
284
+ const runSkill = (args) => {
285
+ const skillPath = resolveSkillPath();
286
+ if (args.path) {
287
+ process.stdout.write(`${skillPath}\n`);
288
+ return;
289
+ }
290
+ process.stdout.write(readFileSync(skillPath, 'utf8'));
291
+ };
292
+ const runScaffold = (args) => {
293
+ const [target] = args.positional;
294
+ if (!target) {
295
+ throw new CliError('scaffold requires a target directory: `slidesctl scaffold my-template`.');
296
+ }
297
+ const name = args.name ?? defaultName(target);
298
+ const nameError = validateName(name);
299
+ if (nameError) {
300
+ throw new CliError(`Invalid template name "${name}": ${nameError}. ` + `Pass --name <slug> with a valid name.`);
301
+ }
302
+ const result = scaffoldTemplate({ target, name });
303
+ process.stdout.write(`Scaffolded ${result.fileCount} files into ${result.targetPath}\n`);
304
+ process.stdout.write(`\nNext steps:\n cd ${target}\n pnpm install\n pnpm dev # open the viewer\n pnpm build # emit dist/ so slidesctl can serve it\n`);
305
+ };
306
+ const resolveSkillPath = () => {
307
+ // SKILL.md ships at the package root, one level above dist/cli.js.
308
+ // From src/cli.ts the same relative path resolves correctly because
309
+ // we run from dist/ in production.
310
+ const here = dirname(fileURLToPath(import.meta.url));
311
+ return resolvePath(here, '..', 'SKILL.md');
312
+ };
313
+ const readStdin = () => {
314
+ const chunks = [];
315
+ return new Promise((resolve, reject) => {
316
+ process.stdin.on('data', (chunk) => {
317
+ chunks.push(typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk);
318
+ });
319
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
320
+ process.stdin.on('error', (err) => reject(err));
321
+ });
322
+ };
323
+ const describeError = (err) => (err instanceof Error ? err.message : String(err));
324
+ export const main = async (argv) => {
325
+ let args;
326
+ try {
327
+ args = parseArgs(argv);
328
+ }
329
+ catch (err) {
330
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
331
+ process.stderr.write(USAGE);
332
+ process.exit(2);
333
+ }
334
+ if (args.help || args.command === undefined) {
335
+ process.stdout.write(USAGE);
336
+ process.exit(args.help ? 0 : 1);
337
+ }
338
+ try {
339
+ switch (args.command) {
340
+ case 'serve':
341
+ await runServe(args);
342
+ return;
343
+ case 'list':
344
+ await runList(args);
345
+ return;
346
+ case 'generate':
347
+ await runGenerate(args);
348
+ return;
349
+ case 'scaffold':
350
+ runScaffold(args);
351
+ return;
352
+ case 'skill':
353
+ runSkill(args);
354
+ return;
355
+ default:
356
+ process.stderr.write(`Unknown command: ${args.command}\n`);
357
+ process.stderr.write(USAGE);
358
+ process.exit(2);
359
+ }
360
+ }
361
+ catch (err) {
362
+ if (err instanceof CliError) {
363
+ process.stderr.write(`${err.message}\n`);
364
+ process.exit(err.exitCode);
365
+ }
366
+ process.stderr.write(`slidesctl failed: ${describeError(err)}\n`);
367
+ process.exit(1);
368
+ }
369
+ };
370
+ // pnpm's content-addressed install layout means `process.argv[1]` is the
371
+ // `.bin` symlink while `import.meta.url` is the realpath under `.pnpm/`.
372
+ // Use realpathSync on both sides so direct invocation and
373
+ // `node_modules/.bin/slidesctl` both detect this file as the entrypoint.
374
+ const argvPath = process.argv[1];
375
+ if (argvPath !== undefined) {
376
+ try {
377
+ const argvReal = realpathSync(argvPath);
378
+ const selfReal = fileURLToPath(import.meta.url);
379
+ if (argvReal === selfReal)
380
+ void main(process.argv.slice(2));
381
+ }
382
+ catch {
383
+ // not invoked as a script — module being imported, ignore.
384
+ }
385
+ }
386
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * The minimal JSX primitive surface the reconciler walks.
3
+ *
4
+ * **This is intentionally a small, lower-case set.** High-level brand
5
+ * components (`<Cover/>`, `<TwoColumn/>`, etc.) live in brand packages
6
+ * (e.g., `@sanity-labs/slides`) and *compose* these primitives. The substrate
7
+ * exports just enough to render an arbitrary slide tree.
8
+ *
9
+ * Why hand-rolled host elements rather than `<div>`-style intrinsic elements:
10
+ * we want the reconciler to recognize these by *type identity*, not by string
11
+ * tag names. Type identity removes a class of bugs ("did you mean 'box' or
12
+ * 'Box'?") and gives the type-checker something concrete to enforce.
13
+ *
14
+ * These don't render to the DOM — they're inert markers the reconciler walks.
15
+ * They return `null` so they're harmless if accidentally rendered through
16
+ * react-dom (e.g., during Storybook prototyping).
17
+ */
18
+ import type { ReactNode } from 'react';
19
+ import type { Rect } from './geometry.js';
20
+ import type { ArtifactRef, SlotId } from './manifest.js';
21
+ import type { HexColor, ParagraphStyle, TextStyle } from './runtime.js';
22
+ /**
23
+ * A single slide in the deck.
24
+ *
25
+ * Every `<Slide>` becomes a `createSlide` op. Children are rendered into the
26
+ * slide's coordinate space.
27
+ */
28
+ export interface SlideProps {
29
+ /** Children: `<Box>` and `<Image>` shapes laid out inside the slide. */
30
+ children?: ReactNode;
31
+ }
32
+ /**
33
+ * A discriminated union describing a `<Box>`'s background fill.
34
+ *
35
+ * Shaped as a tagged union — *not* a flat `fill?: HexColor` — so future fill
36
+ * kinds (texture, image-as-background, gradient) can be added without
37
+ * sprouting parallel optional props. The discriminator is load-bearing:
38
+ * off-brand fills are inexpressible at the type level when a brand component
39
+ * narrows what kinds it accepts.
40
+ *
41
+ * Today only `'solid'` is supported. Image fills (full-bleed photos) are
42
+ * authored as `<Image>` siblings of `<Box>` rather than nested inside a
43
+ * Box's fill.
44
+ */
45
+ export type BoxFill = {
46
+ kind: 'solid';
47
+ color: HexColor;
48
+ };
49
+ /**
50
+ * A rectangular text box on the slide canvas.
51
+ *
52
+ * Becomes a `createShape` op with shape `TEXT_BOX` (the only shape this
53
+ * primitive set produces; other shape kinds are reserved for the future).
54
+ * Children are concatenated into a single text run with style spans.
55
+ */
56
+ export interface BoxProps {
57
+ /** The shape's rect in *points*. The reconciler converts to EMU at the boundary. */
58
+ rect: Rect;
59
+ /**
60
+ * Optional slot ID, encoded into the shape's alt-text. Required for any text
61
+ * box that re-fill should target. Format: `<componentName>:<slotName>`,
62
+ * e.g., `"cover:title"`. See `manifest.ts` for encoding details.
63
+ */
64
+ slotId?: SlotId;
65
+ /**
66
+ * Optional background fill. When set, the reconciler emits an
67
+ * `updateShapeProperties` op immediately after the shape is created,
68
+ * before any text or text-style ops. An empty Box (no children) with a
69
+ * `fill` is a valid full-bleed colored background.
70
+ */
71
+ fill?: BoxFill;
72
+ /** Default text style applied to the shape's contents. */
73
+ textStyle?: TextStyle;
74
+ /** Default paragraph style. */
75
+ paragraphStyle?: ParagraphStyle;
76
+ /** Children: `<Text>` runs and/or raw strings. */
77
+ children?: ReactNode;
78
+ }
79
+ /**
80
+ * A styled text run inside a `<Box>`.
81
+ *
82
+ * Multiple `<Text>` children of the same `<Box>` are concatenated; each
83
+ * run's style is applied to its character range via `updateTextStyle` ops.
84
+ * Raw string children of `<Box>` are equivalent to `<Text>{text}</Text>`
85
+ * with no style override.
86
+ *
87
+ * The intent of carrying `textStyle` here (rather than mandating a typography
88
+ * token) is: high-level brand components compose this primitive *and* enforce
89
+ * brand-token discipline at *their* layer. The substrate stays brand-agnostic.
90
+ */
91
+ export interface TextProps {
92
+ /** Style applied to this run only. Merges over `<Box>`'s `textStyle`. */
93
+ textStyle?: TextStyle;
94
+ /** Children: text content. Nested elements are flattened to their text. */
95
+ children?: ReactNode;
96
+ }
97
+ /**
98
+ * A wrapper that sets the foreground color of its children.
99
+ *
100
+ * A thin convenience over `<Text textStyle={{foregroundColor}}/>` so
101
+ * brand components can read more declaratively. The reconciler treats this
102
+ * identically to a `<Text>` with the same style.
103
+ */
104
+ export interface ColorProps {
105
+ /** The color to apply, as a 24-bit hex. (`#RRGGBB`.) */
106
+ color: HexColor;
107
+ /** Children: text or `<Text>` runs. */
108
+ children?: ReactNode;
109
+ }
110
+ /**
111
+ * A reference to a brand-resolved image, including its provenance.
112
+ *
113
+ * The `artifact` field is **required**: every image rendered through the
114
+ * substrate is recorded in the generation manifest's `artifacts` list, so
115
+ * downstream tooling can detect 404s and verify content integrity. An
116
+ * `<Image>` without a `ArtifactRef` is impossible to construct —
117
+ * type-level enforcement of the manifest contract.
118
+ */
119
+ export interface ImageRef {
120
+ /** Resolved URL the runtime will fetch the image bytes from. */
121
+ readonly url: string;
122
+ /** Template-artifact provenance — recorded in manifest.artifacts. Required. */
123
+ readonly artifact: ArtifactRef;
124
+ }
125
+ /**
126
+ * A bitmap image placed on a slide, rendered as a `createImage` op.
127
+ *
128
+ * Sibling of `<Box>` inside a `<Slide>`. Used for full-bleed background
129
+ * photos, dot-grid texture overlays, brand logos, and any other rasterized
130
+ * brand artifact. Vector content (lines, rectangles, etc.) goes through
131
+ * `<Box>` and the (future) shape-kind extension to its fill prop.
132
+ */
133
+ export interface ImageProps {
134
+ /** The image's rect in *points*. The reconciler converts to EMU at the boundary. */
135
+ rect: Rect;
136
+ /**
137
+ * The image to render, including its brand-artifact provenance. Required —
138
+ * an `<Image>` without an `ImageRef` is unconstructable, by design.
139
+ */
140
+ image: ImageRef;
141
+ /**
142
+ * Optional slot ID. When set, the reconciler records `SlotId → imageId` in
143
+ * the manifest's slot registry.
144
+ */
145
+ slotId?: SlotId;
146
+ /**
147
+ * Accessibility alt-text shown to assistive tech.
148
+ *
149
+ * Carried through to the `createImage` op's `altText` field.
150
+ */
151
+ altText?: string;
152
+ }
153
+ /** A unique brand for each primitive's React component. */
154
+ type Marker<TProps> = ((props: TProps) => null) & {
155
+ readonly __rgsKind: string;
156
+ };
157
+ export declare const Slide: Marker<SlideProps>;
158
+ export declare const Box: Marker<BoxProps>;
159
+ export declare const Text: Marker<TextProps>;
160
+ export declare const Color: Marker<ColorProps>;
161
+ export declare const Image: Marker<ImageProps>;
162
+ /**
163
+ * The set of primitive React components the reconciler recognizes.
164
+ *
165
+ * Used internally for type identity checks (see `reconciler.ts`). Exposed for
166
+ * downstream packages that want to detect "is this a substrate primitive?"
167
+ * without importing each one individually.
168
+ */
169
+ export declare const PRIMITIVES: {
170
+ readonly Slide: Marker<SlideProps>;
171
+ readonly Box: Marker<BoxProps>;
172
+ readonly Text: Marker<TextProps>;
173
+ readonly Color: Marker<ColorProps>;
174
+ readonly Image: Marker<ImageProps>;
175
+ };
176
+ /** Type guard: is this React element type one of our primitives? */
177
+ export declare const isPrimitive: (type: unknown) => type is (typeof PRIMITIVES)[keyof typeof PRIMITIVES];
178
+ export {};
179
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/core/components.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAExE;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,oFAAoF;IACpF,IAAI,EAAE,IAAI,CAAC;IAEX;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,0DAA0D;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC,kDAAkD;IAClD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,KAAK,EAAE,QAAQ,CAAC;IAChB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB,gEAAgE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,IAAI,EAAE,IAAI,CAAC;IAEX;;;OAGG;IACH,KAAK,EAAE,QAAQ,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2DAA2D;AAC3D,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AASjF,eAAO,MAAM,KAAK,oBAAkC,CAAC;AACrD,eAAO,MAAM,GAAG,kBAA8B,CAAC;AAC/C,eAAO,MAAM,IAAI,mBAAgC,CAAC;AAClD,eAAO,MAAM,KAAK,oBAAkC,CAAC;AACrD,eAAO,MAAM,KAAK,oBAAkC,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU;;;;;;CAA8C,CAAC;AAItE,oEAAoE;AACpE,eAAO,MAAM,WAAW,GAAI,MAAM,OAAO,KAAG,IAAI,IAAI,CAAC,OAAO,UAAU,EAAE,MAAM,OAAO,UAAU,CACtE,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The minimal JSX primitive surface the reconciler walks.
3
+ *
4
+ * **This is intentionally a small, lower-case set.** High-level brand
5
+ * components (`<Cover/>`, `<TwoColumn/>`, etc.) live in brand packages
6
+ * (e.g., `@sanity-labs/slides`) and *compose* these primitives. The substrate
7
+ * exports just enough to render an arbitrary slide tree.
8
+ *
9
+ * Why hand-rolled host elements rather than `<div>`-style intrinsic elements:
10
+ * we want the reconciler to recognize these by *type identity*, not by string
11
+ * tag names. Type identity removes a class of bugs ("did you mean 'box' or
12
+ * 'Box'?") and gives the type-checker something concrete to enforce.
13
+ *
14
+ * These don't render to the DOM — they're inert markers the reconciler walks.
15
+ * They return `null` so they're harmless if accidentally rendered through
16
+ * react-dom (e.g., during Storybook prototyping).
17
+ */
18
+ const makeMarker = (kind) => {
19
+ const component = (_props) => null;
20
+ // Display name aids debugging in React DevTools and assertion messages.
21
+ Object.defineProperty(component, 'name', { value: kind });
22
+ return Object.assign(component, { __rgsKind: kind });
23
+ };
24
+ export const Slide = makeMarker('Slide');
25
+ export const Box = makeMarker('Box');
26
+ export const Text = makeMarker('Text');
27
+ export const Color = makeMarker('Color');
28
+ export const Image = makeMarker('Image');
29
+ /**
30
+ * The set of primitive React components the reconciler recognizes.
31
+ *
32
+ * Used internally for type identity checks (see `reconciler.ts`). Exposed for
33
+ * downstream packages that want to detect "is this a substrate primitive?"
34
+ * without importing each one individually.
35
+ */
36
+ export const PRIMITIVES = { Slide, Box, Text, Color, Image };
37
+ const PRIMITIVE_SET = new Set(Object.values(PRIMITIVES));
38
+ /** Type guard: is this React element type one of our primitives? */
39
+ export const isPrimitive = (type) => PRIMITIVE_SET.has(type);
40
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/core/components.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAyJH,MAAM,UAAU,GAAG,CAAS,IAAY,EAAkB,EAAE;IAC1D,MAAM,SAAS,GAAG,CAAC,MAAc,EAAQ,EAAE,CAAC,IAAI,CAAC;IACjD,wEAAwE;IACxE,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAW,CAAC,CAAC;AAChE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAAa,OAAO,CAAC,CAAC;AACrD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAW,KAAK,CAAC,CAAC;AAC/C,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAY,MAAM,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAAa,OAAO,CAAC,CAAC;AACrD,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAAa,OAAO,CAAC,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAW,CAAC;AAEtE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAU,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAElE,oEAAoE;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAa,EAAwD,EAAE,CACjG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC"}