create-substrate 0.1.3 → 0.1.5

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 (39) hide show
  1. package/README.md +53 -0
  2. package/dist/index.js +1 -1
  3. package/dist/scaffold.d.ts.map +1 -1
  4. package/dist/scaffold.js +68 -4
  5. package/dist/scaffold.js.map +1 -1
  6. package/dist/surfaces/3d-scene.d.ts.map +1 -1
  7. package/dist/surfaces/3d-scene.js +414 -67
  8. package/dist/surfaces/3d-scene.js.map +1 -1
  9. package/dist/surfaces/animation.d.ts.map +1 -1
  10. package/dist/surfaces/animation.js +95 -103
  11. package/dist/surfaces/animation.js.map +1 -1
  12. package/dist/surfaces/blank.d.ts.map +1 -1
  13. package/dist/surfaces/blank.js +28 -16
  14. package/dist/surfaces/blank.js.map +1 -1
  15. package/dist/surfaces/canvas-2d.d.ts.map +1 -1
  16. package/dist/surfaces/canvas-2d.js +369 -92
  17. package/dist/surfaces/canvas-2d.js.map +1 -1
  18. package/dist/surfaces/data-vis.d.ts.map +1 -1
  19. package/dist/surfaces/data-vis.js +262 -98
  20. package/dist/surfaces/data-vis.js.map +1 -1
  21. package/dist/surfaces/image-gen.d.ts.map +1 -1
  22. package/dist/surfaces/image-gen.js +354 -92
  23. package/dist/surfaces/image-gen.js.map +1 -1
  24. package/dist/surfaces/node-editor.d.ts.map +1 -1
  25. package/dist/surfaces/node-editor.js +559 -114
  26. package/dist/surfaces/node-editor.js.map +1 -1
  27. package/package.json +4 -2
  28. package/skills/3d-scene/SKILL.md +6 -0
  29. package/skills/animation/SKILL.md +6 -0
  30. package/skills/canvas-2d/SKILL.md +7 -1
  31. package/skills/composing-panels/SKILL.md +14 -8
  32. package/skills/create-custom-tool/SKILL.md +6 -0
  33. package/skills/data-visualisation/SKILL.md +6 -0
  34. package/skills/image-generation/SKILL.md +6 -0
  35. package/skills/install-components/SKILL.md +199 -0
  36. package/skills/scaffold-playground/SKILL.md +12 -6
  37. package/skills/substrate-controls/SKILL.md +1 -3
  38. package/skills/theming/SKILL.md +6 -0
  39. package/skills/wire-interactions/SKILL.md +6 -0
@@ -3,16 +3,19 @@ export const imageGen = {
3
3
  "toolbar",
4
4
  "panel",
5
5
  "pane",
6
+ "action",
6
7
  "gallery",
7
8
  "text-area",
8
9
  "slider",
9
10
  "number-input",
10
11
  "progress-bar",
11
12
  "status-bar",
13
+ "empty-state",
12
14
  ],
13
15
  app: () => `import { useState } from "react"
14
16
  import {
15
17
  Toolbar,
18
+ ToolbarSeparator,
16
19
  ToolbarToggleGroup,
17
20
  ToolbarToggle,
18
21
  } from "@/components/substrate/toolbar"
@@ -21,167 +24,426 @@ import {
21
24
  Pane,
22
25
  PaneHeader,
23
26
  PaneLabel,
27
+ PaneAction,
24
28
  PaneContent,
25
29
  } from "@/components/substrate/pane"
26
- import { Gallery } from "@/components/substrate/gallery"
30
+ import { Action, ActionLabel, ActionControls } from "@/components/substrate/action"
31
+ import {
32
+ Gallery,
33
+ GalleryItem,
34
+ GalleryImage,
35
+ GalleryAction,
36
+ GalleryEmpty,
37
+ } from "@/components/substrate/gallery"
27
38
  import { TextArea } from "@/components/substrate/text-area"
28
39
  import { Slider } from "@/components/substrate/slider"
29
40
  import { NumberInput } from "@/components/substrate/number-input"
30
41
  import { ProgressBar } from "@/components/substrate/progress-bar"
31
- import { StatusBar, StatusBarSection, StatusBarItem } from "@/components/substrate/status-bar"
42
+ import {
43
+ StatusBar,
44
+ StatusBarSection,
45
+ StatusBarItem,
46
+ StatusBarSeparator,
47
+ } from "@/components/substrate/status-bar"
48
+ import {
49
+ EmptyState,
50
+ EmptyStateIcon,
51
+ EmptyStateTitle,
52
+ EmptyStateDescription,
53
+ } from "@/components/substrate/empty-state"
32
54
  import {
33
55
  RiSparklingLine,
34
56
  RiImageLine,
35
- RiSettings3Line,
57
+ RiShuffleLine,
58
+ RiDeleteBinLine,
36
59
  } from "@remixicon/react"
37
60
 
38
- interface Generation {
39
- id: string
61
+ type AspectRatio = "1:1" | "3:2" | "2:3"
62
+
63
+ interface Settings {
40
64
  prompt: string
41
- timestamp: number
42
- placeholder: string
65
+ steps: number
66
+ cfg: number
67
+ seed: number
68
+ aspect: AspectRatio
69
+ }
70
+
71
+ interface Generation extends Settings {
72
+ id: string
73
+ src: string
74
+ }
75
+
76
+ const ASPECT_SIZES: Record<AspectRatio, { width: number; height: number }> = {
77
+ "1:1": { width: 768, height: 768 },
78
+ "3:2": { width: 960, height: 640 },
79
+ "2:3": { width: 640, height: 960 },
80
+ }
81
+
82
+ const ASPECT_RATIOS: AspectRatio[] = ["1:1", "3:2", "2:3"]
83
+
84
+ const MAX_SEED = 999999
85
+
86
+ function isAspectRatio(value: string): value is AspectRatio {
87
+ return ASPECT_RATIOS.some((ratio) => ratio === value)
88
+ }
89
+
90
+ function hashString(text: string) {
91
+ let hash = 0
92
+ for (let i = 0; i < text.length; i++) {
93
+ hash = (hash * 31 + text.charCodeAt(i)) | 0
94
+ }
95
+ return hash
43
96
  }
44
97
 
45
- const PLACEHOLDER_COLOURS = [
46
- "from-indigo-500/20 to-purple-500/20",
47
- "from-emerald-500/20 to-cyan-500/20",
48
- "from-rose-500/20 to-orange-500/20",
49
- "from-blue-500/20 to-violet-500/20",
98
+ // Small deterministic PRNG so the same settings always give the same image
99
+ function createRandom(seed: number) {
100
+ let state = seed | 0
101
+ return () => {
102
+ state = (state + 0x6d2b79f5) | 0
103
+ let t = Math.imul(state ^ (state >>> 15), 1 | state)
104
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
105
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296
106
+ }
107
+ }
108
+
109
+ // Placeholder renderer: draws an abstract SVG from the settings and returns
110
+ // it as a data URL. Swap this for a call to your image model.
111
+ function renderPlaceholder({ prompt, steps, cfg, seed, aspect }: Settings) {
112
+ const { width, height } = ASPECT_SIZES[aspect]
113
+ const random = createRandom(seed + hashString(prompt))
114
+ const hue = Math.floor(random() * 360)
115
+ const saturation = Math.round(30 + cfg * 3)
116
+ const count = 3 + Math.round(steps / 8)
117
+
118
+ let shapes = ""
119
+ for (let i = 0; i < count; i++) {
120
+ const cx = Math.round(random() * width)
121
+ const cy = Math.round(random() * height)
122
+ const r = Math.round((0.08 + random() * 0.3) * Math.min(width, height))
123
+ const shapeHue = (hue + Math.round(random() * 120) - 60 + 360) % 360
124
+ const lightness = Math.round(40 + random() * 35)
125
+ const opacity = (0.25 + random() * 0.45).toFixed(2)
126
+ shapes += \`<circle cx="\${cx}" cy="\${cy}" r="\${r}" fill="hsl(\${shapeHue} \${saturation}% \${lightness}%)" opacity="\${opacity}"/>\`
127
+ }
128
+
129
+ const svg =
130
+ \`<svg xmlns="http://www.w3.org/2000/svg" width="\${width}" height="\${height}" viewBox="0 0 \${width} \${height}">\` +
131
+ \`<defs><linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">\` +
132
+ \`<stop offset="0" stop-color="hsl(\${hue} \${saturation}% 22%)"/>\` +
133
+ \`<stop offset="1" stop-color="hsl(\${(hue + 60) % 360} \${saturation}% 12%)"/>\` +
134
+ \`</linearGradient><filter id="blur"><feGaussianBlur stdDeviation="24"/></filter></defs>\` +
135
+ \`<rect width="\${width}" height="\${height}" fill="url(#bg)"/>\` +
136
+ \`<g filter="url(#blur)">\${shapes}</g></svg>\`
137
+
138
+ return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg)
139
+ }
140
+
141
+ function createGeneration(id: string, settings: Settings): Generation {
142
+ return { ...settings, id, src: renderPlaceholder(settings) }
143
+ }
144
+
145
+ function randomSeed() {
146
+ return Math.floor(Math.random() * (MAX_SEED + 1))
147
+ }
148
+
149
+ const INITIAL_GENERATIONS: Generation[] = [
150
+ createGeneration("sample-1", {
151
+ prompt: "Aurora over a frozen lake, long exposure",
152
+ steps: 40,
153
+ cfg: 8,
154
+ seed: 1204,
155
+ aspect: "3:2",
156
+ }),
157
+ createGeneration("sample-2", {
158
+ prompt: "Soft studio portrait of a ceramic vase",
159
+ steps: 24,
160
+ cfg: 5,
161
+ seed: 77,
162
+ aspect: "1:1",
163
+ }),
164
+ createGeneration("sample-3", {
165
+ prompt: "Neon city street in the rain at night",
166
+ steps: 60,
167
+ cfg: 12,
168
+ seed: 5150,
169
+ aspect: "2:3",
170
+ }),
50
171
  ]
51
172
 
173
+ const TOOLBAR_BUTTON =
174
+ "inline-flex h-7 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-medium outline-none transition-all hover:bg-muted hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50"
175
+
52
176
  export default function App() {
53
- const [prompt, setPrompt] = useState("")
177
+ const [prompt, setPrompt] = useState("Misty mountain valley at sunrise")
54
178
  const [steps, setSteps] = useState(30)
55
179
  const [cfg, setCfg] = useState(7)
56
180
  const [seed, setSeed] = useState(-1)
181
+ const [aspect, setAspect] = useState<AspectRatio>("1:1")
57
182
  const [generating, setGenerating] = useState(false)
58
183
  const [progress, setProgress] = useState(0)
59
- const [generations, setGenerations] = useState<Generation[]>([])
60
- const [selectedId, setSelectedId] = useState<string | null>(null)
184
+ const [generations, setGenerations] = useState<Generation[]>(INITIAL_GENERATIONS)
185
+ const [selectedId, setSelectedId] = useState<string | null>(
186
+ INITIAL_GENERATIONS[0]?.id ?? null,
187
+ )
188
+
189
+ const canGenerate = !generating && prompt.trim().length > 0
190
+ const selected = generations.find((g) => g.id === selectedId)
61
191
 
62
192
  async function handleGenerate() {
63
- if (!prompt.trim()) return
193
+ if (!canGenerate) return
194
+ const settings: Settings = {
195
+ prompt: prompt.trim(),
196
+ steps,
197
+ cfg,
198
+ seed: seed < 0 ? randomSeed() : seed,
199
+ aspect,
200
+ }
201
+
64
202
  setGenerating(true)
65
203
  setProgress(0)
66
204
 
67
- // Simulate generation progress
68
- for (let i = 0; i <= 100; i += 10) {
69
- await new Promise((r) => setTimeout(r, 200))
70
- setProgress(i)
205
+ // Simulated progress. Replace with your model's progress events.
206
+ for (let step = 1; step <= 10; step++) {
207
+ await new Promise((resolve) => setTimeout(resolve, 120))
208
+ setProgress(step * 10)
71
209
  }
72
210
 
73
- const gen: Generation = {
74
- id: crypto.randomUUID(),
75
- prompt: prompt.trim(),
76
- timestamp: Date.now(),
77
- placeholder: PLACEHOLDER_COLOURS[generations.length % PLACEHOLDER_COLOURS.length],
78
- }
79
- setGenerations((prev) => [gen, ...prev])
80
- setSelectedId(gen.id)
211
+ const generation = createGeneration(crypto.randomUUID(), settings)
212
+ setGenerations((prev) => [generation, ...prev])
213
+ setSelectedId(generation.id)
81
214
  setGenerating(false)
82
215
  setProgress(0)
83
216
  }
84
217
 
85
- const selected = generations.find((g) => g.id === selectedId)
218
+ function handleRemove(id: string) {
219
+ const remaining = generations.filter((g) => g.id !== id)
220
+ setGenerations(remaining)
221
+ if (selectedId === id) setSelectedId(remaining[0]?.id ?? null)
222
+ }
223
+
224
+ function handleClear() {
225
+ setGenerations([])
226
+ setSelectedId(null)
227
+ }
228
+
229
+ // Load a previous result's settings back into the controls
230
+ function handleSelect(generation: Generation) {
231
+ setSelectedId(generation.id)
232
+ setPrompt(generation.prompt)
233
+ setSteps(generation.steps)
234
+ setCfg(generation.cfg)
235
+ setSeed(generation.seed)
236
+ setAspect(generation.aspect)
237
+ }
86
238
 
87
239
  return (
88
240
  <div className="flex h-screen flex-col bg-background text-foreground">
89
- <div className="relative flex flex-1 overflow-hidden">
90
- <Panel position="left">
241
+ <div className="flex min-h-0 flex-1">
242
+ <Panel position="left" className="shrink-0">
91
243
  <Pane>
92
244
  <PaneHeader>
93
245
  <PaneLabel>Prompt</PaneLabel>
94
246
  </PaneHeader>
95
- <PaneContent>
247
+ <PaneContent className="space-y-2">
96
248
  <TextArea
97
249
  value={prompt}
98
250
  onChange={(e) => setPrompt(e.target.value)}
251
+ onKeyDown={(e) => {
252
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
253
+ e.preventDefault()
254
+ void handleGenerate()
255
+ }
256
+ }}
99
257
  placeholder="Describe the image you want to generate..."
100
- rows={4}
258
+ minRows={4}
259
+ aria-label="Prompt"
101
260
  />
261
+ <button
262
+ type="button"
263
+ onClick={() => void handleGenerate()}
264
+ disabled={!canGenerate}
265
+ className="flex h-7 w-full items-center justify-center gap-1.5 rounded-md bg-primary text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50"
266
+ >
267
+ <RiSparklingLine className="size-3.5" />
268
+ {generating ? "Generating..." : "Generate"}
269
+ </button>
270
+ {generating && <ProgressBar value={progress} aria-label="Generation progress" />}
102
271
  </PaneContent>
103
272
  </Pane>
104
273
  <Pane>
105
274
  <PaneHeader>
106
275
  <PaneLabel>Parameters</PaneLabel>
276
+ <PaneAction
277
+ type="button"
278
+ title="Random seed"
279
+ aria-label="Random seed"
280
+ onClick={() => setSeed(randomSeed())}
281
+ >
282
+ <RiShuffleLine />
283
+ </PaneAction>
107
284
  </PaneHeader>
108
- <PaneContent className="space-y-3">
109
- <Slider
110
- label="Steps"
111
- min={1}
112
- max={100}
113
- value={[steps]}
114
- onValueChange={([v]) => setSteps(v)}
115
- />
116
- <Slider
117
- label="CFG scale"
118
- min={1}
119
- max={20}
120
- step={0.5}
121
- value={[cfg]}
122
- onValueChange={([v]) => setCfg(v)}
123
- />
124
- <NumberInput label="Seed" value={seed} onChange={setSeed} />
285
+ <PaneContent className="space-y-1">
286
+ <Action>
287
+ <ActionLabel>Steps</ActionLabel>
288
+ <ActionControls>
289
+ <Slider
290
+ aria-label="Steps"
291
+ min={1}
292
+ max={100}
293
+ value={[steps]}
294
+ onValueChange={(value) => setSteps(value[0] ?? steps)}
295
+ />
296
+ <span className="w-8 text-right text-xs tabular-nums">{steps}</span>
297
+ </ActionControls>
298
+ </Action>
299
+ <Action>
300
+ <ActionLabel>CFG scale</ActionLabel>
301
+ <ActionControls>
302
+ <Slider
303
+ aria-label="CFG scale"
304
+ min={1}
305
+ max={20}
306
+ step={0.5}
307
+ value={[cfg]}
308
+ onValueChange={(value) => setCfg(value[0] ?? cfg)}
309
+ />
310
+ <span className="w-8 text-right text-xs tabular-nums">{cfg}</span>
311
+ </ActionControls>
312
+ </Action>
313
+ <Action>
314
+ <ActionLabel>Seed</ActionLabel>
315
+ <ActionControls>
316
+ <NumberInput
317
+ className="flex-1"
318
+ aria-label="Seed"
319
+ value={seed}
320
+ onChange={(value) => setSeed(Math.round(value))}
321
+ min={-1}
322
+ max={MAX_SEED}
323
+ precision={0}
324
+ />
325
+ </ActionControls>
326
+ </Action>
327
+ <p className="pt-1 text-[11px] text-muted-foreground">
328
+ A seed of -1 picks a random seed for each generation.
329
+ </p>
125
330
  </PaneContent>
126
331
  </Pane>
127
332
  </Panel>
128
333
 
129
334
  {/* Preview area */}
130
- <div className="flex flex-1 flex-col bg-canvas">
131
- <div className="flex flex-1 items-center justify-center p-8">
132
- {selected ? (
133
- <div className={\`flex aspect-square max-h-full w-full max-w-lg items-center justify-center rounded-lg bg-gradient-to-br \${selected.placeholder}\`}>
134
- <RiImageLine className="size-16 text-muted-foreground/30" />
135
- </div>
136
- ) : (
137
- <div className="text-center text-muted-foreground">
138
- <RiSparklingLine className="mx-auto mb-3 size-12 opacity-30" />
139
- <p className="text-sm">Enter a prompt and generate</p>
140
- </div>
141
- )}
142
- </div>
143
-
144
- {generating && (
145
- <div className="px-8 pb-4">
146
- <ProgressBar value={progress} max={100} />
147
- </div>
148
- )}
149
-
150
- {/* Gallery history */}
151
- {generations.length > 0 && (
152
- <div className="border-t border-border p-3">
153
- <Gallery
154
- items={generations.map((g) => ({
155
- id: g.id,
156
- label: g.prompt.slice(0, 40),
157
- }))}
158
- selectedId={selectedId}
159
- onSelect={setSelectedId}
160
- />
161
- </div>
335
+ <div className="flex min-w-0 flex-1 items-center justify-center bg-canvas p-8 pb-28">
336
+ {selected ? (
337
+ <img
338
+ src={selected.src}
339
+ alt={selected.prompt}
340
+ className="max-h-full max-w-full rounded-lg object-contain shadow-lg"
341
+ />
342
+ ) : (
343
+ <EmptyState>
344
+ <EmptyStateIcon>
345
+ <RiImageLine />
346
+ </EmptyStateIcon>
347
+ <EmptyStateTitle>No image selected</EmptyStateTitle>
348
+ <EmptyStateDescription>
349
+ Enter a prompt and press Generate to create one.
350
+ </EmptyStateDescription>
351
+ </EmptyState>
162
352
  )}
163
353
  </div>
354
+
355
+ <Panel position="right" className="shrink-0">
356
+ <Pane>
357
+ <PaneHeader>
358
+ <PaneLabel>History</PaneLabel>
359
+ <PaneAction
360
+ type="button"
361
+ title="Clear history"
362
+ aria-label="Clear history"
363
+ onClick={handleClear}
364
+ disabled={generations.length === 0}
365
+ >
366
+ <RiDeleteBinLine />
367
+ </PaneAction>
368
+ </PaneHeader>
369
+ <PaneContent>
370
+ <Gallery columns={2}>
371
+ {generations.length === 0 && <GalleryEmpty>No generations yet</GalleryEmpty>}
372
+ {generations.map((generation) => (
373
+ <GalleryItem
374
+ key={generation.id}
375
+ selected={generation.id === selectedId}
376
+ onSelect={() => handleSelect(generation)}
377
+ title={generation.prompt}
378
+ >
379
+ <GalleryImage src={generation.src} alt={generation.prompt} />
380
+ <GalleryAction
381
+ type="button"
382
+ aria-label="Remove"
383
+ onClick={(e) => {
384
+ e.stopPropagation()
385
+ handleRemove(generation.id)
386
+ }}
387
+ >
388
+ <RiDeleteBinLine className="size-3.5" />
389
+ </GalleryAction>
390
+ </GalleryItem>
391
+ ))}
392
+ </Gallery>
393
+ </PaneContent>
394
+ </Pane>
395
+ </Panel>
164
396
  </div>
165
397
 
166
398
  <Toolbar>
167
- <ToolbarToggle
168
- value="generate"
169
- tooltip="Generate"
170
- shortcut="⌘↵"
171
- onPressedChange={handleGenerate}
172
- disabled={generating || !prompt.trim()}
399
+ <ToolbarToggleGroup
400
+ value={aspect}
401
+ onValueChange={(value) => {
402
+ if (isAspectRatio(value)) setAspect(value)
403
+ }}
404
+ >
405
+ {ASPECT_RATIOS.map((ratio) => (
406
+ <ToolbarToggle key={ratio} value={ratio} tooltip={"Aspect ratio " + ratio}>
407
+ {ratio}
408
+ </ToolbarToggle>
409
+ ))}
410
+ </ToolbarToggleGroup>
411
+ <ToolbarSeparator />
412
+ <button
413
+ type="button"
414
+ className={TOOLBAR_BUTTON}
415
+ onClick={() => void handleGenerate()}
416
+ disabled={!canGenerate}
417
+ title="Generate (Ctrl/Cmd + Enter in the prompt)"
173
418
  >
174
419
  <RiSparklingLine className="size-4" />
175
- </ToolbarToggle>
420
+ Generate
421
+ </button>
176
422
  </Toolbar>
177
423
 
178
424
  <StatusBar>
179
- <StatusBarSection>
425
+ <StatusBarSection align="left">
180
426
  <StatusBarItem>Generations: {generations.length}</StatusBarItem>
181
- {generating && <StatusBarItem>Progress: {progress}%</StatusBarItem>}
427
+ {generating && (
428
+ <>
429
+ <StatusBarSeparator />
430
+ <StatusBarItem>Progress: {progress}%</StatusBarItem>
431
+ </>
432
+ )}
182
433
  </StatusBarSection>
183
- <StatusBarSection>
434
+ <StatusBarSection align="right">
435
+ {selected && (
436
+ <>
437
+ <StatusBarItem>
438
+ {ASPECT_SIZES[selected.aspect].width} × {ASPECT_SIZES[selected.aspect].height}
439
+ </StatusBarItem>
440
+ <StatusBarSeparator />
441
+ <StatusBarItem>Seed: {selected.seed}</StatusBarItem>
442
+ <StatusBarSeparator />
443
+ </>
444
+ )}
184
445
  <StatusBarItem>Steps: {steps}</StatusBarItem>
446
+ <StatusBarSeparator />
185
447
  <StatusBarItem>CFG: {cfg}</StatusBarItem>
186
448
  </StatusBarSection>
187
449
  </StatusBar>
@@ -1 +1 @@
1
- {"version":3,"file":"image-gen.js","sourceRoot":"","sources":["../../src/surfaces/image-gen.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,UAAU,EAAE;QACV,SAAS;QACT,OAAO;QACP,MAAM;QACN,SAAS;QACT,WAAW;QACX,QAAQ;QACR,cAAc;QACd,cAAc;QACd,YAAY;KACb;IACD,GAAG,EAAE,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkLZ;CACA,CAAA"}
1
+ {"version":3,"file":"image-gen.js","sourceRoot":"","sources":["../../src/surfaces/image-gen.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,UAAU,EAAE;QACV,SAAS;QACT,OAAO;QACP,MAAM;QACN,QAAQ;QACR,SAAS;QACT,WAAW;QACX,QAAQ;QACR,cAAc;QACd,cAAc;QACd,YAAY;QACZ,aAAa;KACd;IACD,GAAG,EAAE,GAAG,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsbZ;CACA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"node-editor.d.ts","sourceRoot":"","sources":["../../src/surfaces/node-editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,eAAO,MAAM,UAAU,EAAE,aAqNxB,CAAA"}
1
+ {"version":3,"file":"node-editor.d.ts","sourceRoot":"","sources":["../../src/surfaces/node-editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,eAAO,MAAM,UAAU,EAAE,aAkpBxB,CAAA"}