@substrate-kit/cli 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/registry.json ADDED
@@ -0,0 +1,1939 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry.json",
3
+ "name": "substrate",
4
+ "homepage": "https://substrate.georgedrury.co.uk",
5
+ "items": [
6
+ {
7
+ "name": "types",
8
+ "type": "registry:lib",
9
+ "title": "Types",
10
+ "description": "Core TypeScript type definitions for the design canvas — element types, camera, tools, panels, hit testing, and interaction state.",
11
+ "author": "George Drury <info@georgedrury.co.uk>",
12
+ "categories": [
13
+ "substrate",
14
+ "lib"
15
+ ],
16
+ "meta": {
17
+ "lineage": [
18
+ {
19
+ "name": "Substrate"
20
+ }
21
+ ]
22
+ },
23
+ "files": [
24
+ {
25
+ "path": "registry/substrate/types.ts",
26
+ "type": "registry:lib",
27
+ "target": "lib/substrate/types.ts"
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "name": "math",
33
+ "type": "registry:lib",
34
+ "title": "Math",
35
+ "description": "Geometry helpers — rotate point, bounds checking, ellipse hit test, screen/world coordinate conversion, normalize bounds, distance, and clamping.",
36
+ "author": "George Drury <info@georgedrury.co.uk>",
37
+ "categories": [
38
+ "substrate",
39
+ "lib"
40
+ ],
41
+ "registryDependencies": [
42
+ "https://substrate.georgedrury.co.uk/r/types"
43
+ ],
44
+ "meta": {
45
+ "lineage": [
46
+ {
47
+ "name": "Substrate"
48
+ }
49
+ ]
50
+ },
51
+ "files": [
52
+ {
53
+ "path": "registry/substrate/lib/math.ts",
54
+ "type": "registry:lib",
55
+ "target": "lib/substrate/math.ts"
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ "name": "id",
61
+ "type": "registry:lib",
62
+ "title": "ID",
63
+ "description": "ID generation utility using crypto.randomUUID.",
64
+ "author": "George Drury <info@georgedrury.co.uk>",
65
+ "categories": [
66
+ "substrate",
67
+ "lib"
68
+ ],
69
+ "meta": {
70
+ "lineage": [
71
+ {
72
+ "name": "Substrate"
73
+ }
74
+ ]
75
+ },
76
+ "files": [
77
+ {
78
+ "path": "registry/substrate/lib/id.ts",
79
+ "type": "registry:lib",
80
+ "target": "lib/substrate/id.ts"
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ "name": "color",
86
+ "type": "registry:lib",
87
+ "title": "Color",
88
+ "description": "OKLCh color parsing and manipulation utilities — parse, serialize, and adjust lightness.",
89
+ "author": "George Drury <info@georgedrury.co.uk>",
90
+ "categories": [
91
+ "substrate",
92
+ "lib"
93
+ ],
94
+ "meta": {
95
+ "lineage": [
96
+ {
97
+ "name": "Substrate"
98
+ }
99
+ ]
100
+ },
101
+ "files": [
102
+ {
103
+ "path": "registry/substrate/lib/color.ts",
104
+ "type": "registry:lib",
105
+ "target": "lib/substrate/color.ts"
106
+ }
107
+ ]
108
+ },
109
+ {
110
+ "name": "document-store",
111
+ "type": "registry:lib",
112
+ "title": "Document Store",
113
+ "description": "Zustand store for canvas document state — elements, camera, selection, and undo/redo history with colocated actions.",
114
+ "author": "George Drury <info@georgedrury.co.uk>",
115
+ "categories": [
116
+ "substrate",
117
+ "store"
118
+ ],
119
+ "dependencies": [
120
+ "zustand"
121
+ ],
122
+ "registryDependencies": [
123
+ "https://substrate.georgedrury.co.uk/r/types"
124
+ ],
125
+ "meta": {
126
+ "lineage": [
127
+ {
128
+ "name": "Substrate"
129
+ }
130
+ ]
131
+ },
132
+ "files": [
133
+ {
134
+ "path": "registry/substrate/stores/document-store.ts",
135
+ "type": "registry:lib",
136
+ "target": "stores/substrate/document-store.ts"
137
+ }
138
+ ]
139
+ },
140
+ {
141
+ "name": "tool-store",
142
+ "type": "registry:lib",
143
+ "title": "Tool Store",
144
+ "description": "Zustand store for active tool state with temporary tool support (e.g. hold Space for hand tool).",
145
+ "author": "George Drury <info@georgedrury.co.uk>",
146
+ "categories": [
147
+ "substrate",
148
+ "store"
149
+ ],
150
+ "dependencies": [
151
+ "zustand"
152
+ ],
153
+ "registryDependencies": [
154
+ "https://substrate.georgedrury.co.uk/r/types"
155
+ ],
156
+ "meta": {
157
+ "lineage": [
158
+ {
159
+ "name": "Substrate"
160
+ }
161
+ ]
162
+ },
163
+ "files": [
164
+ {
165
+ "path": "registry/substrate/stores/tool-store.ts",
166
+ "type": "registry:lib",
167
+ "target": "stores/substrate/tool-store.ts"
168
+ }
169
+ ]
170
+ },
171
+ {
172
+ "name": "panel-store",
173
+ "type": "registry:lib",
174
+ "title": "Panel Store",
175
+ "description": "Zustand store for panel visibility — left panel, right panel, and open/collapse state.",
176
+ "author": "George Drury <info@georgedrury.co.uk>",
177
+ "categories": [
178
+ "substrate",
179
+ "store"
180
+ ],
181
+ "dependencies": [
182
+ "zustand"
183
+ ],
184
+ "registryDependencies": [
185
+ "https://substrate.georgedrury.co.uk/r/types"
186
+ ],
187
+ "meta": {
188
+ "lineage": [
189
+ {
190
+ "name": "Substrate"
191
+ }
192
+ ]
193
+ },
194
+ "files": [
195
+ {
196
+ "path": "registry/substrate/stores/panel-store.ts",
197
+ "type": "registry:lib",
198
+ "target": "stores/substrate/panel-store.ts"
199
+ }
200
+ ]
201
+ },
202
+ {
203
+ "name": "element-factory",
204
+ "type": "registry:lib",
205
+ "title": "Element Factory",
206
+ "description": "Factory functions for creating design elements — rectangle, ellipse, text, line, and frame with sensible defaults.",
207
+ "author": "George Drury <info@georgedrury.co.uk>",
208
+ "categories": [
209
+ "substrate",
210
+ "canvas"
211
+ ],
212
+ "registryDependencies": [
213
+ "https://substrate.georgedrury.co.uk/r/types",
214
+ "https://substrate.georgedrury.co.uk/r/id"
215
+ ],
216
+ "meta": {
217
+ "lineage": [
218
+ {
219
+ "name": "Substrate"
220
+ }
221
+ ]
222
+ },
223
+ "files": [
224
+ {
225
+ "path": "registry/substrate/lib/element-factory.ts",
226
+ "type": "registry:lib",
227
+ "target": "lib/substrate/element-factory.ts"
228
+ }
229
+ ]
230
+ },
231
+ {
232
+ "name": "renderer",
233
+ "type": "registry:lib",
234
+ "title": "Renderer",
235
+ "description": "Pure Canvas 2D rendering functions — grid, elements (rectangle, ellipse, text, line, frame), selection boxes, resize handles, creation preview, and marquee.",
236
+ "author": "George Drury <info@georgedrury.co.uk>",
237
+ "categories": [
238
+ "substrate",
239
+ "canvas"
240
+ ],
241
+ "registryDependencies": [
242
+ "https://substrate.georgedrury.co.uk/r/types"
243
+ ],
244
+ "meta": {
245
+ "lineage": [
246
+ {
247
+ "name": "Substrate"
248
+ }
249
+ ]
250
+ },
251
+ "files": [
252
+ {
253
+ "path": "registry/substrate/canvas/renderer.ts",
254
+ "type": "registry:lib",
255
+ "target": "components/substrate/renderer.ts"
256
+ }
257
+ ]
258
+ },
259
+ {
260
+ "name": "hit-test",
261
+ "type": "registry:lib",
262
+ "title": "Hit Test",
263
+ "description": "Pure geometry functions for point-in-element testing, element-at-point lookup, marquee selection, and resize handle detection.",
264
+ "author": "George Drury <info@georgedrury.co.uk>",
265
+ "categories": [
266
+ "substrate",
267
+ "canvas"
268
+ ],
269
+ "registryDependencies": [
270
+ "https://substrate.georgedrury.co.uk/r/types",
271
+ "https://substrate.georgedrury.co.uk/r/math"
272
+ ],
273
+ "meta": {
274
+ "lineage": [
275
+ {
276
+ "name": "Substrate"
277
+ }
278
+ ]
279
+ },
280
+ "files": [
281
+ {
282
+ "path": "registry/substrate/canvas/hit-test.ts",
283
+ "type": "registry:lib",
284
+ "target": "components/substrate/hit-test.ts"
285
+ }
286
+ ]
287
+ },
288
+ {
289
+ "name": "use-canvas-drag",
290
+ "type": "registry:hook",
291
+ "title": "useCanvasDrag",
292
+ "description": "Hook for managing drag state machine — tracks drag type (create, move, resize, marquee, pan), start/current positions, and element snapshots.",
293
+ "author": "George Drury <info@georgedrury.co.uk>",
294
+ "categories": [
295
+ "substrate",
296
+ "canvas"
297
+ ],
298
+ "registryDependencies": [
299
+ "https://substrate.georgedrury.co.uk/r/types"
300
+ ],
301
+ "meta": {
302
+ "lineage": [
303
+ {
304
+ "name": "Substrate"
305
+ }
306
+ ]
307
+ },
308
+ "files": [
309
+ {
310
+ "path": "registry/substrate/hooks/use-canvas-drag.ts",
311
+ "type": "registry:hook",
312
+ "target": "hooks/substrate/use-canvas-drag.ts"
313
+ }
314
+ ]
315
+ },
316
+ {
317
+ "name": "use-canvas-transform",
318
+ "type": "registry:hook",
319
+ "title": "useCanvasTransform",
320
+ "description": "Hook for screen/world coordinate conversion, pan, zoom-to-point, zoom in/out, and reset zoom.",
321
+ "author": "George Drury <info@georgedrury.co.uk>",
322
+ "categories": [
323
+ "substrate",
324
+ "canvas"
325
+ ],
326
+ "registryDependencies": [
327
+ "https://substrate.georgedrury.co.uk/r/types",
328
+ "https://substrate.georgedrury.co.uk/r/math",
329
+ "https://substrate.georgedrury.co.uk/r/document-store"
330
+ ],
331
+ "meta": {
332
+ "lineage": [
333
+ {
334
+ "name": "Substrate"
335
+ }
336
+ ]
337
+ },
338
+ "files": [
339
+ {
340
+ "path": "registry/substrate/hooks/use-canvas-transform.ts",
341
+ "type": "registry:hook",
342
+ "target": "hooks/substrate/use-canvas-transform.ts"
343
+ }
344
+ ]
345
+ },
346
+ {
347
+ "name": "use-hit-test",
348
+ "type": "registry:hook",
349
+ "title": "useHitTest",
350
+ "description": "Hook wrapping hit-test functions with canvas state — get element or resize handle at screen point.",
351
+ "author": "George Drury <info@georgedrury.co.uk>",
352
+ "categories": [
353
+ "substrate",
354
+ "canvas"
355
+ ],
356
+ "registryDependencies": [
357
+ "https://substrate.georgedrury.co.uk/r/types",
358
+ "https://substrate.georgedrury.co.uk/r/math",
359
+ "https://substrate.georgedrury.co.uk/r/document-store",
360
+ "https://substrate.georgedrury.co.uk/r/hit-test",
361
+ "https://substrate.georgedrury.co.uk/r/use-canvas-transform"
362
+ ],
363
+ "meta": {
364
+ "lineage": [
365
+ {
366
+ "name": "Substrate"
367
+ }
368
+ ]
369
+ },
370
+ "files": [
371
+ {
372
+ "path": "registry/substrate/hooks/use-hit-test.ts",
373
+ "type": "registry:hook",
374
+ "target": "hooks/substrate/use-hit-test.ts"
375
+ }
376
+ ]
377
+ },
378
+ {
379
+ "name": "use-canvas-renderer",
380
+ "type": "registry:hook",
381
+ "title": "useCanvasRenderer",
382
+ "description": "Hook for the requestAnimationFrame render loop — dirty-flag optimization, DPR-aware canvas sizing, and full render pipeline (grid, elements, selection UI, creation preview, marquee).",
383
+ "author": "George Drury <info@georgedrury.co.uk>",
384
+ "categories": [
385
+ "substrate",
386
+ "canvas"
387
+ ],
388
+ "registryDependencies": [
389
+ "https://substrate.georgedrury.co.uk/r/types",
390
+ "https://substrate.georgedrury.co.uk/r/math",
391
+ "https://substrate.georgedrury.co.uk/r/document-store",
392
+ "https://substrate.georgedrury.co.uk/r/tool-store",
393
+ "https://substrate.georgedrury.co.uk/r/renderer"
394
+ ],
395
+ "meta": {
396
+ "lineage": [
397
+ {
398
+ "name": "Substrate"
399
+ }
400
+ ]
401
+ },
402
+ "files": [
403
+ {
404
+ "path": "registry/substrate/hooks/use-canvas-renderer.ts",
405
+ "type": "registry:hook",
406
+ "target": "hooks/substrate/use-canvas-renderer.ts"
407
+ }
408
+ ]
409
+ },
410
+ {
411
+ "name": "use-canvas-interaction",
412
+ "type": "registry:hook",
413
+ "title": "useCanvasInteraction",
414
+ "description": "Hook for pointer event handling — state machine for idle, panning, creating, moving, resizing, and marquee selecting. Handles element creation, selection, and drag operations.",
415
+ "author": "George Drury <info@georgedrury.co.uk>",
416
+ "categories": [
417
+ "substrate",
418
+ "canvas"
419
+ ],
420
+ "registryDependencies": [
421
+ "https://substrate.georgedrury.co.uk/r/types",
422
+ "https://substrate.georgedrury.co.uk/r/math",
423
+ "https://substrate.georgedrury.co.uk/r/document-store",
424
+ "https://substrate.georgedrury.co.uk/r/tool-store",
425
+ "https://substrate.georgedrury.co.uk/r/element-factory",
426
+ "https://substrate.georgedrury.co.uk/r/hit-test",
427
+ "https://substrate.georgedrury.co.uk/r/use-canvas-transform",
428
+ "https://substrate.georgedrury.co.uk/r/use-hit-test",
429
+ "https://substrate.georgedrury.co.uk/r/use-canvas-drag"
430
+ ],
431
+ "meta": {
432
+ "lineage": [
433
+ {
434
+ "name": "Substrate"
435
+ }
436
+ ]
437
+ },
438
+ "files": [
439
+ {
440
+ "path": "registry/substrate/hooks/use-canvas-interaction.ts",
441
+ "type": "registry:hook",
442
+ "target": "hooks/substrate/use-canvas-interaction.ts"
443
+ }
444
+ ]
445
+ },
446
+ {
447
+ "name": "use-keyboard-shortcuts",
448
+ "type": "registry:hook",
449
+ "title": "useKeyboardShortcuts",
450
+ "description": "Hook for global keyboard shortcuts — tool switching (V/R/O/T/F), delete, undo/redo, select all, duplicate, zoom, and temporary hand tool (Space hold).",
451
+ "author": "George Drury <info@georgedrury.co.uk>",
452
+ "categories": [
453
+ "substrate",
454
+ "canvas"
455
+ ],
456
+ "registryDependencies": [
457
+ "https://substrate.georgedrury.co.uk/r/types",
458
+ "https://substrate.georgedrury.co.uk/r/id",
459
+ "https://substrate.georgedrury.co.uk/r/document-store",
460
+ "https://substrate.georgedrury.co.uk/r/tool-store",
461
+ "https://substrate.georgedrury.co.uk/r/use-canvas-transform"
462
+ ],
463
+ "meta": {
464
+ "lineage": [
465
+ {
466
+ "name": "Substrate"
467
+ }
468
+ ]
469
+ },
470
+ "files": [
471
+ {
472
+ "path": "registry/substrate/hooks/use-keyboard-shortcuts.ts",
473
+ "type": "registry:hook",
474
+ "target": "hooks/substrate/use-keyboard-shortcuts.ts"
475
+ }
476
+ ]
477
+ },
478
+ {
479
+ "name": "design-canvas",
480
+ "type": "registry:ui",
481
+ "title": "Design Canvas",
482
+ "description": "The main canvas component — renders a full-size HTML5 Canvas element with cursor management, pointer events, and keyboard shortcuts wired up.",
483
+ "author": "George Drury <info@georgedrury.co.uk>",
484
+ "categories": [
485
+ "substrate",
486
+ "canvas"
487
+ ],
488
+ "registryDependencies": [
489
+ "https://substrate.georgedrury.co.uk/r/tool-store",
490
+ "https://substrate.georgedrury.co.uk/r/use-canvas-renderer",
491
+ "https://substrate.georgedrury.co.uk/r/use-canvas-interaction",
492
+ "https://substrate.georgedrury.co.uk/r/use-keyboard-shortcuts"
493
+ ],
494
+ "cssVars": {
495
+ "theme": {
496
+ "color-canvas": "var(--canvas, var(--color-background))",
497
+ "color-canvas-foreground": "var(--canvas-foreground, var(--color-foreground-muted))"
498
+ },
499
+ "light": {
500
+ "canvas": "oklch(.97 0.0 0)",
501
+ "canvas-foreground": "oklch(0.556 0 0)"
502
+ },
503
+ "dark": {
504
+ "canvas": "oklch(17.764% 0.00002 271.152)",
505
+ "canvas-foreground": "oklch(0.708 0 0)"
506
+ }
507
+ },
508
+ "meta": {
509
+ "example": "<DesignCanvas />",
510
+ "lineage": [
511
+ {
512
+ "name": "Substrate"
513
+ }
514
+ ]
515
+ },
516
+ "files": [
517
+ {
518
+ "path": "registry/substrate/canvas/design-canvas.tsx",
519
+ "type": "registry:ui",
520
+ "target": "components/substrate/design-canvas.tsx"
521
+ }
522
+ ]
523
+ },
524
+ {
525
+ "name": "toolbar",
526
+ "type": "registry:ui",
527
+ "title": "Toolbar",
528
+ "description": "Floating toolbar with toggle groups, toggle buttons with tooltips, separators, and dropdown menus for tool variant selection. Built directly on Radix primitives.",
529
+ "author": "George Drury <info@georgedrury.co.uk>",
530
+ "categories": [
531
+ "substrate",
532
+ "ui"
533
+ ],
534
+ "dependencies": [
535
+ "radix-ui",
536
+ "@remixicon/react"
537
+ ],
538
+ "meta": {
539
+ "example": "<Toolbar><ToolbarToggleGroup value={tool} onValueChange={setTool}><ToolbarToggle value=\"select\" tooltip=\"Select\" shortcut=\"V\"><CursorIcon /></ToolbarToggle></ToolbarToggleGroup></Toolbar>",
540
+ "lineage": [
541
+ {
542
+ "name": "Radix"
543
+ },
544
+ {
545
+ "name": "Substrate"
546
+ }
547
+ ]
548
+ },
549
+ "files": [
550
+ {
551
+ "path": "registry/substrate/components/toolbar.tsx",
552
+ "type": "registry:ui",
553
+ "target": "components/substrate/toolbar.tsx"
554
+ }
555
+ ]
556
+ },
557
+ {
558
+ "name": "panel",
559
+ "type": "registry:ui",
560
+ "title": "Panel",
561
+ "description": "Side panel container with position (left/right), variant (tool/default), border, and scroll area. Used for layers, properties, and other side panels.",
562
+ "author": "George Drury <info@georgedrury.co.uk>",
563
+ "categories": [
564
+ "substrate",
565
+ "ui"
566
+ ],
567
+ "registryDependencies": [
568
+ "scroll-area"
569
+ ],
570
+ "cssVars": {
571
+ "theme": {
572
+ "color-panel": "var(--panel, var(--color-card))",
573
+ "color-panel-foreground": "var(--panel-foreground, var(--color-card-foreground))"
574
+ },
575
+ "light": {
576
+ "panel": "oklch(1 0 0)",
577
+ "panel-foreground": "oklch(0.145 0 0)"
578
+ },
579
+ "dark": {
580
+ "panel": "oklch(0.205 0 0)",
581
+ "panel-foreground": "oklch(0.985 0 0)"
582
+ }
583
+ },
584
+ "meta": {
585
+ "example": "<Panel position=\"left\">content</Panel>",
586
+ "lineage": [
587
+ {
588
+ "name": "Substrate"
589
+ }
590
+ ]
591
+ },
592
+ "files": [
593
+ {
594
+ "path": "registry/substrate/components/panel.tsx",
595
+ "type": "registry:ui",
596
+ "target": "components/substrate/panel.tsx"
597
+ }
598
+ ]
599
+ },
600
+ {
601
+ "name": "pane",
602
+ "type": "registry:ui",
603
+ "title": "Pane",
604
+ "description": "Content section within a panel — Pane wrapper with PaneHeader, PaneLabel, and PaneAction for composing property editors.",
605
+ "author": "George Drury <info@georgedrury.co.uk>",
606
+ "categories": [
607
+ "substrate",
608
+ "ui"
609
+ ],
610
+ "dependencies": [],
611
+ "registryDependencies": [
612
+ "https://substrate.georgedrury.co.uk/r/panel"
613
+ ],
614
+ "meta": {
615
+ "example": "<Pane><PaneHeader><PaneLabel>Fill</PaneLabel><PaneAction>+</PaneAction></PaneHeader></Pane>",
616
+ "lineage": [
617
+ {
618
+ "name": "Substrate"
619
+ }
620
+ ]
621
+ },
622
+ "files": [
623
+ {
624
+ "path": "registry/substrate/components/pane.tsx",
625
+ "type": "registry:ui",
626
+ "target": "components/substrate/pane.tsx"
627
+ }
628
+ ]
629
+ },
630
+ {
631
+ "name": "action",
632
+ "type": "registry:ui",
633
+ "title": "Action",
634
+ "description": "Form field row layout — Action container with ActionLabel and ActionControls for consistent label + control rows in property panes.",
635
+ "author": "George Drury <info@georgedrury.co.uk>",
636
+ "categories": [
637
+ "substrate",
638
+ "ui"
639
+ ],
640
+ "meta": {
641
+ "example": "<Action><ActionLabel>Opacity</ActionLabel><ActionControls><Slider /></ActionControls></Action>",
642
+ "lineage": [
643
+ {
644
+ "name": "Substrate"
645
+ }
646
+ ]
647
+ },
648
+ "files": [
649
+ {
650
+ "path": "registry/substrate/components/action.tsx",
651
+ "type": "registry:ui",
652
+ "target": "components/substrate/action.tsx"
653
+ }
654
+ ]
655
+ },
656
+ {
657
+ "name": "slider",
658
+ "type": "registry:ui",
659
+ "title": "Slider",
660
+ "description": "Slider component built directly on Radix Slider primitive with design tool styling.",
661
+ "author": "George Drury <info@georgedrury.co.uk>",
662
+ "categories": [
663
+ "substrate",
664
+ "ui"
665
+ ],
666
+ "dependencies": [
667
+ "radix-ui"
668
+ ],
669
+ "meta": {
670
+ "example": "<Slider value={[50]} onValueChange={setValue} max={100} step={1} />",
671
+ "lineage": [
672
+ {
673
+ "name": "Radix"
674
+ },
675
+ {
676
+ "name": "Substrate"
677
+ }
678
+ ]
679
+ },
680
+ "files": [
681
+ {
682
+ "path": "registry/substrate/components/slider.tsx",
683
+ "type": "registry:ui",
684
+ "target": "components/substrate/slider.tsx"
685
+ }
686
+ ]
687
+ },
688
+ {
689
+ "name": "surface",
690
+ "type": "registry:ui",
691
+ "title": "Surface",
692
+ "description": "Container component for creative surfaces — provides consistent mount point with canvas background, optional overlay controls, and dot grid background.",
693
+ "author": "George Drury <info@georgedrury.co.uk>",
694
+ "categories": [
695
+ "substrate",
696
+ "ui",
697
+ "chrome"
698
+ ],
699
+ "cssVars": {
700
+ "theme": {
701
+ "color-canvas": "var(--canvas, var(--color-background))",
702
+ "color-canvas-foreground": "var(--canvas-foreground, var(--color-foreground-muted))"
703
+ },
704
+ "light": {
705
+ "canvas": "oklch(.97 0.0 0)",
706
+ "canvas-foreground": "oklch(0.556 0 0)"
707
+ },
708
+ "dark": {
709
+ "canvas": "oklch(17.764% 0.00002 271.152)",
710
+ "canvas-foreground": "oklch(0.708 0 0)"
711
+ }
712
+ },
713
+ "meta": {
714
+ "example": "<Surface><SurfaceGrid />{/* your renderer */}<SurfaceControls position=\"bottom-right\">{/* zoom buttons */}</SurfaceControls></Surface>",
715
+ "lineage": [
716
+ {
717
+ "name": "Substrate"
718
+ }
719
+ ]
720
+ },
721
+ "files": [
722
+ {
723
+ "path": "registry/substrate/components/surface.tsx",
724
+ "type": "registry:ui",
725
+ "target": "components/substrate/surface.tsx"
726
+ }
727
+ ]
728
+ },
729
+ {
730
+ "name": "easing",
731
+ "type": "registry:lib",
732
+ "title": "Easing",
733
+ "description": "Cubic bezier easing utilities — presets, evaluation via Newton's method, CSS cubic-bezier() parsing and serialisation.",
734
+ "author": "George Drury <info@georgedrury.co.uk>",
735
+ "categories": [
736
+ "substrate",
737
+ "lib",
738
+ "animation"
739
+ ],
740
+ "meta": {
741
+ "lineage": [
742
+ {
743
+ "name": "Substrate"
744
+ }
745
+ ]
746
+ },
747
+ "files": [
748
+ {
749
+ "path": "registry/substrate/lib/easing.ts",
750
+ "type": "registry:lib",
751
+ "target": "lib/substrate/easing.ts"
752
+ }
753
+ ]
754
+ },
755
+ {
756
+ "name": "animation-store",
757
+ "type": "registry:lib",
758
+ "title": "Animation Store",
759
+ "description": "Zustand store for animation playback — duration, current time, play/pause, zoom level, and keyframe selection.",
760
+ "author": "George Drury <info@georgedrury.co.uk>",
761
+ "categories": [
762
+ "substrate",
763
+ "store",
764
+ "animation"
765
+ ],
766
+ "dependencies": [
767
+ "zustand"
768
+ ],
769
+ "meta": {
770
+ "lineage": [
771
+ {
772
+ "name": "Substrate"
773
+ }
774
+ ]
775
+ },
776
+ "files": [
777
+ {
778
+ "path": "registry/substrate/stores/animation-store.ts",
779
+ "type": "registry:lib",
780
+ "target": "stores/substrate/animation-store.ts"
781
+ }
782
+ ]
783
+ },
784
+ {
785
+ "name": "timeline",
786
+ "type": "registry:ui",
787
+ "title": "Timeline",
788
+ "description": "Compound timeline component with ruler, playhead, tracks, keyframe diamonds, and transport controls for animation and sequencing tools.",
789
+ "author": "George Drury <info@georgedrury.co.uk>",
790
+ "categories": [
791
+ "substrate",
792
+ "ui",
793
+ "animation"
794
+ ],
795
+ "dependencies": [
796
+ "@remixicon/react"
797
+ ],
798
+ "registryDependencies": [
799
+ "https://substrate.georgedrury.co.uk/r/animation-store"
800
+ ],
801
+ "cssVars": {
802
+ "theme": {
803
+ "color-timeline-playhead": "var(--timeline-playhead, var(--color-destructive))",
804
+ "color-timeline-keyframe": "var(--timeline-keyframe, var(--color-muted-foreground))",
805
+ "color-timeline-track": "var(--timeline-track, var(--color-panel))"
806
+ },
807
+ "light": {},
808
+ "dark": {}
809
+ },
810
+ "meta": {
811
+ "example": "<Timeline><TimelineTransport /><TimelineRuler duration={5} zoomLevel={100} /><TimelineTrack label=\"opacity\"><TimelineKeyframe time={0} duration={5} zoomLevel={100} /><TimelineKeyframe time={2.5} duration={5} zoomLevel={100} /></TimelineTrack></Timeline>",
812
+ "lineage": [
813
+ {
814
+ "name": "Substrate"
815
+ }
816
+ ]
817
+ },
818
+ "files": [
819
+ {
820
+ "path": "registry/substrate/components/timeline.tsx",
821
+ "type": "registry:ui",
822
+ "target": "components/substrate/timeline.tsx"
823
+ }
824
+ ]
825
+ },
826
+ {
827
+ "name": "number-input",
828
+ "type": "registry:ui",
829
+ "title": "Number Input",
830
+ "description": "Numeric input with drag-to-scrub on the label, arrow key stepping, shift for larger increments, and optional suffix. Designed for property editors.",
831
+ "author": "George Drury <info@georgedrury.co.uk>",
832
+ "categories": [
833
+ "substrate",
834
+ "ui",
835
+ "form"
836
+ ],
837
+ "meta": {
838
+ "example": "<NumberInput label=\"X\" value={100} onChange={setValue} />",
839
+ "lineage": [
840
+ {
841
+ "name": "Substrate"
842
+ }
843
+ ]
844
+ },
845
+ "files": [
846
+ {
847
+ "path": "registry/substrate/components/number-input.tsx",
848
+ "type": "registry:component",
849
+ "target": "components/substrate/number-input.tsx"
850
+ }
851
+ ]
852
+ },
853
+ {
854
+ "name": "history-controls",
855
+ "type": "registry:ui",
856
+ "title": "History Controls",
857
+ "description": "Undo and redo buttons that read from the document store. Position anywhere — inside a toolbar, panel header, or floating independently.",
858
+ "author": "George Drury <info@georgedrury.co.uk>",
859
+ "categories": [
860
+ "substrate",
861
+ "ui",
862
+ "chrome"
863
+ ],
864
+ "dependencies": [
865
+ "@remixicon/react"
866
+ ],
867
+ "meta": {
868
+ "example": "<HistoryControls />",
869
+ "lineage": [
870
+ {
871
+ "name": "Substrate"
872
+ }
873
+ ]
874
+ },
875
+ "files": [
876
+ {
877
+ "path": "registry/substrate/components/history-controls.tsx",
878
+ "type": "registry:component",
879
+ "target": "components/substrate/history-controls.tsx"
880
+ }
881
+ ]
882
+ },
883
+ {
884
+ "name": "gallery",
885
+ "type": "registry:ui",
886
+ "title": "Gallery",
887
+ "description": "Responsive thumbnail grid with selection state, hover overlays, and action buttons. Used for image histories, asset browsers, and media galleries.",
888
+ "author": "George Drury <info@georgedrury.co.uk>",
889
+ "categories": [
890
+ "substrate",
891
+ "ui",
892
+ "visualization"
893
+ ],
894
+ "cssVars": {
895
+ "theme": {
896
+ "color-gallery-selection": "var(--gallery-selection, var(--color-primary))"
897
+ },
898
+ "light": {},
899
+ "dark": {}
900
+ },
901
+ "meta": {
902
+ "example": "<Gallery columns={3}><GalleryItem selected onSelect={handleSelect}><GalleryImage src=\"/image.jpg\" alt=\"\" /><GalleryAction><RiDeleteBinLine /></GalleryAction></GalleryItem></Gallery>",
903
+ "lineage": [
904
+ {
905
+ "name": "Substrate"
906
+ }
907
+ ]
908
+ },
909
+ "files": [
910
+ {
911
+ "path": "registry/substrate/components/gallery.tsx",
912
+ "type": "registry:ui",
913
+ "target": "components/substrate/gallery.tsx"
914
+ }
915
+ ]
916
+ },
917
+ {
918
+ "name": "colour-picker",
919
+ "type": "registry:ui",
920
+ "title": "Colour Picker",
921
+ "description": "Colour picker with hex input and swatch preview, powered by react-colorful in a Radix Popover. Used in material editors, fill/stroke controls, and chart styling.",
922
+ "author": "George Drury <info@georgedrury.co.uk>",
923
+ "categories": [
924
+ "substrate",
925
+ "ui",
926
+ "control"
927
+ ],
928
+ "dependencies": [
929
+ "react-colorful",
930
+ "radix-ui"
931
+ ],
932
+ "meta": {
933
+ "example": "<ColourPicker value=\"#6366f1\" onChange={setColour} />",
934
+ "lineage": [
935
+ {
936
+ "name": "react-colorful"
937
+ },
938
+ {
939
+ "name": "Substrate"
940
+ }
941
+ ]
942
+ },
943
+ "files": [
944
+ {
945
+ "path": "registry/substrate/components/colour-picker.tsx",
946
+ "type": "registry:ui",
947
+ "target": "components/substrate/colour-picker.tsx"
948
+ }
949
+ ]
950
+ },
951
+ {
952
+ "name": "easing-curve-editor",
953
+ "type": "registry:ui",
954
+ "title": "Easing Curve Editor",
955
+ "description": "Interactive cubic bezier curve editor with draggable control points and preset buttons. Used for keyframe easing in animation tools.",
956
+ "author": "George Drury <info@georgedrury.co.uk>",
957
+ "categories": [
958
+ "substrate",
959
+ "ui",
960
+ "animation"
961
+ ],
962
+ "registryDependencies": [
963
+ "https://substrate.georgedrury.co.uk/r/easing"
964
+ ],
965
+ "cssVars": {
966
+ "theme": {
967
+ "color-easing-curve": "var(--easing-curve, var(--color-primary))",
968
+ "color-easing-handle": "var(--easing-handle, var(--color-primary))"
969
+ },
970
+ "light": {},
971
+ "dark": {}
972
+ },
973
+ "meta": {
974
+ "example": "<EasingCurveEditor value={{ x1: 0.42, y1: 0, x2: 0.58, y2: 1 }} onChange={setEasing} />",
975
+ "lineage": [
976
+ {
977
+ "name": "Substrate"
978
+ }
979
+ ]
980
+ },
981
+ "files": [
982
+ {
983
+ "path": "registry/substrate/components/easing-curve-editor.tsx",
984
+ "type": "registry:ui",
985
+ "target": "components/substrate/easing-curve-editor.tsx"
986
+ }
987
+ ]
988
+ },
989
+ {
990
+ "name": "use-selection",
991
+ "type": "registry:hook",
992
+ "title": "useSelection",
993
+ "description": "Multi-select hook with cmd-click toggle and shift-click range selection.",
994
+ "author": "George Drury <info@georgedrury.co.uk>",
995
+ "categories": [
996
+ "substrate",
997
+ "hook"
998
+ ],
999
+ "registryDependencies": [],
1000
+ "meta": {
1001
+ "lineage": [
1002
+ {
1003
+ "name": "Substrate"
1004
+ }
1005
+ ]
1006
+ },
1007
+ "files": [
1008
+ {
1009
+ "path": "registry/substrate/hooks/use-selection.ts",
1010
+ "type": "registry:hook",
1011
+ "target": "hooks/substrate/use-selection.ts"
1012
+ }
1013
+ ]
1014
+ },
1015
+ {
1016
+ "name": "use-drag-reorder",
1017
+ "type": "registry:hook",
1018
+ "title": "useDragReorder",
1019
+ "description": "Pointer-based list reordering with visual feedback and pointer capture.",
1020
+ "author": "George Drury <info@georgedrury.co.uk>",
1021
+ "categories": [
1022
+ "substrate",
1023
+ "hook"
1024
+ ],
1025
+ "registryDependencies": [],
1026
+ "meta": {
1027
+ "lineage": [
1028
+ {
1029
+ "name": "Substrate"
1030
+ }
1031
+ ]
1032
+ },
1033
+ "files": [
1034
+ {
1035
+ "path": "registry/substrate/hooks/use-drag-reorder.ts",
1036
+ "type": "registry:hook",
1037
+ "target": "hooks/substrate/use-drag-reorder.ts"
1038
+ }
1039
+ ]
1040
+ },
1041
+ {
1042
+ "name": "use-clipboard",
1043
+ "type": "registry:hook",
1044
+ "title": "useClipboard",
1045
+ "description": "Copy, cut, and paste with keyboard shortcuts and system clipboard integration.",
1046
+ "author": "George Drury <info@georgedrury.co.uk>",
1047
+ "categories": [
1048
+ "substrate",
1049
+ "hook"
1050
+ ],
1051
+ "registryDependencies": [],
1052
+ "meta": {
1053
+ "lineage": [
1054
+ {
1055
+ "name": "Substrate"
1056
+ }
1057
+ ]
1058
+ },
1059
+ "files": [
1060
+ {
1061
+ "path": "registry/substrate/hooks/use-clipboard.ts",
1062
+ "type": "registry:hook",
1063
+ "target": "hooks/substrate/use-clipboard.ts"
1064
+ }
1065
+ ]
1066
+ },
1067
+ {
1068
+ "name": "use-viewport",
1069
+ "type": "registry:hook",
1070
+ "title": "useViewport",
1071
+ "description": "Pan and zoom state management for canvas surfaces — coordinate transforms, pinch-zoom, and zoom-to-fit.",
1072
+ "author": "George Drury <info@georgedrury.co.uk>",
1073
+ "categories": [
1074
+ "substrate",
1075
+ "hook"
1076
+ ],
1077
+ "registryDependencies": [],
1078
+ "meta": {
1079
+ "lineage": [
1080
+ {
1081
+ "name": "Substrate"
1082
+ }
1083
+ ]
1084
+ },
1085
+ "files": [
1086
+ {
1087
+ "path": "registry/substrate/hooks/use-viewport.ts",
1088
+ "type": "registry:hook",
1089
+ "target": "hooks/substrate/use-viewport.ts"
1090
+ }
1091
+ ]
1092
+ },
1093
+ {
1094
+ "name": "use-undoable",
1095
+ "type": "registry:hook",
1096
+ "title": "useUndoable",
1097
+ "description": "Lightweight undo/redo stack using refs for performance — pushSnapshot, undo, redo.",
1098
+ "author": "George Drury <info@georgedrury.co.uk>",
1099
+ "categories": [
1100
+ "substrate",
1101
+ "hook"
1102
+ ],
1103
+ "registryDependencies": [],
1104
+ "meta": {
1105
+ "lineage": [
1106
+ {
1107
+ "name": "Substrate"
1108
+ }
1109
+ ]
1110
+ },
1111
+ "files": [
1112
+ {
1113
+ "path": "registry/substrate/hooks/use-undoable.ts",
1114
+ "type": "registry:hook",
1115
+ "target": "hooks/substrate/use-undoable.ts"
1116
+ }
1117
+ ]
1118
+ },
1119
+ {
1120
+ "name": "keyboard-shortcuts",
1121
+ "type": "registry:lib",
1122
+ "title": "Keyboard shortcuts",
1123
+ "description": "Declarative keyboard shortcut registration and formatting — replaces switch statements with a structured map.",
1124
+ "author": "George Drury <info@georgedrury.co.uk>",
1125
+ "categories": [
1126
+ "substrate",
1127
+ "lib"
1128
+ ],
1129
+ "registryDependencies": [],
1130
+ "meta": {
1131
+ "lineage": [
1132
+ {
1133
+ "name": "Substrate"
1134
+ }
1135
+ ]
1136
+ },
1137
+ "files": [
1138
+ {
1139
+ "path": "registry/substrate/lib/keyboard-shortcuts.ts",
1140
+ "type": "registry:lib",
1141
+ "target": "lib/substrate/keyboard-shortcuts.ts"
1142
+ }
1143
+ ]
1144
+ },
1145
+ {
1146
+ "name": "snap",
1147
+ "type": "registry:lib",
1148
+ "title": "Snap",
1149
+ "description": "Grid snapping and smart edge snapping utilities — snapToGrid, snapToGuides, guidesFromBounds.",
1150
+ "author": "George Drury <info@georgedrury.co.uk>",
1151
+ "categories": [
1152
+ "substrate",
1153
+ "lib"
1154
+ ],
1155
+ "registryDependencies": [
1156
+ "https://substrate.georgedrury.co.uk/r/types"
1157
+ ],
1158
+ "meta": {
1159
+ "lineage": [
1160
+ {
1161
+ "name": "Substrate"
1162
+ }
1163
+ ]
1164
+ },
1165
+ "files": [
1166
+ {
1167
+ "path": "registry/substrate/lib/snap.ts",
1168
+ "type": "registry:lib",
1169
+ "target": "lib/substrate/snap.ts"
1170
+ }
1171
+ ]
1172
+ },
1173
+ {
1174
+ "name": "bounding-box",
1175
+ "type": "registry:lib",
1176
+ "title": "Bounding box",
1177
+ "description": "Bounding box computation — union, intersection, containment, expansion, and point-in-bounds testing.",
1178
+ "author": "George Drury <info@georgedrury.co.uk>",
1179
+ "categories": [
1180
+ "substrate",
1181
+ "lib"
1182
+ ],
1183
+ "registryDependencies": [
1184
+ "https://substrate.georgedrury.co.uk/r/types"
1185
+ ],
1186
+ "meta": {
1187
+ "lineage": [
1188
+ {
1189
+ "name": "Substrate"
1190
+ }
1191
+ ]
1192
+ },
1193
+ "files": [
1194
+ {
1195
+ "path": "registry/substrate/lib/bounding-box.ts",
1196
+ "type": "registry:lib",
1197
+ "target": "lib/substrate/bounding-box.ts"
1198
+ }
1199
+ ]
1200
+ },
1201
+ {
1202
+ "name": "alignment-controls",
1203
+ "type": "registry:ui",
1204
+ "title": "Alignment Controls",
1205
+ "description": "Horizontal and vertical alignment and distribution buttons for positioning selected elements on the canvas.",
1206
+ "categories": [
1207
+ "substrate",
1208
+ "ui",
1209
+ "control"
1210
+ ],
1211
+ "dependencies": [
1212
+ "@remixicon/react"
1213
+ ],
1214
+ "meta": {
1215
+ "example": "<AlignmentControls onAlign={(type) => alignElements(type)} />",
1216
+ "lineage": [
1217
+ {
1218
+ "name": "Substrate"
1219
+ }
1220
+ ]
1221
+ },
1222
+ "files": [
1223
+ {
1224
+ "path": "registry/substrate/components/alignment-controls.tsx",
1225
+ "type": "registry:ui",
1226
+ "target": "components/substrate/alignment-controls.tsx"
1227
+ }
1228
+ ],
1229
+ "author": "George Drury <info@georgedrury.co.uk>"
1230
+ },
1231
+ {
1232
+ "name": "badge",
1233
+ "type": "registry:ui",
1234
+ "title": "Badge",
1235
+ "description": "Small status indicator with variant support. Used for element type labels, node badges, and status indicators.",
1236
+ "categories": [
1237
+ "substrate",
1238
+ "ui"
1239
+ ],
1240
+ "meta": {
1241
+ "example": "<Badge variant=\"secondary\">Frame</Badge>",
1242
+ "lineage": [
1243
+ {
1244
+ "name": "Substrate"
1245
+ }
1246
+ ]
1247
+ },
1248
+ "files": [
1249
+ {
1250
+ "path": "registry/substrate/components/badge.tsx",
1251
+ "type": "registry:ui",
1252
+ "target": "components/substrate/badge.tsx"
1253
+ }
1254
+ ],
1255
+ "author": "George Drury <info@georgedrury.co.uk>"
1256
+ },
1257
+ {
1258
+ "name": "breadcrumbs",
1259
+ "type": "registry:ui",
1260
+ "title": "Breadcrumbs",
1261
+ "description": "Navigation breadcrumb trail for showing document or frame hierarchy. Supports click-to-navigate.",
1262
+ "categories": [
1263
+ "substrate",
1264
+ "ui",
1265
+ "chrome"
1266
+ ],
1267
+ "dependencies": [
1268
+ "@remixicon/react"
1269
+ ],
1270
+ "meta": {
1271
+ "example": "<Breadcrumbs><BreadcrumbItem>Page</BreadcrumbItem><BreadcrumbItem>Frame 1</BreadcrumbItem></Breadcrumbs>",
1272
+ "lineage": [
1273
+ {
1274
+ "name": "Substrate"
1275
+ }
1276
+ ]
1277
+ },
1278
+ "files": [
1279
+ {
1280
+ "path": "registry/substrate/components/breadcrumbs.tsx",
1281
+ "type": "registry:ui",
1282
+ "target": "components/substrate/breadcrumbs.tsx"
1283
+ }
1284
+ ],
1285
+ "author": "George Drury <info@georgedrury.co.uk>"
1286
+ },
1287
+ {
1288
+ "name": "collapsible-pane",
1289
+ "type": "registry:ui",
1290
+ "title": "Collapsible Pane",
1291
+ "description": "Expandable pane section with animated open/close and chevron indicator. Wraps PaneHeader and PaneContent.",
1292
+ "categories": [
1293
+ "substrate",
1294
+ "ui",
1295
+ "control"
1296
+ ],
1297
+ "dependencies": [
1298
+ "radix-ui",
1299
+ "@remixicon/react"
1300
+ ],
1301
+ "meta": {
1302
+ "example": "<CollapsiblePane label=\"Transform\">content</CollapsiblePane>",
1303
+ "lineage": [
1304
+ {
1305
+ "name": "Radix"
1306
+ },
1307
+ {
1308
+ "name": "Substrate"
1309
+ }
1310
+ ]
1311
+ },
1312
+ "files": [
1313
+ {
1314
+ "path": "registry/substrate/components/collapsible-pane.tsx",
1315
+ "type": "registry:ui",
1316
+ "target": "components/substrate/collapsible-pane.tsx"
1317
+ }
1318
+ ],
1319
+ "author": "George Drury <info@georgedrury.co.uk>"
1320
+ },
1321
+ {
1322
+ "name": "command-palette",
1323
+ "type": "registry:ui",
1324
+ "title": "Command Palette",
1325
+ "description": "Searchable command launcher overlay triggered by keyboard shortcut. Groups commands with icons and shortcut hints.",
1326
+ "categories": [
1327
+ "substrate",
1328
+ "ui",
1329
+ "chrome"
1330
+ ],
1331
+ "dependencies": [
1332
+ "cmdk",
1333
+ "radix-ui",
1334
+ "@remixicon/react"
1335
+ ],
1336
+ "meta": {
1337
+ "example": "<CommandPalette open={open} onOpenChange={setOpen} groups={groups} />",
1338
+ "lineage": [
1339
+ {
1340
+ "name": "Radix"
1341
+ },
1342
+ {
1343
+ "name": "Substrate"
1344
+ }
1345
+ ]
1346
+ },
1347
+ "files": [
1348
+ {
1349
+ "path": "registry/substrate/components/command-palette.tsx",
1350
+ "type": "registry:ui",
1351
+ "target": "components/substrate/command-palette.tsx"
1352
+ }
1353
+ ],
1354
+ "author": "George Drury <info@georgedrury.co.uk>"
1355
+ },
1356
+ {
1357
+ "name": "context-menu",
1358
+ "type": "registry:ui",
1359
+ "title": "Context Menu",
1360
+ "description": "Right-click context menu with items, separators, sub-menus, and keyboard shortcut display.",
1361
+ "categories": [
1362
+ "substrate",
1363
+ "ui"
1364
+ ],
1365
+ "dependencies": [
1366
+ "radix-ui"
1367
+ ],
1368
+ "meta": {
1369
+ "example": "<ContextMenu><ContextMenuTrigger>Right click here</ContextMenuTrigger><ContextMenuContent><ContextMenuItem>Copy</ContextMenuItem></ContextMenuContent></ContextMenu>",
1370
+ "lineage": [
1371
+ {
1372
+ "name": "Radix"
1373
+ },
1374
+ {
1375
+ "name": "Substrate"
1376
+ }
1377
+ ]
1378
+ },
1379
+ "files": [
1380
+ {
1381
+ "path": "registry/substrate/components/context-menu.tsx",
1382
+ "type": "registry:ui",
1383
+ "target": "components/substrate/context-menu.tsx"
1384
+ }
1385
+ ],
1386
+ "author": "George Drury <info@georgedrury.co.uk>"
1387
+ },
1388
+ {
1389
+ "name": "document-tabs",
1390
+ "type": "registry:ui",
1391
+ "title": "Document Tabs",
1392
+ "description": "Tab bar for switching between open documents or canvases. Supports close button and active state.",
1393
+ "categories": [
1394
+ "substrate",
1395
+ "ui",
1396
+ "chrome"
1397
+ ],
1398
+ "dependencies": [
1399
+ "radix-ui",
1400
+ "@remixicon/react"
1401
+ ],
1402
+ "meta": {
1403
+ "example": "<DocumentTabs tabs={tabs} activeId={activeId} onSelect={setActiveId} onClose={closeTab} />",
1404
+ "lineage": [
1405
+ {
1406
+ "name": "Radix"
1407
+ },
1408
+ {
1409
+ "name": "Substrate"
1410
+ }
1411
+ ]
1412
+ },
1413
+ "files": [
1414
+ {
1415
+ "path": "registry/substrate/components/document-tabs.tsx",
1416
+ "type": "registry:ui",
1417
+ "target": "components/substrate/document-tabs.tsx"
1418
+ }
1419
+ ],
1420
+ "author": "George Drury <info@georgedrury.co.uk>"
1421
+ },
1422
+ {
1423
+ "name": "empty-state",
1424
+ "type": "registry:ui",
1425
+ "title": "Empty State",
1426
+ "description": "Placeholder component for empty panels, lists, or surfaces. Displays a title, description, and optional icon or action.",
1427
+ "categories": [
1428
+ "substrate",
1429
+ "ui"
1430
+ ],
1431
+ "meta": {
1432
+ "example": "<EmptyState title=\"No layers\" description=\"Draw something to get started\" />",
1433
+ "lineage": [
1434
+ {
1435
+ "name": "Substrate"
1436
+ }
1437
+ ]
1438
+ },
1439
+ "files": [
1440
+ {
1441
+ "path": "registry/substrate/components/empty-state.tsx",
1442
+ "type": "registry:ui",
1443
+ "target": "components/substrate/empty-state.tsx"
1444
+ }
1445
+ ],
1446
+ "author": "George Drury <info@georgedrury.co.uk>"
1447
+ },
1448
+ {
1449
+ "name": "layer-list",
1450
+ "type": "registry:ui",
1451
+ "title": "Layer List",
1452
+ "description": "Sortable layer panel with visibility and lock toggles, icons, and context menu support. Compound component pattern.",
1453
+ "categories": [
1454
+ "substrate",
1455
+ "ui",
1456
+ "control"
1457
+ ],
1458
+ "dependencies": [
1459
+ "@remixicon/react"
1460
+ ],
1461
+ "meta": {
1462
+ "example": "<LayerList><LayerItem><LayerIcon><SquareIcon /></LayerIcon><LayerName>Rectangle 1</LayerName></LayerItem></LayerList>",
1463
+ "lineage": [
1464
+ {
1465
+ "name": "Substrate"
1466
+ }
1467
+ ]
1468
+ },
1469
+ "files": [
1470
+ {
1471
+ "path": "registry/substrate/components/layer-list.tsx",
1472
+ "type": "registry:ui",
1473
+ "target": "components/substrate/layer-list.tsx"
1474
+ }
1475
+ ],
1476
+ "author": "George Drury <info@georgedrury.co.uk>"
1477
+ },
1478
+ {
1479
+ "name": "node",
1480
+ "type": "registry:ui",
1481
+ "title": "Node",
1482
+ "description": "Card-based node for visual programming editors with typed input/output ports, preview area, dividers, and badges. Seven port types with CSS variable colours.",
1483
+ "categories": [
1484
+ "substrate",
1485
+ "ui",
1486
+ "control"
1487
+ ],
1488
+ "cssVars": {
1489
+ "theme": {
1490
+ "color-node-port-number": "var(--node-port-number, oklch(0.7 0.15 250))",
1491
+ "color-node-port-colour": "var(--node-port-colour, oklch(0.7 0.15 330))",
1492
+ "color-node-port-image": "var(--node-port-image, oklch(0.7 0.15 100))",
1493
+ "color-node-port-geometry": "var(--node-port-geometry, oklch(0.7 0.15 200))",
1494
+ "color-node-port-text": "var(--node-port-text, oklch(0.7 0.15 150))",
1495
+ "color-node-port-boolean": "var(--node-port-boolean, oklch(0.7 0.15 30))",
1496
+ "color-node-port-any": "var(--node-port-any, oklch(0.6 0 0))"
1497
+ }
1498
+ },
1499
+ "meta": {
1500
+ "example": "<Node><NodeHeader><NodeTitle>Add</NodeTitle></NodeHeader><NodeContent><NodePort type=\"number\" direction=\"input\" label=\"A\" /></NodeContent></Node>",
1501
+ "lineage": [
1502
+ {
1503
+ "name": "Substrate"
1504
+ }
1505
+ ]
1506
+ },
1507
+ "files": [
1508
+ {
1509
+ "path": "registry/substrate/components/node.tsx",
1510
+ "type": "registry:ui",
1511
+ "target": "components/substrate/node.tsx"
1512
+ }
1513
+ ],
1514
+ "author": "George Drury <info@georgedrury.co.uk>"
1515
+ },
1516
+ {
1517
+ "name": "number-slider",
1518
+ "type": "registry:ui",
1519
+ "title": "Number Slider",
1520
+ "description": "Combined number input and slider in a single row. Pairs NumberInput with Slider for properties like opacity or font size.",
1521
+ "categories": [
1522
+ "substrate",
1523
+ "ui",
1524
+ "form"
1525
+ ],
1526
+ "registryDependencies": [
1527
+ "slider",
1528
+ "number-input"
1529
+ ],
1530
+ "meta": {
1531
+ "example": "<NumberSlider label=\"Opacity\" min={0} max={100} value={opacity} onChange={setOpacity} />",
1532
+ "lineage": [
1533
+ {
1534
+ "name": "Substrate"
1535
+ }
1536
+ ]
1537
+ },
1538
+ "files": [
1539
+ {
1540
+ "path": "registry/substrate/components/number-slider.tsx",
1541
+ "type": "registry:ui",
1542
+ "target": "components/substrate/number-slider.tsx"
1543
+ }
1544
+ ],
1545
+ "author": "George Drury <info@georgedrury.co.uk>"
1546
+ },
1547
+ {
1548
+ "name": "popover",
1549
+ "type": "registry:ui",
1550
+ "title": "Popover",
1551
+ "description": "Floating content panel anchored to a trigger element. Used for colour pickers, mini inspectors, and inline editors.",
1552
+ "categories": [
1553
+ "substrate",
1554
+ "ui"
1555
+ ],
1556
+ "dependencies": [
1557
+ "radix-ui"
1558
+ ],
1559
+ "meta": {
1560
+ "example": "<Popover><PopoverTrigger>Open</PopoverTrigger><PopoverContent>content</PopoverContent></Popover>",
1561
+ "lineage": [
1562
+ {
1563
+ "name": "Radix"
1564
+ },
1565
+ {
1566
+ "name": "Substrate"
1567
+ }
1568
+ ]
1569
+ },
1570
+ "files": [
1571
+ {
1572
+ "path": "registry/substrate/components/popover.tsx",
1573
+ "type": "registry:ui",
1574
+ "target": "components/substrate/popover.tsx"
1575
+ }
1576
+ ],
1577
+ "author": "George Drury <info@georgedrury.co.uk>"
1578
+ },
1579
+ {
1580
+ "name": "progress-bar",
1581
+ "type": "registry:ui",
1582
+ "title": "Progress Bar",
1583
+ "description": "Horizontal progress indicator with animated fill. Used for generation progress, file uploads, and loading states.",
1584
+ "categories": [
1585
+ "substrate",
1586
+ "ui"
1587
+ ],
1588
+ "meta": {
1589
+ "example": "<ProgressBar value={75} max={100} />",
1590
+ "lineage": [
1591
+ {
1592
+ "name": "Substrate"
1593
+ }
1594
+ ]
1595
+ },
1596
+ "files": [
1597
+ {
1598
+ "path": "registry/substrate/components/progress-bar.tsx",
1599
+ "type": "registry:ui",
1600
+ "target": "components/substrate/progress-bar.tsx"
1601
+ }
1602
+ ],
1603
+ "author": "George Drury <info@georgedrury.co.uk>"
1604
+ },
1605
+ {
1606
+ "name": "resizer",
1607
+ "type": "registry:ui",
1608
+ "title": "Resizer",
1609
+ "description": "Draggable resize handle for creating split regions between panels or panes. Vertical and horizontal orientations.",
1610
+ "categories": [
1611
+ "substrate",
1612
+ "ui",
1613
+ "chrome"
1614
+ ],
1615
+ "meta": {
1616
+ "example": "<Resizer orientation=\"vertical\" onResize={setWidth} />",
1617
+ "lineage": [
1618
+ {
1619
+ "name": "Substrate"
1620
+ }
1621
+ ]
1622
+ },
1623
+ "files": [
1624
+ {
1625
+ "path": "registry/substrate/components/resizer.tsx",
1626
+ "type": "registry:ui",
1627
+ "target": "components/substrate/resizer.tsx"
1628
+ }
1629
+ ],
1630
+ "author": "George Drury <info@georgedrury.co.uk>"
1631
+ },
1632
+ {
1633
+ "name": "select",
1634
+ "type": "registry:ui",
1635
+ "title": "Select",
1636
+ "description": "Dropdown select input with label, built on Radix Select. Used for blend modes, font families, and enumerated properties.",
1637
+ "categories": [
1638
+ "substrate",
1639
+ "ui",
1640
+ "form"
1641
+ ],
1642
+ "dependencies": [
1643
+ "radix-ui",
1644
+ "@remixicon/react"
1645
+ ],
1646
+ "meta": {
1647
+ "example": "<Select label=\"Blend mode\" value={mode} onValueChange={setMode} options={options} />",
1648
+ "lineage": [
1649
+ {
1650
+ "name": "Radix"
1651
+ },
1652
+ {
1653
+ "name": "Substrate"
1654
+ }
1655
+ ]
1656
+ },
1657
+ "files": [
1658
+ {
1659
+ "path": "registry/substrate/components/select.tsx",
1660
+ "type": "registry:ui",
1661
+ "target": "components/substrate/select.tsx"
1662
+ }
1663
+ ],
1664
+ "author": "George Drury <info@georgedrury.co.uk>"
1665
+ },
1666
+ {
1667
+ "name": "shortcut-overlay",
1668
+ "type": "registry:ui",
1669
+ "title": "Shortcut Overlay",
1670
+ "description": "Full-screen overlay displaying grouped keyboard shortcuts. Triggered by a help shortcut (typically ?).",
1671
+ "categories": [
1672
+ "substrate",
1673
+ "ui",
1674
+ "chrome"
1675
+ ],
1676
+ "dependencies": [
1677
+ "radix-ui"
1678
+ ],
1679
+ "meta": {
1680
+ "example": "<ShortcutOverlay open={open} onOpenChange={setOpen} groups={shortcutGroups} />",
1681
+ "lineage": [
1682
+ {
1683
+ "name": "Radix"
1684
+ },
1685
+ {
1686
+ "name": "Substrate"
1687
+ }
1688
+ ]
1689
+ },
1690
+ "files": [
1691
+ {
1692
+ "path": "registry/substrate/components/shortcut-overlay.tsx",
1693
+ "type": "registry:ui",
1694
+ "target": "components/substrate/shortcut-overlay.tsx"
1695
+ }
1696
+ ],
1697
+ "author": "George Drury <info@georgedrury.co.uk>"
1698
+ },
1699
+ {
1700
+ "name": "status-bar",
1701
+ "type": "registry:ui",
1702
+ "title": "Status Bar",
1703
+ "description": "Bottom bar showing tool state, selection count, zoom level, and other status indicators. Compound component with sections and items.",
1704
+ "categories": [
1705
+ "substrate",
1706
+ "ui",
1707
+ "chrome"
1708
+ ],
1709
+ "meta": {
1710
+ "example": "<StatusBar><StatusBarSection><StatusBarItem label=\"Tool\" value=\"Select\" /></StatusBarSection></StatusBar>",
1711
+ "lineage": [
1712
+ {
1713
+ "name": "Substrate"
1714
+ }
1715
+ ]
1716
+ },
1717
+ "files": [
1718
+ {
1719
+ "path": "registry/substrate/components/status-bar.tsx",
1720
+ "type": "registry:ui",
1721
+ "target": "components/substrate/status-bar.tsx"
1722
+ }
1723
+ ],
1724
+ "author": "George Drury <info@georgedrury.co.uk>"
1725
+ },
1726
+ {
1727
+ "name": "swatch-palette",
1728
+ "type": "registry:ui",
1729
+ "title": "Swatch Palette",
1730
+ "description": "Grid of colour swatches for quick colour selection. Supports custom palettes and active swatch indicator.",
1731
+ "categories": [
1732
+ "substrate",
1733
+ "ui",
1734
+ "control"
1735
+ ],
1736
+ "meta": {
1737
+ "example": "<SwatchPalette colours={palette} value={colour} onChange={setColour} />",
1738
+ "lineage": [
1739
+ {
1740
+ "name": "Substrate"
1741
+ }
1742
+ ]
1743
+ },
1744
+ "files": [
1745
+ {
1746
+ "path": "registry/substrate/components/swatch-palette.tsx",
1747
+ "type": "registry:ui",
1748
+ "target": "components/substrate/swatch-palette.tsx"
1749
+ }
1750
+ ],
1751
+ "author": "George Drury <info@georgedrury.co.uk>"
1752
+ },
1753
+ {
1754
+ "name": "text-area",
1755
+ "type": "registry:ui",
1756
+ "title": "Text Area",
1757
+ "description": "Multi-line text input with label and design tool styling. Used for prompts, descriptions, and code fields.",
1758
+ "categories": [
1759
+ "substrate",
1760
+ "ui",
1761
+ "form"
1762
+ ],
1763
+ "meta": {
1764
+ "example": "<TextArea label=\"Prompt\" value={text} onChange={(e) => setText(e.target.value)} />",
1765
+ "lineage": [
1766
+ {
1767
+ "name": "Substrate"
1768
+ }
1769
+ ]
1770
+ },
1771
+ "files": [
1772
+ {
1773
+ "path": "registry/substrate/components/text-area.tsx",
1774
+ "type": "registry:ui",
1775
+ "target": "components/substrate/text-area.tsx"
1776
+ }
1777
+ ],
1778
+ "author": "George Drury <info@georgedrury.co.uk>"
1779
+ },
1780
+ {
1781
+ "name": "toast",
1782
+ "type": "registry:ui",
1783
+ "title": "Toast",
1784
+ "description": "Notification toast with undo support, powered by Sonner. Used for action confirmations, errors, and undo-able deletions.",
1785
+ "categories": [
1786
+ "substrate",
1787
+ "ui"
1788
+ ],
1789
+ "dependencies": [
1790
+ "sonner"
1791
+ ],
1792
+ "meta": {
1793
+ "example": "toast(\"Element deleted\", { action: { label: \"Undo\", onClick: undo } })",
1794
+ "lineage": [
1795
+ {
1796
+ "name": "Substrate"
1797
+ }
1798
+ ]
1799
+ },
1800
+ "files": [
1801
+ {
1802
+ "path": "registry/substrate/components/toast.tsx",
1803
+ "type": "registry:ui",
1804
+ "target": "components/substrate/toast.tsx"
1805
+ }
1806
+ ],
1807
+ "author": "George Drury <info@georgedrury.co.uk>"
1808
+ },
1809
+ {
1810
+ "name": "toggle",
1811
+ "type": "registry:ui",
1812
+ "title": "Toggle",
1813
+ "description": "Boolean toggle switch input with label and design tool styling. Built on Radix Toggle.",
1814
+ "categories": [
1815
+ "substrate",
1816
+ "ui",
1817
+ "form"
1818
+ ],
1819
+ "dependencies": [
1820
+ "radix-ui"
1821
+ ],
1822
+ "meta": {
1823
+ "example": "<Toggle pressed={visible} onPressedChange={setVisible}>Visible</Toggle>",
1824
+ "lineage": [
1825
+ {
1826
+ "name": "Radix"
1827
+ },
1828
+ {
1829
+ "name": "Substrate"
1830
+ }
1831
+ ]
1832
+ },
1833
+ "files": [
1834
+ {
1835
+ "path": "registry/substrate/components/toggle.tsx",
1836
+ "type": "registry:ui",
1837
+ "target": "components/substrate/toggle.tsx"
1838
+ }
1839
+ ],
1840
+ "author": "George Drury <info@georgedrury.co.uk>"
1841
+ },
1842
+ {
1843
+ "name": "toggle-group",
1844
+ "type": "registry:ui",
1845
+ "title": "Toggle Group",
1846
+ "description": "Grouped set of toggles for single or multi-select choices. Built on Radix ToggleGroup.",
1847
+ "categories": [
1848
+ "substrate",
1849
+ "ui",
1850
+ "form"
1851
+ ],
1852
+ "dependencies": [
1853
+ "radix-ui"
1854
+ ],
1855
+ "registryDependencies": [
1856
+ "toggle"
1857
+ ],
1858
+ "meta": {
1859
+ "example": "<ToggleGroup type=\"single\" value={align} onValueChange={setAlign}><ToggleGroupItem value=\"left\">Left</ToggleGroupItem><ToggleGroupItem value=\"center\">Center</ToggleGroupItem><ToggleGroupItem value=\"right\">Right</ToggleGroupItem></ToggleGroup>",
1860
+ "lineage": [
1861
+ {
1862
+ "name": "Radix"
1863
+ },
1864
+ {
1865
+ "name": "Substrate"
1866
+ }
1867
+ ]
1868
+ },
1869
+ "files": [
1870
+ {
1871
+ "path": "registry/substrate/components/toggle-group.tsx",
1872
+ "type": "registry:ui",
1873
+ "target": "components/substrate/toggle-group.tsx"
1874
+ }
1875
+ ],
1876
+ "author": "George Drury <info@georgedrury.co.uk>"
1877
+ },
1878
+ {
1879
+ "name": "tree-list",
1880
+ "type": "registry:ui",
1881
+ "title": "Tree List",
1882
+ "description": "Hierarchical tree view with expand/collapse, selection, and drag-to-reorder. Used for scene graphs and nested layer structures.",
1883
+ "categories": [
1884
+ "substrate",
1885
+ "ui",
1886
+ "control"
1887
+ ],
1888
+ "dependencies": [
1889
+ "@remixicon/react"
1890
+ ],
1891
+ "meta": {
1892
+ "example": "<TreeList items={treeData} selectedId={selectedId} onSelect={setSelectedId} />",
1893
+ "lineage": [
1894
+ {
1895
+ "name": "Substrate"
1896
+ }
1897
+ ]
1898
+ },
1899
+ "files": [
1900
+ {
1901
+ "path": "registry/substrate/components/tree-list.tsx",
1902
+ "type": "registry:ui",
1903
+ "target": "components/substrate/tree-list.tsx"
1904
+ }
1905
+ ],
1906
+ "author": "George Drury <info@georgedrury.co.uk>"
1907
+ },
1908
+ {
1909
+ "name": "zoom-controls",
1910
+ "type": "registry:ui",
1911
+ "title": "Zoom Controls",
1912
+ "description": "Zoom in, zoom out, and reset buttons with percentage display. Typically placed in the status bar or toolbar.",
1913
+ "categories": [
1914
+ "substrate",
1915
+ "ui",
1916
+ "chrome"
1917
+ ],
1918
+ "dependencies": [
1919
+ "@remixicon/react"
1920
+ ],
1921
+ "meta": {
1922
+ "example": "<ZoomControls zoom={zoom} onZoomIn={zoomIn} onZoomOut={zoomOut} onReset={resetZoom} />",
1923
+ "lineage": [
1924
+ {
1925
+ "name": "Substrate"
1926
+ }
1927
+ ]
1928
+ },
1929
+ "files": [
1930
+ {
1931
+ "path": "registry/substrate/components/zoom-controls.tsx",
1932
+ "type": "registry:ui",
1933
+ "target": "components/substrate/zoom-controls.tsx"
1934
+ }
1935
+ ],
1936
+ "author": "George Drury <info@georgedrury.co.uk>"
1937
+ }
1938
+ ]
1939
+ }