shadertown 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +20 -0
  3. package/cli/cli.mjs +341 -0
  4. package/cli/shadertown.mjs +8 -0
  5. package/dist/config.d.ts +29 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +8 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/export.d.ts +30 -0
  10. package/dist/export.d.ts.map +1 -0
  11. package/dist/export.js +234 -0
  12. package/dist/export.js.map +1 -0
  13. package/dist/generated/sources.d.ts +22 -0
  14. package/dist/generated/sources.d.ts.map +1 -0
  15. package/dist/generated/sources.js +24 -0
  16. package/dist/generated/sources.js.map +1 -0
  17. package/dist/index.d.ts +13 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +8 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/params.d.ts +24 -0
  22. package/dist/params.d.ts.map +1 -0
  23. package/dist/params.js +105 -0
  24. package/dist/params.js.map +1 -0
  25. package/dist/react.d.ts +41 -0
  26. package/dist/react.d.ts.map +1 -0
  27. package/dist/react.js +127 -0
  28. package/dist/react.js.map +1 -0
  29. package/dist/registry.d.ts +1930 -0
  30. package/dist/registry.d.ts.map +1 -0
  31. package/dist/registry.js +1067 -0
  32. package/dist/registry.js.map +1 -0
  33. package/dist/renderer.d.ts +31 -0
  34. package/dist/renderer.d.ts.map +1 -0
  35. package/dist/renderer.js +144 -0
  36. package/dist/renderer.js.map +1 -0
  37. package/dist/stage.d.ts +39 -0
  38. package/dist/stage.d.ts.map +1 -0
  39. package/dist/stage.js +79 -0
  40. package/dist/stage.js.map +1 -0
  41. package/dist/types.d.ts +71 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/package.json +85 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shadertown
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # shadertown
2
+
3
+ Production WebGPU shader backgrounds for the web, drawn by
4
+ [vgpu](https://vgpu.sh).
5
+
6
+ ```bash
7
+ npm install shadertown
8
+ ```
9
+
10
+ ```tsx
11
+ import { ShaderCanvas } from "shadertown/react";
12
+
13
+ <ShaderCanvas shader="aurora" params={{ speed: 0.4 }} play="visible" />;
14
+ ```
15
+
16
+ No WGSL loader, no bundler plugin: shader sources ship as strings. Every
17
+ renderer on a page shares one GPU context and one frame loop, and the loop stops
18
+ when nothing is animating.
19
+
20
+ Full documentation: https://www.shadertown.com/docs
package/cli/cli.mjs ADDED
@@ -0,0 +1,341 @@
1
+ import { mkdir, readFile, writeFile, access, chmod, rm } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { spawn } from "node:child_process";
5
+
6
+ const DEFAULT_REGISTRY = process.env.SHADERTOWN_REGISTRY ?? "https://www.shadertown.com";
7
+ const DEFAULT_OUT = "src/shaders";
8
+
9
+ const esc = (code, text) => `\u001b[${code}m${text}\u001b[0m`;
10
+ const c = {
11
+ dim: (s) => esc(2, s),
12
+ bold: (s) => esc(1, s),
13
+ green: (s) => esc(32, s),
14
+ cyan: (s) => esc(36, s),
15
+ yellow: (s) => esc(33, s),
16
+ };
17
+
18
+ export async function run(argv) {
19
+ const [command, ...rest] = argv;
20
+ switch (command) {
21
+ case "add":
22
+ return add(rest);
23
+ case "list":
24
+ return list(rest);
25
+ case "init":
26
+ return init();
27
+ case "login":
28
+ return login(rest);
29
+ case "logout":
30
+ return logout();
31
+ case "whoami":
32
+ return whoami();
33
+ case undefined:
34
+ case "help":
35
+ case "--help":
36
+ case "-h":
37
+ return help();
38
+ case "--version":
39
+ case "-v":
40
+ return version();
41
+ default:
42
+ throw new Error(`Unknown command "${command}". Run \`shadertown help\`.`);
43
+ }
44
+ }
45
+
46
+ function parseFlags(args) {
47
+ const flags = {};
48
+ const positional = [];
49
+ for (let i = 0; i < args.length; i += 1) {
50
+ const arg = args[i];
51
+ if (arg.startsWith("--")) {
52
+ const key = arg.slice(2);
53
+ if (key === "force") {
54
+ flags.force = true;
55
+ } else {
56
+ flags[key] = args[i + 1];
57
+ i += 1;
58
+ }
59
+ } else {
60
+ positional.push(arg);
61
+ }
62
+ }
63
+ return { flags, positional };
64
+ }
65
+
66
+ /** Reads shadertown.config.ts without executing it - only the fields we need. */
67
+ async function readProjectConfig(cwd) {
68
+ for (const file of ["shadertown.config.ts", "shadertown.config.js", "shadertown.config.mjs"]) {
69
+ try {
70
+ const source = await readFile(join(cwd, file), "utf8");
71
+ const pick = (key) => source.match(new RegExp(`${key}\\s*:\\s*["\'\`]([^"\'\`]+)`))?.[1];
72
+ return { outDir: pick("outDir"), registry: pick("registry"), license: pick("license") };
73
+ } catch {
74
+ // Try the next candidate.
75
+ }
76
+ }
77
+ return {};
78
+ }
79
+
80
+ // --- credentials ----------------------------------------------------------
81
+
82
+ const CREDENTIALS_PATH = join(homedir(), ".shadertown", "credentials.json");
83
+
84
+ async function readToken() {
85
+ // An explicit environment variable wins, so CI needs no interactive login.
86
+ if (process.env.SHADERTOWN_TOKEN) return process.env.SHADERTOWN_TOKEN;
87
+ try {
88
+ const raw = await readFile(CREDENTIALS_PATH, "utf8");
89
+ return JSON.parse(raw).token ?? undefined;
90
+ } catch {
91
+ return undefined;
92
+ }
93
+ }
94
+
95
+ async function writeToken(token, licensee, registry) {
96
+ await mkdir(dirname(CREDENTIALS_PATH), { recursive: true });
97
+ await writeFile(CREDENTIALS_PATH, JSON.stringify({ token, licensee, registry }, null, 2));
98
+ // The token is a bearer credential; keep it off other accounts on the box.
99
+ await chmod(CREDENTIALS_PATH, 0o600);
100
+ }
101
+
102
+ function openBrowser(url) {
103
+ const command =
104
+ process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
105
+ try {
106
+ spawn(command, [url], { stdio: "ignore", detached: true }).unref();
107
+ } catch {
108
+ // Printing the URL is the fallback, and it is always printed anyway.
109
+ }
110
+ }
111
+
112
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
113
+
114
+ async function login(args) {
115
+ const { flags } = parseFlags(args);
116
+ const config = await readProjectConfig(process.cwd());
117
+ const registry = flags.registry ?? config.registry ?? DEFAULT_REGISTRY;
118
+
119
+ const startResponse = await fetch(new URL("/api/device/start", registry), { method: "POST" });
120
+ if (!startResponse.ok) {
121
+ throw new Error(`${registry} did not start a login (${startResponse.status}).`);
122
+ }
123
+ const flow = await startResponse.json();
124
+
125
+ console.log(`\n ${c.bold("shadertown")} ${c.dim(`- ${registry}`)}\n`);
126
+ console.log(` Open ${c.cyan(flow.verification_uri)}`);
127
+ console.log(` Code ${c.bold(flow.user_code)}\n`);
128
+ console.log(` ${c.dim("Waiting for approval...")}`);
129
+
130
+ if (!flags["no-browser"]) openBrowser(flow.verification_uri_complete ?? flow.verification_uri);
131
+
132
+ const deadline = Date.now() + (flow.expires_in ?? 600) * 1000;
133
+ let interval = (flow.interval ?? 2) * 1000;
134
+
135
+ while (Date.now() < deadline) {
136
+ await sleep(interval);
137
+ const response = await fetch(new URL("/api/device/poll", registry), {
138
+ method: "POST",
139
+ headers: { "content-type": "application/json" },
140
+ body: JSON.stringify({ device_code: flow.device_code }),
141
+ });
142
+ const body = await response.json().catch(() => ({}));
143
+
144
+ if (response.ok && body.access_token) {
145
+ await writeToken(body.access_token, body.licensee, registry);
146
+ console.log(`\n ${c.green("ok")} Signed in as ${c.bold(body.licensee ?? "your account")}`);
147
+ console.log(` ${c.dim(`Token stored in ${CREDENTIALS_PATH}`)}\n`);
148
+ return;
149
+ }
150
+ if (body.error === "slow_down") interval = (body.interval ?? 4) * 1000;
151
+ if (body.error === "expired_token") break;
152
+ }
153
+
154
+ throw new Error("That login expired before it was approved. Run `shadertown login` again.");
155
+ }
156
+
157
+ async function logout() {
158
+ await rm(CREDENTIALS_PATH, { force: true });
159
+ console.log(`\n ${c.green("ok")} Signed out.\n`);
160
+ }
161
+
162
+ async function whoami() {
163
+ const token = await readToken();
164
+ if (!token) {
165
+ console.log(`\n ${c.dim("Not signed in. Run `shadertown login`.")}\n`);
166
+ return;
167
+ }
168
+ try {
169
+ const raw = await readFile(CREDENTIALS_PATH, "utf8");
170
+ const saved = JSON.parse(raw);
171
+ console.log(`\n ${c.bold(saved.licensee ?? "signed in")} ${c.dim(`- ${saved.registry ?? DEFAULT_REGISTRY}`)}\n`);
172
+ } catch {
173
+ console.log(`\n ${c.dim("Signed in via SHADERTOWN_TOKEN.")}\n`);
174
+ }
175
+ }
176
+
177
+ async function fetchJson(url, key) {
178
+ const response = await fetch(url, {
179
+ headers: key ? { authorization: `Bearer ${key}` } : undefined,
180
+ });
181
+
182
+ if (response.status === 402) {
183
+ const body = await response.json().catch(() => ({}));
184
+ const lines = [
185
+ body.message ?? "This shader requires a licence.",
186
+ body.reason ? c.dim(body.reason) : null,
187
+ body.hint ? c.dim(body.hint) : null,
188
+ body.upgrade ? c.cyan(body.upgrade) : null,
189
+ ].filter(Boolean);
190
+ throw new Error(lines.join("\n "));
191
+ }
192
+
193
+ if (!response.ok) {
194
+ const body = await response.json().catch(() => ({}));
195
+ throw new Error(body.message ?? `${url} responded ${response.status}`);
196
+ }
197
+
198
+ return response.json();
199
+ }
200
+
201
+ async function exists(path) {
202
+ try {
203
+ await access(path);
204
+ return true;
205
+ } catch {
206
+ return false;
207
+ }
208
+ }
209
+
210
+ async function add(args) {
211
+ const { flags, positional } = parseFlags(args);
212
+ if (positional.length === 0) {
213
+ throw new Error("Give at least one shader slug. Try `shadertown list`.");
214
+ }
215
+
216
+ const cwd = process.cwd();
217
+ const config = await readProjectConfig(cwd);
218
+ const registry = flags.registry ?? config.registry ?? DEFAULT_REGISTRY;
219
+ const outDir = resolve(cwd, flags.out ?? config.outDir ?? DEFAULT_OUT);
220
+ const key = await readToken();
221
+
222
+ console.log(`\n ${c.bold("shadertown")} ${c.dim(`- ${registry}`)}\n`);
223
+
224
+ for (const slug of positional) {
225
+ const url = new URL(`/r/${slug}.json`, registry);
226
+ if (flags.params) {
227
+ for (const [k, v] of new URLSearchParams(flags.params)) url.searchParams.set(k, v);
228
+ }
229
+ if (flags.licensee) url.searchParams.set("licensee", flags.licensee);
230
+
231
+ const item = await fetchJson(url.toString(), key);
232
+ await mkdir(outDir, { recursive: true });
233
+
234
+ let written = 0;
235
+ let skipped = 0;
236
+ for (const file of item.files) {
237
+ const target = join(outDir, file.path);
238
+ if ((await exists(target)) && !flags.force) {
239
+ skipped += 1;
240
+ continue;
241
+ }
242
+ await mkdir(dirname(target), { recursive: true });
243
+ await writeFile(target, file.content);
244
+ written += 1;
245
+ console.log(` ${c.green("add")} ${relative(cwd, target)}`);
246
+ }
247
+
248
+ if (skipped > 0) {
249
+ console.log(` ${c.yellow("skip")} ${skipped} existing file(s) ${c.dim("- pass --force to overwrite")}`);
250
+ }
251
+ console.log(` ${c.dim(`${item.name} - ${item.tagline}`)}`);
252
+ if (written > 0) {
253
+ console.log(` ${c.dim(`Read ${slug}/README.md for every control.`)}`);
254
+ }
255
+ console.log("");
256
+ }
257
+
258
+ console.log(` ${c.dim("Next: import the preset and pass it to <ShaderCanvas preset={...} />")}\n`);
259
+ }
260
+
261
+ async function list(args) {
262
+ const { flags } = parseFlags(args);
263
+ const config = await readProjectConfig(process.cwd());
264
+ const registry = flags.registry ?? config.registry ?? DEFAULT_REGISTRY;
265
+ const index = await fetchJson(new URL("/r/", registry).toString());
266
+
267
+ console.log(`\n ${c.bold("shadertown")} ${c.dim(`- ${index.items.length} shaders`)}\n`);
268
+ const width = Math.max(...index.items.map((item) => item.slug.length));
269
+ let free = 0;
270
+ for (const item of index.items) {
271
+ const isFree = item.tier === "free";
272
+ if (isFree) free += 1;
273
+ // Only free is marked. Professional is the default, so marking it would
274
+ // put a badge on almost every row and say nothing.
275
+ const gate = isFree ? c.green(" free") : " ";
276
+ console.log(` ${item.slug.padEnd(width)}${gate} ${c.dim(item.tagline)}`);
277
+ }
278
+ if (free < index.items.length) {
279
+ console.log(
280
+ `\n ${c.dim("Unmarked shaders need the Professional plan for their source. Tuning is free on all of them.")}`,
281
+ );
282
+ }
283
+ console.log("");
284
+ }
285
+
286
+ async function init() {
287
+ const target = resolve(process.cwd(), "shadertown.config.ts");
288
+ if (await exists(target)) throw new Error("shadertown.config.ts already exists.");
289
+
290
+ await writeFile(
291
+ target,
292
+ `import { defineShadertownConfig } from "shadertown";
293
+
294
+ export default defineShadertownConfig({
295
+ outDir: "${DEFAULT_OUT}",
296
+ registry: "${DEFAULT_REGISTRY}",
297
+ // Name of the environment variable holding your key - never the key itself.
298
+ license: "SHADERTOWN_KEY",
299
+ });
300
+ `,
301
+ );
302
+ console.log(`\n ${c.green("add")} shadertown.config.ts\n`);
303
+ }
304
+
305
+ function relative(from, to) {
306
+ return to.startsWith(from) ? to.slice(from.length + 1) : to;
307
+ }
308
+
309
+ function help() {
310
+ console.log(`
311
+ ${c.bold("shadertown")} - vendor WebGPU shaders into your codebase
312
+
313
+ ${c.dim("Usage")}
314
+ npx shadertown <command> [options]
315
+
316
+ ${c.dim("Commands")}
317
+ login Connect this terminal to your shadertown account
318
+ logout Forget the stored token
319
+ whoami Show who this terminal is signed in as
320
+ add <slug...> Write a shader's WGSL and typed preset into your repo
321
+ list Print the catalogue
322
+ init Create shadertown.config.ts
323
+
324
+ ${c.dim("Options")}
325
+ --out <dir> Output directory ${c.dim(`(default: ${DEFAULT_OUT})`)}
326
+ --params <query> Tuned values from a detail page URL
327
+ --registry <url> Registry base URL ${c.dim(`(default: ${DEFAULT_REGISTRY})`)}
328
+ --licensee <name> Name to issue the LICENSE to
329
+ --force Overwrite existing files
330
+
331
+ ${c.dim("Examples")}
332
+ npx shadertown add aurora
333
+ npx shadertown add aurora --params "speed=0.42&exposure=1.6"
334
+ npx shadertown add voronoi tunnel --out app/shaders
335
+ `);
336
+ }
337
+
338
+ async function version() {
339
+ const pkg = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
340
+ console.log(pkg.version);
341
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "./cli.mjs";
3
+
4
+ run(process.argv.slice(2)).catch((error) => {
5
+ const message = error instanceof Error ? error.message : String(error);
6
+ console.error(`\n \u001b[31merror\u001b[0m ${message}\n`);
7
+ process.exit(1);
8
+ });
@@ -0,0 +1,29 @@
1
+ import type { ShaderName, ShaderParams } from "./registry.js";
2
+ import type { PlayMode, QualityOptions } from "./types.js";
3
+ /**
4
+ * A tuned shader, ready to hand to `<ShaderCanvas />` or `createShaderRenderer`.
5
+ * This object is the thing you actually author: the slider positions you
6
+ * settled on, in a form your editor can type-check.
7
+ */
8
+ export interface ShaderConfig<K extends ShaderName = ShaderName> {
9
+ readonly shader: K;
10
+ readonly params?: ShaderParams<K>;
11
+ readonly quality?: QualityOptions;
12
+ readonly play?: PlayMode;
13
+ /** Free-text note, kept so exported presets can explain themselves. */
14
+ readonly note?: string;
15
+ }
16
+ /** Identity at runtime; it exists so `params` is checked against `shader`. */
17
+ export declare function defineShader<const K extends ShaderName>(config: ShaderConfig<K>): ShaderConfig<K>;
18
+ export interface ShadertownConfig {
19
+ /** Where `shadertown add` writes vendored shaders. */
20
+ readonly outDir?: string;
21
+ /** Registry base URL. Point this at a fork to serve your own catalogue. */
22
+ readonly registry?: string;
23
+ /** License key, or the name of the env var holding it. */
24
+ readonly license?: string;
25
+ /** Named presets, so a project refers to `presets.hero` rather than a slug. */
26
+ readonly presets?: Readonly<Record<string, ShaderConfig>>;
27
+ }
28
+ export declare function defineShadertownConfig(config: ShadertownConfig): ShadertownConfig;
29
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAEjG;AAED,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC3D;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAEjF"}
package/dist/config.js ADDED
@@ -0,0 +1,8 @@
1
+ /** Identity at runtime; it exists so `params` is checked against `shader`. */
2
+ export function defineShader(config) {
3
+ return config;
4
+ }
5
+ export function defineShadertownConfig(config) {
6
+ return config;
7
+ }
8
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiBA,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAA6B,MAAuB;IAC9E,OAAO,MAAM,CAAC;AAChB,CAAC;AAaD,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type ShaderName, type ShaderParams } from "./registry.js";
2
+ /**
3
+ * Only the values that differ from the registry defaults. Exported snippets
4
+ * stay short, and a shader's defaults can improve later without silently
5
+ * changing anyone's pinned look.
6
+ */
7
+ export declare function diffParams<K extends ShaderName>(name: K, params: ShaderParams<K>): Record<string, number | string>;
8
+ /** A `shader.config.ts` module: the tuned preset, typed against the registry. */
9
+ export declare function toConfigSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
10
+ /** A drop-in React usage snippet for the current settings. */
11
+ export declare function toReactSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
12
+ /** The imperative form, for codebases that are not React. */
13
+ export declare function toVanillaSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
14
+ /** The complete, self-contained WGSL for this shader. */
15
+ export declare function toWgslSource<K extends ShaderName>(name: K): string;
16
+ export declare function toInstallCommand<K extends ShaderName>(name: K): string;
17
+ /** A paste-ready component wired with the tuned parameters. */
18
+ export declare function toExampleSource<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
19
+ /**
20
+ * Per-shader documentation, generated from the registry rather than written by
21
+ * hand — the control table cannot drift out of date with the shader.
22
+ */
23
+ export declare function toReadme<K extends ShaderName>(name: K, params: ShaderParams<K>): string;
24
+ export interface LicenceHolder {
25
+ readonly name?: string;
26
+ readonly order?: string;
27
+ }
28
+ /** The licence that ships with a purchased shader, issued to the buyer. */
29
+ export declare function toLicense<K extends ShaderName>(name: K, holder?: LicenceHolder): string;
30
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEnF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAC7C,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAQjC;AAgBD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAW7F;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAoB5F;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAkB9F;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAElE;AAED,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAEtE;AAOD,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAwB9F;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CA6FvF;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAE,aAAkB,GAAG,MAAM,CAwB3F"}