@substrate-kit/cli 0.1.1 → 0.2.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 (146) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/LICENSE +21 -0
  3. package/README.md +25 -8
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +10 -60
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/add.d.ts +1 -0
  8. package/dist/commands/add.d.ts.map +1 -1
  9. package/dist/commands/add.js +51 -106
  10. package/dist/commands/add.js.map +1 -1
  11. package/dist/commands/docs.d.ts +4 -2
  12. package/dist/commands/docs.d.ts.map +1 -1
  13. package/dist/commands/docs.js +33 -54
  14. package/dist/commands/docs.js.map +1 -1
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +158 -122
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/index.js +0 -0
  19. package/dist/mcp/server.d.ts.map +1 -1
  20. package/dist/mcp/server.js +8 -7
  21. package/dist/mcp/server.js.map +1 -1
  22. package/dist/mcp/tools/get-component.d.ts +1 -1
  23. package/dist/mcp/tools/get-component.d.ts.map +1 -1
  24. package/dist/mcp/tools/get-component.js +10 -6
  25. package/dist/mcp/tools/get-component.js.map +1 -1
  26. package/dist/mcp/tools/get-docs.d.ts +17 -0
  27. package/dist/mcp/tools/get-docs.d.ts.map +1 -0
  28. package/dist/mcp/tools/get-docs.js +23 -0
  29. package/dist/mcp/tools/get-docs.js.map +1 -0
  30. package/dist/mcp/tools/install.d.ts +2 -1
  31. package/dist/mcp/tools/install.d.ts.map +1 -1
  32. package/dist/mcp/tools/install.js +19 -30
  33. package/dist/mcp/tools/install.js.map +1 -1
  34. package/dist/mcp/tools/search.d.ts +1 -1
  35. package/dist/mcp/tools/search.d.ts.map +1 -1
  36. package/dist/mcp/tools/search.js +2 -4
  37. package/dist/mcp/tools/search.js.map +1 -1
  38. package/dist/{mcp/types.d.ts → registry.d.ts} +6 -1
  39. package/dist/registry.d.ts.map +1 -0
  40. package/dist/registry.js +48 -0
  41. package/dist/registry.js.map +1 -0
  42. package/dist/utils/agents-file.d.ts +4 -0
  43. package/dist/utils/agents-file.d.ts.map +1 -0
  44. package/dist/utils/agents-file.js +36 -0
  45. package/dist/utils/agents-file.js.map +1 -0
  46. package/dist/utils/docs.d.ts +7 -0
  47. package/dist/utils/docs.d.ts.map +1 -0
  48. package/dist/utils/docs.js +28 -0
  49. package/dist/utils/docs.js.map +1 -0
  50. package/dist/utils/shadcn.d.ts +12 -0
  51. package/dist/utils/shadcn.d.ts.map +1 -0
  52. package/dist/utils/shadcn.js +29 -0
  53. package/dist/utils/shadcn.js.map +1 -0
  54. package/dist/utils/version.d.ts +3 -0
  55. package/dist/utils/version.d.ts.map +1 -0
  56. package/dist/utils/version.js +8 -0
  57. package/dist/utils/version.js.map +1 -0
  58. package/docs/components/action.mdx +30 -0
  59. package/docs/components/alignment-controls.mdx +30 -0
  60. package/docs/components/badge.mdx +22 -0
  61. package/docs/components/breadcrumbs.mdx +25 -0
  62. package/docs/components/collapsible-pane.mdx +35 -0
  63. package/docs/components/colour-picker.mdx +66 -0
  64. package/docs/components/command-palette.mdx +36 -0
  65. package/docs/components/context-menu.mdx +31 -0
  66. package/docs/components/controls-timeline.mdx +107 -0
  67. package/docs/components/controls.mdx +168 -0
  68. package/docs/components/design-canvas.mdx +51 -0
  69. package/docs/components/document-tabs.mdx +25 -0
  70. package/docs/components/easing-curve-editor.mdx +85 -0
  71. package/docs/components/empty-state.mdx +26 -0
  72. package/docs/components/gallery.mdx +60 -0
  73. package/docs/components/history-controls.mdx +47 -0
  74. package/docs/components/image-picker.mdx +50 -0
  75. package/docs/components/layer-list.mdx +36 -0
  76. package/docs/components/node.mdx +85 -0
  77. package/docs/components/number-input.mdx +44 -0
  78. package/docs/components/number-slider.mdx +32 -0
  79. package/docs/components/pane.mdx +39 -0
  80. package/docs/components/panel.mdx +28 -0
  81. package/docs/components/popover.mdx +32 -0
  82. package/docs/components/progress-bar.mdx +24 -0
  83. package/docs/components/resizer.mdx +24 -0
  84. package/docs/components/select.mdx +31 -0
  85. package/docs/components/shortcut-overlay.mdx +43 -0
  86. package/docs/components/slider.mdx +20 -0
  87. package/docs/components/spring-editor.mdx +85 -0
  88. package/docs/components/status-bar.mdx +42 -0
  89. package/docs/components/surface.mdx +47 -0
  90. package/docs/components/swatch-palette.mdx +36 -0
  91. package/docs/components/text-area.mdx +26 -0
  92. package/docs/components/timeline.mdx +96 -0
  93. package/docs/components/toast.mdx +42 -0
  94. package/docs/components/toggle-group.mdx +40 -0
  95. package/docs/components/toggle.mdx +27 -0
  96. package/docs/components/toolbar.mdx +24 -0
  97. package/docs/components/tree-list.mdx +46 -0
  98. package/docs/components/xy-pad.mdx +49 -0
  99. package/docs/hooks/use-clipboard.mdx +70 -0
  100. package/docs/hooks/use-drag-reorder.mdx +60 -0
  101. package/docs/hooks/use-selection.mdx +68 -0
  102. package/docs/hooks/use-undoable.mdx +83 -0
  103. package/docs/hooks/use-viewport.mdx +75 -0
  104. package/docs/utilities/bounding-box.mdx +76 -0
  105. package/docs/utilities/keyboard-shortcuts.mdx +64 -0
  106. package/docs/utilities/snap.mdx +73 -0
  107. package/package.json +6 -3
  108. package/registry.json +331 -16
  109. package/skills/3d-scene/SKILL.md +2 -1
  110. package/skills/animation/SKILL.md +2 -1
  111. package/skills/canvas-2d/SKILL.md +68 -6
  112. package/skills/composing-panels/SKILL.md +9 -12
  113. package/skills/data-visualisation/SKILL.md +2 -1
  114. package/skills/image-generation/SKILL.md +2 -1
  115. package/skills/install-components/SKILL.md +22 -16
  116. package/skills/scaffold-playground/SKILL.md +42 -22
  117. package/skills/substrate-canvas/SKILL.md +5 -0
  118. package/skills/substrate-controls/SKILL.md +57 -2
  119. package/skills/substrate-interaction/SKILL.md +19 -10
  120. package/skills/substrate-scaffold/SKILL.md +4 -4
  121. package/skills/theming/SKILL.md +8 -2
  122. package/skills/wire-interactions/SKILL.md +6 -3
  123. package/templates/agents-section.md +41 -0
  124. package/dist/commands/browse.d.ts +0 -2
  125. package/dist/commands/browse.d.ts.map +0 -1
  126. package/dist/commands/browse.js +0 -25
  127. package/dist/commands/browse.js.map +0 -1
  128. package/dist/commands/create.d.ts +0 -9
  129. package/dist/commands/create.d.ts.map +0 -1
  130. package/dist/commands/create.js +0 -415
  131. package/dist/commands/create.js.map +0 -1
  132. package/dist/commands/variables.d.ts +0 -4
  133. package/dist/commands/variables.d.ts.map +0 -1
  134. package/dist/commands/variables.js +0 -111
  135. package/dist/commands/variables.js.map +0 -1
  136. package/dist/mcp/registry.d.ts +0 -3
  137. package/dist/mcp/registry.d.ts.map +0 -1
  138. package/dist/mcp/registry.js +0 -43
  139. package/dist/mcp/registry.js.map +0 -1
  140. package/dist/mcp/tools/theme.d.ts +0 -10
  141. package/dist/mcp/tools/theme.d.ts.map +0 -1
  142. package/dist/mcp/tools/theme.js +0 -37
  143. package/dist/mcp/tools/theme.js.map +0 -1
  144. package/dist/mcp/types.d.ts.map +0 -1
  145. package/dist/mcp/types.js +0 -2
  146. package/dist/mcp/types.js.map +0 -1
@@ -167,7 +167,7 @@ Use Pane/Action/Slider to build parameter controls:
167
167
  - **Parameters pane** — sliders for inference steps, CFG scale, seed, image size selector
168
168
  - **Style pane** (optional) — style preset buttons, LoRA weight sliders
169
169
 
170
- The Action/ActionLabel/ActionControls pattern works well for each parameter row.
170
+ For this kind of local, tunable state, prefer `useControlsController` with `<Controls />` over hand-built rows: one config object gives the sliders, selects and seed field, plus reset, versions and a copy button, and `setValues` loads a saved generation (see **substrate-controls**). Use the Action/ActionLabel/ActionControls pattern when a row needs a custom layout.
171
171
 
172
172
  ## Interaction patterns
173
173
 
@@ -211,6 +211,7 @@ Some examples of what this surface enables:
211
211
 
212
212
  ## Related reference skills
213
213
 
214
+ - **scaffold-playground** — the craft rules and the checklist to run before you say it's done
214
215
  - **substrate-scaffold** — Toolbar, Panel, StatusBar for the app shell
215
216
  - **substrate-controls** — Slider, NumberInput, TextArea, Select for generation parameters
216
217
  - **substrate-feedback** — Toast, ProgressBar for generation status, EmptyState for no results
@@ -25,8 +25,8 @@ npx substrate-kit add slider number-input toggle colour-picker
25
25
  Install every component in a category:
26
26
 
27
27
  ```bash
28
- npx substrate-kit add --category substrate/ui/form
29
- npx substrate-kit add --category substrate/ui/control
28
+ npx substrate-kit add --category form
29
+ npx substrate-kit add --category control
30
30
  ```
31
31
 
32
32
  Open an interactive picker (no arguments):
@@ -45,16 +45,17 @@ npx substrate-kit add --list-categories
45
45
 
46
46
  - Run from a project created with `npx create-substrate` or initialised with `npx @substrate-kit/cli init`. Both add `@substrate-kit/cli` as a dev dependency, which is what makes `npx substrate-kit` resolve. The CLI looks for `components.json` — it will error if it's missing.
47
47
  - Components land in `registry/substrate/...` and related aliases defined in `components.json`.
48
- - Under the hood the CLI delegates to `npx shadcn@latest add` against `https://substrate.georgedrury.co.uk/r/<name>`. Do **not** use the shadcn CLI directly — always go through `substrate-kit add` so the CLI can print theme-override hints and keep the workflow uniform.
48
+ - Under the hood the CLI delegates to `npx shadcn@latest add` against `https://substrate.georgedrury.co.uk/r/<name>`, in one call for all the names you give it, retrying if the network drops. Do **not** use the shadcn CLI directly — always go through `substrate-kit add` so the CLI can print theme-override hints and keep the workflow uniform.
49
+ - If the Substrate MCP server is connected, `search_components`, `get_component`, `get_docs` and `install_components` do the same jobs without a shell.
49
50
 
50
51
  ### Related CLI commands
51
52
 
52
53
  | Command | What it does |
53
54
  | --- | --- |
54
55
  | `substrate-kit add <name>` | Install one or more components |
55
- | `substrate-kit docs <name>` | Read component docs in the terminal |
56
- | `substrate-kit browse <name>` | Open component docs in the browser |
57
- | `substrate-kit variables <name>` | Print the theme-override CSS variables for a component |
56
+ | `substrate-kit docs <name>` | Read component docs in the terminal: props, theme variables, usage |
57
+ | `substrate-kit docs <name> --open` | Open the component's docs page in the browser |
58
+ | `substrate-kit docs --list` | List every component |
58
59
 
59
60
  ---
60
61
 
@@ -62,10 +63,11 @@ npx substrate-kit add --list-categories
62
63
 
63
64
  When you catch yourself about to write a custom version of any of these, stop and run `substrate-kit add <name>` instead.
64
65
 
65
- ### Form controls — `substrate/ui/form`
66
+ ### Form controls — `form`
66
67
 
67
68
  | Component | Command | Use for |
68
69
  | --- | --- | --- |
70
+ | Controls | `substrate-kit add controls` | Whole parameter panels from a config object (`useControls` + `<Controls />`) — reach for this before hand-wiring rows |
69
71
  | Slider | `substrate-kit add slider` | Any range input — opacity, volume, zoom, numeric sliders |
70
72
  | Number Input | `substrate-kit add number-input` | Numeric property fields with drag-to-scrub on the label |
71
73
  | Number Slider | `substrate-kit add number-slider` | Combined slider + numeric input on one row |
@@ -73,11 +75,13 @@ When you catch yourself about to write a custom version of any of these, stop an
73
75
  | Toggle | `substrate-kit add toggle` | Binary on/off switches (snap, visibility, lock) |
74
76
  | Text Area | `substrate-kit add text-area` | Auto-resizing multi-line text input |
75
77
 
76
- ### Higher-level controls — `substrate/ui/control`
78
+ ### Higher-level controls — `control`
77
79
 
78
80
  | Component | Command | Use for |
79
81
  | --- | --- | --- |
80
82
  | Colour Picker | `substrate-kit add colour-picker` | HSV picker with hex/RGB + opacity |
83
+ | XY Pad | `substrate-kit add xy-pad` | Drag or arrow-key pad that sets two values at once |
84
+ | Image Picker | `substrate-kit add image-picker` | Thumbnail grid for choosing or uploading an image |
81
85
  | Swatch Palette | `substrate-kit add swatch-palette` | Grid of preset colours |
82
86
  | Alignment Controls | `substrate-kit add alignment-controls` | Horizontal/vertical align + distribute |
83
87
  | Collapsible Pane | `substrate-kit add collapsible-pane` | Expandable section inside a panel |
@@ -85,7 +89,7 @@ When you catch yourself about to write a custom version of any of these, stop an
85
89
  | Tree List | `substrate-kit add tree-list` | Hierarchical tree with expand/collapse and drag reorder |
86
90
  | Node | `substrate-kit add node` | Card-based node with typed input/output ports |
87
91
 
88
- ### Chrome (app shell) — `substrate/ui/chrome`
92
+ ### Chrome (app shell) — `chrome`
89
93
 
90
94
  | Component | Command | Use for |
91
95
  | --- | --- | --- |
@@ -99,7 +103,7 @@ When you catch yourself about to write a custom version of any of these, stop an
99
103
  | Status Bar | `substrate-kit add status-bar` | Bottom bar for tool/selection/zoom info |
100
104
  | Zoom Controls | `substrate-kit add zoom-controls` | Zoom in/out/reset with percentage display |
101
105
 
102
- ### Core UI — `substrate/ui`
106
+ ### Core UI — `ui`
103
107
 
104
108
  | Component | Command | Use for |
105
109
  | --- | --- | --- |
@@ -114,20 +118,22 @@ When you catch yourself about to write a custom version of any of these, stop an
114
118
  | Progress Bar | `substrate-kit add progress-bar` | Horizontal progress indicator |
115
119
  | Toast | `substrate-kit add toast` | Notifications with undo, powered by Sonner |
116
120
 
117
- ### Animation — `substrate/ui/animation`
121
+ ### Animation — `animation`
118
122
 
119
123
  | Component | Command | Use for |
120
124
  | --- | --- | --- |
121
125
  | Timeline | `substrate-kit add timeline` | Ruler + playhead + tracks + keyframe diamonds |
122
126
  | Easing Curve Editor | `substrate-kit add easing-curve-editor` | Draggable cubic-bezier editor |
127
+ | Spring Editor | `substrate-kit add spring-editor` | Spring curve preview with time or physics sliders |
128
+ | Controls Timeline | `substrate-kit add controls-timeline` | Clips defined in code, tuned in a scrubbable timeline (`useControlsTimeline` + `<ControlsTimeline />`) |
123
129
 
124
- ### Visualisation — `substrate/ui/visualization`
130
+ ### Visualisation — `visualization`
125
131
 
126
132
  | Component | Command | Use for |
127
133
  | --- | --- | --- |
128
134
  | Gallery | `substrate-kit add gallery` | Responsive thumbnail grid with selection and actions |
129
135
 
130
- ### 2D canvas — `substrate/canvas`
136
+ ### 2D canvas — `canvas`
131
137
 
132
138
  | Component | Command | Use for |
133
139
  | --- | --- | --- |
@@ -136,7 +142,7 @@ When you catch yourself about to write a custom version of any of these, stop an
136
142
  | Hit Test | `substrate-kit add hit-test` | Point-in-element geometry |
137
143
  | Element Factory | `substrate-kit add element-factory` | Factories for rectangle/ellipse/text/etc |
138
144
 
139
- ### Canvas hooks — `substrate/canvas` & `substrate/hook`
145
+ ### Canvas hooks — `canvas` and `hook`
140
146
 
141
147
  | Hook | Command | Use for |
142
148
  | --- | --- | --- |
@@ -152,7 +158,7 @@ When you catch yourself about to write a custom version of any of these, stop an
152
158
  | useViewport | `substrate-kit add use-viewport` | Pan/zoom state for canvas surfaces |
153
159
  | useUndoable | `substrate-kit add use-undoable` | Lightweight undo/redo stack |
154
160
 
155
- ### Stores — `substrate/store`
161
+ ### Stores — `store`
156
162
 
157
163
  | Store | Command | Use for |
158
164
  | --- | --- | --- |
@@ -161,7 +167,7 @@ When you catch yourself about to write a custom version of any of these, stop an
161
167
  | panel-store | `substrate-kit add panel-store` | Left/right panel visibility, open panes |
162
168
  | animation-store | `substrate-kit add animation-store` | Playback: duration, time, play/pause |
163
169
 
164
- ### Libraries — `substrate/lib`
170
+ ### Libraries — `lib`
165
171
 
166
172
  | Lib | Command | Use for |
167
173
  | --- | --- | --- |
@@ -14,13 +14,13 @@ A Substrate playground is a creative app built from composable primitives: a **s
14
14
 
15
15
  ## Prerequisites
16
16
 
17
- A Next.js 14+ project with Tailwind CSS and the shadcn CLI configured. If you don't have one, run:
17
+ A Vite or Next.js project with React and Tailwind CSS v4. If you don't have one, run:
18
18
 
19
19
  ```bash
20
20
  npx create-substrate my-playground
21
21
  ```
22
22
 
23
- This scaffolds a full project with dependencies, globals.css with Substrate tokens, and a starter playground page.
23
+ This scaffolds a Vite + React project with dependencies, `globals.css` with Substrate tokens, and a starter page for the surface you pick. It asks for a name and a surface; pass `--surface <type>` (or `--yes`) when there is no terminal.
24
24
 
25
25
  To add Substrate to an existing project instead:
26
26
 
@@ -28,7 +28,7 @@ To add Substrate to an existing project instead:
28
28
  npx @substrate-kit/cli init
29
29
  ```
30
30
 
31
- This installs skills, CLAUDE.md, components.json, and registers the MCP server.
31
+ This detects Vite or Next, installs the skills, adds Substrate guidance to `CLAUDE.md` and `AGENTS.md` without touching the rest of them, adds the `@substrate` registry to `components.json`, and registers the MCP server in `.mcp.json`.
32
32
 
33
33
  ## 1. Choose your surface
34
34
 
@@ -36,11 +36,12 @@ The surface is the heart of the playground — the central area where the main i
36
36
 
37
37
  | Surface | Best for | Skill |
38
38
  | ------------------ | --------------------------------------------------------- | --------------------------------------------- |
39
- | 2D canvas | Shape editors, diagrams, whiteboards, node graphs | [canvas-2d](./canvas-2d.md) |
40
- | 3D scene | Product viewers, scene builders, shader playgrounds | [3d-scene](./3d-scene.md) |
41
- | Animation | Timeline editors, motion prototyping, easing explorers | [animation](./animation.md) |
42
- | Image generation | Prompt-driven image tools, texture generators, inpainting | [image-generation](./image-generation.md) |
43
- | Data visualisation | Chart editors, dashboard builders, data explorers | [data-visualisation](./data-visualisation.md) |
39
+ | 2D canvas | Shape editors, diagrams, whiteboards, node graphs | `canvas-2d` |
40
+ | 3D scene | Product viewers, scene builders, shader playgrounds | `3d-scene` |
41
+ | Animation | Timeline editors, motion prototyping, easing explorers | `animation` |
42
+ | Image generation | Prompt-driven image tools, texture generators, inpainting | `image-generation` |
43
+ | Data visualisation | Chart editors, dashboard builders, data explorers | `data-visualisation` |
44
+ | Node editor | Visual programming, shader graphs, data pipelines | `substrate-nodes` |
44
45
 
45
46
  Read the relevant surface skill for setup instructions, dependencies, and architecture patterns.
46
47
 
@@ -50,17 +51,13 @@ Regardless of surface type, most playgrounds use the same chrome components:
50
51
 
51
52
  ```bash
52
53
  # UI chrome
53
- npx shadcn@latest add https://substrate.georgedrury.co.uk/r/toolbar
54
- npx shadcn@latest add https://substrate.georgedrury.co.uk/r/panel
55
- npx shadcn@latest add https://substrate.georgedrury.co.uk/r/pane
56
- npx shadcn@latest add https://substrate.georgedrury.co.uk/r/action
57
- npx shadcn@latest add https://substrate.georgedrury.co.uk/r/slider
54
+ npx substrate-kit add toolbar panel pane action slider
58
55
  ```
59
56
 
60
57
  For the 2D canvas surface specifically, also install:
61
58
 
62
59
  ```bash
63
- npx shadcn@latest add https://substrate.georgedrury.co.uk/r/design-canvas
60
+ npx substrate-kit add design-canvas
64
61
  ```
65
62
 
66
63
  ## 3. Compose the layout
@@ -70,15 +67,15 @@ Every playground follows the same layout pattern — surface in the centre, opti
70
67
  ```tsx
71
68
  "use client"
72
69
 
73
- import { Panel } from "@/registry/substrate/components/panel"
70
+ import { Panel } from "@/components/substrate/panel"
74
71
  import {
75
72
  Toolbar,
76
73
  ToolbarToggleGroup,
77
74
  ToolbarToggle,
78
75
  ToolbarSeparator,
79
- } from "@/registry/substrate/components/toolbar"
80
- import { usePanelStore } from "@/registry/substrate/stores/panel-store"
81
- import { useToolStore } from "@/registry/substrate/stores/tool-store"
76
+ } from "@/components/substrate/toolbar"
77
+ import { usePanelStore } from "@/stores/substrate/panel-store" // npx substrate-kit add panel-store
78
+ import { useToolStore } from "@/stores/substrate/tool-store"
82
79
 
83
80
  export default function PlaygroundPage() {
84
81
  const leftPanel = usePanelStore((s) => s.leftPanel)
@@ -128,10 +125,33 @@ These are surface-agnostic — they work the same whether you're building a 3D s
128
125
  ## 5. Next steps
129
126
 
130
127
  - **Build your surface** — read the surface skill for your chosen type
131
- - **Add property panels** — see [composing panels](./composing-panels.md)
132
- - **Wire keyboard shortcuts** — see [wire interactions](./wire-interactions.md)
133
- - **Create custom tools** — see [create custom tool](./create-custom-tool.md)
134
- - **Customise appearance** — see [theming](./theming.md)
128
+ - **Add property panels** — see `composing-panels`
129
+ - **Wire keyboard shortcuts** — see `wire-interactions`
130
+ - **Create custom tools** — see `create-custom-tool`
131
+ - **Customise appearance** — see `theming`
132
+
133
+ ## 6. Craft rules
134
+
135
+ Substrate tools are dense, so the details decide whether one feels finished. Apply these to everything you build, including your own components.
136
+
137
+ - **Density:** chrome controls are 28px (`h-7`) with `text-xs`. Keep that. Don't enlarge inputs or buttons to fill space; a touch layout can use `size-9` or larger instead.
138
+ - **Transitions:** name the properties (`transition-[color,background-color,box-shadow]`), never `transition-all`. Use about 150ms. Pressable buttons get `active:scale-[0.96]`, never below 0.95. Anything that moves must respect `prefers-reduced-motion`; the starter's `globals.css` already does.
139
+ - **Depth:** panels are separated from the canvas by a border. Floating things (toolbar, popovers, menus) use a shadow, not a border. When a rounded child sits inside a rounded parent, its radius is the parent's minus the padding between them.
140
+ - **Both themes:** use tokens (`bg-background`, `text-foreground`, `bg-muted`, `--canvas`), never hex values, in chrome. Content drawn on the board must be visible on both the light and the dark canvas, so check starter shapes and text in both. The element factories' default ink is safe; a hard-coded navy title is invisible on dark.
141
+ - **Changing numbers** (zoom, coordinates, counts, timers) get `tabular-nums`, so digits don't jiggle as they update.
142
+ - **No layout shift:** reserve space for anything that loads or appears. Empty states teach: say what goes there and give the action that creates it, using `EmptyState`.
143
+ - **Keyboard:** every tool and action has a shortcut, listed in `ShortcutOverlay`. `DesignCanvas` already installs tool keys, undo, redo, delete, duplicate, select all and zoom, so don't register those again: they would run twice.
144
+ - **Labels:** every icon-only button has an `aria-label`. Leave focus rings visible and neutral.
145
+ - **First paint:** restore saved state before the first render. Defaulting first and correcting afterwards flashes the wrong state.
146
+
147
+ ### Before you say it's done
148
+
149
+ 1. `npm run build` passes and the console is clean.
150
+ 2. Open it in light and dark and look at it. Starter content, text and borders must be readable in both.
151
+ 3. Make each kind of edit, then undo and redo it: move, resize, create, delete, property changes, reorder. Pan or zoom after an edit and undo again; the view must stay put.
152
+ 4. Tab through the controls, and use every shortcut you listed.
153
+ 5. Reload. The board and the zoom come back.
154
+ 6. Click-create each tool without dragging, with a long name and with many layers.
135
155
 
136
156
  ## Component reference skills
137
157
 
@@ -156,6 +156,11 @@ Core geometry functions.
156
156
  | `screenToWorld(point, camera)` / `worldToScreen(point, camera)` | Coordinate transforms |
157
157
  | `clamp(value, min, max)` | Numeric clamp |
158
158
  | `distance(a, b)` | Euclidean distance |
159
+ | `angleBetween(from, to)` / `normalizeAngle(deg)` / `snapAngle(deg, step)` | Angle of a line, wrapped to [-180, 180), snapped to a step. Degrees, positive clockwise on screen |
160
+ | `rotatedCorners(bounds, rotation)` / `rotatedBounds(bounds, rotation)` | The corners of a rotated box, and the axis-aligned box that contains it (for marquee, fit and alignment) |
161
+ | `handlePosition(handle, bounds, rotation)` | Where a resize handle, or `"rotate"`, sits on a rotated box |
162
+ | `resizeBounds(start, handle, delta, rotation)` | Resize by dragging a handle. The opposite handle stays fixed, also when rotated |
163
+ | `HANDLE_SIZE`, `ROTATE_HANDLE_OFFSET`, `HANDLES` | Handle geometry shared by the renderer and hit-test |
159
164
 
160
165
  ---
161
166
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: substrate-controls
3
- description: "Substrate input and selection primitives: number input, slider, number slider, select, toggle, text area, colour picker, easing curve editor, swatch palette, and action controls. Use when building property editors, parameter forms, or any interactive control surface. Triggers on: input, slider, select, toggle, colour picker, swatch, easing, action controls, property editor, form control."
3
+ description: "Substrate input and selection primitives and config-driven panels: Controls and useControls (describe parameters as an object, get a tuning panel), the controls timeline for tuning animation clips, number input, slider, number slider, select, toggle, text area, colour picker, easing curve editor, spring editor, XY pad, image picker, swatch palette, and action controls. Use when building property editors, parameter or settings panels, tuning values by eye, or any interactive control surface. Triggers on: useControls, Controls, controls panel, tweak values, tuning, parameters, input, slider, select, toggle, colour picker, spring, easing, XY pad, swatch, action controls, property editor, form control, useControlsTimeline."
4
4
  user-invocable: true
5
5
  ---
6
6
 
@@ -61,6 +61,61 @@ The same pattern is used by **Toolbar** (compaction) and **PaneHeader** (auto-po
61
61
 
62
62
  ## Components in this domain
63
63
 
64
+ ### Controls and useControls
65
+
66
+ `registry/substrate/components/controls.tsx`, `registry/substrate/hooks/use-controls.ts`
67
+
68
+ Config-driven panels. Describe parameters as an object, get typed values back, and render every panel with `<Controls />`. Built on DialKit's headless store; the rows are the Substrate controls below.
69
+
70
+ ```tsx
71
+ const chart = useControls("Chart", {
72
+ months: [12, 3, 12, 1], // [default, min, max, step]
73
+ grid: true,
74
+ colour: "#a78bfa",
75
+ metric: { type: "select", options: ["revenue", "users"] },
76
+ style: { strokeWidth: [2, 1, 6] }, // nested object = collapsible folder
77
+ })
78
+
79
+ <Panel>
80
+ <Controls />
81
+ </Panel>
82
+ ```
83
+
84
+ **Config types**: number tuple or bare number (NumberSlider), boolean (Toggle), string (TextArea), hex string (ColourPicker), `{ type: "select" }`, `{ type: "easing" }` (EasingCurveEditor), `{ type: "spring" }` with `visualDuration`/`bounce` or `stiffness`/`damping`/`mass` (SpringEditor; easing and spring share a row with a type switch), `{ type: "image", options }` (ImagePicker, uploads become data URLs), `{ type: "pad", x, y }` with slider-style axis tuples (XYPad, returns `{ x, y }`, positive y is up), `{ type: "action" }` with the `onAction` option, nested object (folder).
85
+
86
+ **Options**: `id`, `persist`, `onAction`, `shortcuts` (by control path, e.g. `{ radius: { key: "r" }, visible: { key: "v" } }`: hold a slider's key and scroll, or `interaction: "drag"`/`"move"`; press a toggle's key). **Controls prop**: `panel` to render a single panel by name. Each panel header has a versions menu (DialKit presets), a copy button that copies the values as an agent instruction, and reset.
87
+
88
+ **Setting values from code**: `useControlsController` returns `{ values, setValues, reset }` for loading saved state or presets.
89
+
90
+ **Values that belong to a selection**: mount a small component with `key={selected.id}` that seeds its config from the selected item (hold it in `useState` so it is built once) and writes `useControls` values back in an effect. Only do this when nothing else edits those values while the item is selected.
91
+
92
+ **When to use**: The default for any panel of tunable parameters with local state – chart settings, generation parameters, material properties. Compose the individual controls by hand instead when values live in a store with selection and undo (as in the design editor's property panes), or when a row needs a custom layout.
93
+
94
+ ---
95
+
96
+ ### ControlsTimeline and useControlsTimeline
97
+
98
+ `registry/substrate/components/controls-timeline.tsx`, `registry/substrate/hooks/use-controls-timeline.ts`
99
+
100
+ Animation clips defined in code, tuned in a timeline editor. Built on DialKit's headless timeline. Bind `timeline.<clip>.current` to style so the UI follows the playhead; `<ControlsTimeline />` scrubs, moves and resizes clips and edits their values in a popover.
101
+
102
+ ```tsx
103
+ const timeline = useControlsTimeline("Card", {
104
+ enter: { at: 0, duration: 0.6, from: { y: 24, opacity: 0 }, to: { y: 0, opacity: 1 }, transition: { type: "spring", visualDuration: 0.5, bounce: 0.2 } },
105
+ badge: { at: 0.6, from: { scale: 0 }, steps: [{ duration: 0.2, to: { scale: 1.2 } }, { duration: 0.2, to: { scale: 1 } }] },
106
+ glow: { at: 1, props: { blur: { from: 0, to: 24, duration: 0.6 } } },
107
+ }, { loop: true })
108
+
109
+ <div style={{ opacity: timeline.enter.current.opacity }} />
110
+ <ControlsTimeline />
111
+ ```
112
+
113
+ **Options**: `id`, `persist`, `autoplay` (default true), `loop` (`true` or `{ from }`). **Controls**: `play`, `pause`, `replay`, `seek`.
114
+
115
+ **When to use**: tuning entrance and choreography timing by eye. Once tuned, copy the values and move them into the production animation.
116
+
117
+ ---
118
+
64
119
  ### NumberInput
65
120
 
66
121
  `registry/substrate/components/number-input.tsx`
@@ -131,7 +186,7 @@ Auto-resizing textarea with `minRows` / `maxRows`. Shares border/bg styling with
131
186
 
132
187
  `registry/substrate/components/colour-picker.tsx`
133
188
 
134
- HSV colour picker with hex/RGB inputs and opacity slider. The swatch trigger renders `data-slot="colour-swatch"` for slot-aware composition.
189
+ Colour picker with a hex input. `value` accepts any CSS colour (hex, `oklch()`, `rgb()`, named) and `onChange` returns hex; `onStart` fires when a drag or edit begins, for undo snapshots. The swatch trigger renders `data-slot="colour-swatch"` for slot-aware composition.
135
190
 
136
191
  **When to use**: Fill, stroke, background, text colour – any colour property.
137
192
 
@@ -45,7 +45,7 @@ function handleMove(id: string, x: number, y: number) {
45
45
  }
46
46
  ```
47
47
 
48
- **Connects to**: `HistoryControls` component, `NumberInput.onStart` (push snapshot before scrub), `createKeyboardShortcuts` (⌘Z / ⌘⇧Z).
48
+ **Connects to**: `NumberInput.onStart` (push snapshot before scrub), `createKeyboardShortcuts` (⌘Z / ⌘⇧Z). The 2D canvas does not use this hook: `useDocumentStore` has its own history (`pushSnapshot`, `undo`, `redo`) that covers elements and their order, not the camera, so pan and zoom survive an undo. Call `pushSnapshot()` before every mutation you want to be undoable, including property edits.
49
49
 
50
50
  ---
51
51
 
@@ -139,7 +139,7 @@ formatShortcut({ key: "z", meta: true, shift: true }) // → "⌘+Shift+Z"
139
139
 
140
140
  Undo/redo button pair. Renders `data-slot="history-controls"` for auto-positioning in PaneHeader and Toolbar.
141
141
 
142
- **Props**: `canUndo`, `canRedo`, `onUndo`, `onRedo`
142
+ **Props**: `size` (`"sm"` or `"md"`). It takes no undo callbacks: it reads `past`/`future` and calls `undo`/`redo` on `useDocumentStore`, so it works with the canvas store out of the box. For any other undo stack (`useUndoable`), build your own pair of buttons from `canUndo`/`undo`/`canRedo`/`redo`.
143
143
 
144
144
  **Typical placement**:
145
145
  - Inside `PaneHeader` – auto-positioned to the right via `**:data-[slot=history-controls]:ml-auto`
@@ -157,7 +157,9 @@ Flat layer panel with selection, visibility, lock, rename, and reorder.
157
157
 
158
158
  **Features**:
159
159
  - `LayerItem` supports `selected`, `hovered`, `depth` props
160
- - `LayerName` enables double-click inline rename
160
+ - `LayerName` takes the name as `children` and enables double-click inline rename via `onRename`
161
+ - `LayerVisibilityToggle` and `LayerLockToggle` are controlled: `visible`/`onVisibleChange` and `locked`/`onLockedChange`
162
+ - Sorting is not built in: spread `useDragReorder`'s `getDragItemProps` on each `LayerItem`
161
163
  - `LayerActions` are hidden by default, visible on row hover
162
164
  - `LayerVisibilityToggle` and `LayerLockToggle` use eye/lock icons
163
165
 
@@ -199,8 +201,8 @@ Hierarchical tree with expand/collapse, depth indentation, and icons.
199
201
  │ → apply to store │
200
202
  ├─────────────────────────────────────────────────┤
201
203
  │ HistoryControls (in PaneHeader or Toolbar) │
202
- │ → reads canUndo/canRedo │
203
- │ → calls onUndo/onRedo │
204
+ │ → reads past/future from useDocumentStore │
205
+ │ → calls the store's undo/redo │
204
206
  ├─────────────────────────────────────────────────┤
205
207
  │ NumberInput.onStart │
206
208
  │ → pushSnapshot before scrub begins │
@@ -231,7 +233,14 @@ Hierarchical tree with expand/collapse, depth indentation, and icons.
231
233
  ```tsx
232
234
  function LayerPanel() {
233
235
  const { selectedIds, select, isSelected } = useSelection({ items: elementIds })
234
- const { getDragItemProps } = useDragReorder({ items: elements, onReorder: reorderElements })
236
+ const setElementOrder = useDocumentStore((s) => s.setElementOrder)
237
+ const { getDragItemProps } = useDragReorder({
238
+ items: elements,
239
+ onReorder: (next) => {
240
+ pushSnapshot()
241
+ setElementOrder(next.map((el) => el.id))
242
+ },
243
+ })
235
244
 
236
245
  return (
237
246
  <LayerList>
@@ -244,21 +253,21 @@ function LayerPanel() {
244
253
  {...getDragItemProps(i)}
245
254
  >
246
255
  <LayerIcon colour={el.fill?.color} />
247
- <LayerName value={el.name} onRename={(name) => updateElement(el.id, { name })} />
256
+ <LayerName onRename={(name) => updateElement(el.id, { name })}>{el.name}</LayerName>
248
257
  <LayerActions>
249
258
  <LayerVisibilityToggle
250
259
  visible={el.visible}
251
- onToggle={() => updateElement(el.id, { visible: !el.visible })}
260
+ onVisibleChange={(visible) => updateElement(el.id, { visible })}
252
261
  />
253
262
  <LayerLockToggle
254
263
  locked={el.locked}
255
- onToggle={() => updateElement(el.id, { locked: !el.locked })}
264
+ onLockedChange={(locked) => updateElement(el.id, { locked })}
256
265
  />
257
266
  </LayerActions>
258
267
  </LayerItem>
259
268
  </ContextMenuTrigger>
260
269
  <ContextMenuContent>
261
- <ContextMenuItem onSelect={() => duplicateElement(el.id)}>
270
+ <ContextMenuItem onSelect={() => duplicateElements([el.id])}>
262
271
  Duplicate <ContextMenuShortcut>⌘D</ContextMenuShortcut>
263
272
  </ContextMenuItem>
264
273
  <ContextMenuItem onSelect={() => deleteElement(el.id)}>
@@ -39,9 +39,9 @@ Floating bottom bar. Renders tool buttons, separators, and groups. Uses `data-sl
39
39
  | `slider` / `slider-track` | h-6 |
40
40
  | `history-controls` | gap-0 |
41
41
 
42
- **Exports**: `Toolbar`, `ToolbarButton`, `ToolbarSeparator`, `ToolbarGroup`
42
+ **Exports**: `Toolbar`, `ToolbarToggleGroup`, `ToolbarToggle`, `ToolbarSeparator`, `ToolbarDropdown`
43
43
 
44
- **Typical use**: One per playground, positioned at the bottom. Connect each `ToolbarButton` to `useToolStore` for active-tool state.
44
+ **Typical use**: One per playground, positioned at the bottom. Put the tool buttons in a `ToolbarToggleGroup` of `ToolbarToggle`s and connect it to `useToolStore` for active-tool state.
45
45
 
46
46
  **Related**: substrate-controls (for inputs inside the toolbar), substrate-interaction (for keyboard shortcuts bound to tools)
47
47
 
@@ -181,11 +181,11 @@ Breadcrumbs show the path into nested node groups. Right panel shows properties
181
181
  <div className="flex h-screen flex-col">
182
182
  <DocumentTabList>{/* tabs */}</DocumentTabList>
183
183
  <div className="flex flex-1 overflow-hidden">
184
- <Panel side="left">{/* layers/tree */}</Panel>
184
+ <Panel position="left">{/* layers/tree */}</Panel>
185
185
  <div className="relative flex-1">
186
186
  <Surface />{/* central area */}
187
187
  </div>
188
- <Panel side="right">{/* property panes */}</Panel>
188
+ <Panel position="right">{/* property panes */}</Panel>
189
189
  </div>
190
190
  <StatusBar>{/* metadata */}</StatusBar>
191
191
  <Toolbar>{/* tools */}</Toolbar>
@@ -113,9 +113,15 @@ const CURSOR_MAP: Record<string, string> = {
113
113
  }
114
114
  ```
115
115
 
116
- ## 5. Dark mode
116
+ ## 5. Light and dark mode
117
117
 
118
- Substrate UI components automatically respect dark mode when using `next-themes` or a `.dark` class on the document. The canvas renderer needs manual dark mode handling — check a CSS variable or a store flag and swap your colour constants accordingly.
118
+ Every Substrate component works in both themes. Colours come from tokens, and the theme is chosen by a `.dark` class on `<html>`: light values live in `:root`, dark values in `.dark`.
119
+
120
+ Projects made with `create-substrate` follow the system theme through a small script in `index.html`. To force a theme, remove that script and either set `class="dark"` on `<html>` or leave it off. To add a switch, toggle that class yourself (or use `next-themes` in a Next.js app).
121
+
122
+ Canvas-drawn parts follow the theme too: the design canvas reads `--canvas` and `--canvas-foreground`, the easing curve editor draws in its text colour, and both repaint when the theme changes. In your own canvas code, read colours with `getComputedStyle` at draw time instead of hardcoding them, and use mid-tones for defaults that must read on both backgrounds.
123
+
124
+ When writing a component, use tokens (`bg-panel`, `text-muted-foreground`, `bg-foreground/10`) and check it in both themes. Avoid `bg-background` for a control's track or well: it matches the page in light mode and disappears.
119
125
 
120
126
  ## Related reference skills
121
127
 
@@ -39,6 +39,7 @@ Keyboard events (DOM)
39
39
  | `creating` | Drag with shape tool on empty canvas | Preview element dimensions | Commit new element to store |
40
40
  | `moving` | Drag on selected element | Update element positions | Commit positions |
41
41
  | `resizing` | Drag on resize handle | Update element bounds | Commit bounds |
42
+ | `rotating` | Drag on the rotate handle above a single selection | Turn the element about its centre (hold Shift to snap to 15°) | Commit rotation |
42
43
  | `marquee_selecting` | Drag on empty canvas with select tool | Draw selection rectangle | Select contained elements |
43
44
 
44
45
  ### Pointer down logic
@@ -66,7 +67,8 @@ Keyboard events (DOM)
66
67
  - "pan": update camera
67
68
  - "create": preview element (stored on drag ref, rendered by renderer)
68
69
  - "move": update element positions (delta from start)
69
- - "resize": update element bounds respecting handle position
70
+ - "resize": update element bounds with `resizeBounds`, which respects the handle and the element's rotation
71
+ - "rotate": set `rotation` from the pointer's angle around the element centre
70
72
  - "marquee": update selection rectangle
71
73
  5. Call markDirty() to trigger repaint
72
74
  ```
@@ -77,7 +79,7 @@ Keyboard events (DOM)
77
79
  1. End drag (useCanvasDrag.endDrag)
78
80
  2. Based on drag type:
79
81
  - "create": push snapshot, add element to store, select it, reset tool to select
80
- - "move"/"resize": push snapshot (positions already updated during drag)
82
+ - "move"/"resize"/"rotate": nothing to push; the snapshot was taken when the drag first moved, so a click without a drag leaves no undo step
81
83
  - "marquee": select all elements within the marquee bounds
82
84
  - "pan": nothing to commit
83
85
  ```
@@ -104,12 +106,13 @@ Always convert pointer event coordinates to world space before doing hit-testing
104
106
 
105
107
  ```ts
106
108
  interface DragInfo {
107
- type: DragType // "create" | "move" | "resize" | "marquee" | "pan"
109
+ type: DragType // "create" | "move" | "resize" | "rotate" | "marquee" | "pan"
108
110
  startWorld: Point // Where the drag began (world space)
109
111
  startScreen: Point // Where the drag began (screen space)
110
112
  currentWorld: Point // Current position (updated on every move)
111
113
  currentScreen: Point
112
114
  handle?: HandlePosition // Which resize handle, if resizing
115
+ rotate?: { id, center, startAngle, startRotation } // Set for a rotate drag
113
116
  elementStartPositions?: Record<string, { x, y, width, height }> // Snapshot for move/resize
114
117
  }
115
118
  ```
@@ -0,0 +1,41 @@
1
+ # Substrate
2
+
3
+ This project uses [Substrate](https://substrate.georgedrury.co.uk), a set of primitives for building creative tools: scaffold (toolbar, panels, panes, shortcuts), canvas and node helpers, and config-driven controls.
4
+
5
+ ## Use Substrate components first
6
+
7
+ Components are installed into the project with the Substrate CLI, which wraps shadcn. Never run `npx shadcn@latest add` for them directly.
8
+
9
+ ```bash
10
+ npx substrate-kit add panel slider toolbar # install by name, in one call
11
+ npx substrate-kit add # interactive picker
12
+ npx substrate-kit docs <component> # props, CSS variables, usage
13
+ npx substrate-kit docs <component> --open # open its docs page in the browser
14
+ npx substrate-kit docs --list # every component
15
+ ```
16
+
17
+ Before writing a custom slider, input, panel, timeline or colour picker, check `docs --list`. If the Substrate MCP server is connected, use `search_components`, `get_component` and `get_docs` instead of the commands above, and `install_components` to install.
18
+
19
+ ## Tune values with Controls
20
+
21
+ For parameters you want to adjust live (sizes, colours, springs, toggles), describe them as an object and render them with `Controls` instead of building a form:
22
+
23
+ ```tsx
24
+ const card = useControls("Card", {
25
+ radius: [16, 0, 48], // [default, min, max, step?] slider
26
+ colour: "#a78bfa", // colour picker
27
+ visible: true, // toggle
28
+ motion: { type: "spring", visualDuration: 0.3, bounce: 0.2 },
29
+ })
30
+ // <Panel><Controls /></Panel> renders every registered panel
31
+ ```
32
+
33
+ The returned values keep the shape of the config. Panels have versions, reset, keyboard shortcuts (`shortcuts` option) and a copy button that gives an agent the tuned values to paste back in as the new defaults. Install with `npx substrate-kit add controls`, and read `docs controls` for every control type and option. Controls and the timeline are built on [DialKit](https://github.com/joshpuckett/dialkit) (MIT, by Josh Puckett), which installs as the `dialkit` dependency.
34
+
35
+ ## Tune animation with the timeline
36
+
37
+ For motion, define clips with `useControlsTimeline` and bind `clip.current` to your UI. `ControlsTimeline` is the editor: scrub, move and resize clips, edit curves, and copy the tuned timing back as defaults. Install with `npx substrate-kit add controls-timeline`, and read `docs controls-timeline` for clip types, looping and zoom.
38
+
39
+ ## Skills
40
+
41
+ Substrate skills are in `.claude/skills/` and `.agents/skills/`. Surface guides explain how to build each kind of tool (`scaffold-playground`, `canvas-2d`, `3d-scene`, `animation`, `image-generation`, `data-visualisation`) and workflows (`composing-panels`, `wire-interactions`, `create-custom-tool`, `theming`). Component references (`substrate-scaffold`, `substrate-controls`, `substrate-canvas`, `substrate-nodes`, `substrate-feedback`, `substrate-interaction`) say what to use. `install-components` lists everything available.
@@ -1,2 +0,0 @@
1
- export declare function browse(component?: string): void;
2
- //# sourceMappingURL=browse.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"browse.d.ts","sourceRoot":"","sources":["../../src/commands/browse.ts"],"names":[],"mappings":"AAKA,wBAAgB,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAiB/C"}
@@ -1,25 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- import { log } from "../utils/logger.js";
3
- const DOCS_BASE = "https://substrate.georgedrury.co.uk/docs/components";
4
- export function browse(component) {
5
- const url = component
6
- ? `${DOCS_BASE}/${component}`
7
- : "https://substrate.georgedrury.co.uk/docs";
8
- log.info(`Opening ${url}`);
9
- try {
10
- const platform = process.platform;
11
- if (platform === "darwin") {
12
- execSync(`open "${url}"`);
13
- }
14
- else if (platform === "win32") {
15
- execSync(`start "${url}"`);
16
- }
17
- else {
18
- execSync(`xdg-open "${url}"`);
19
- }
20
- }
21
- catch {
22
- log.error(`Could not open browser. Visit: ${url}`);
23
- }
24
- }
25
- //# sourceMappingURL=browse.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"browse.js","sourceRoot":"","sources":["../../src/commands/browse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAExC,MAAM,SAAS,GAAG,qDAAqD,CAAA;AAEvE,MAAM,UAAU,MAAM,CAAC,SAAkB;IACxC,MAAM,GAAG,GAAG,SAAS;QACpB,CAAC,CAAC,GAAG,SAAS,IAAI,SAAS,EAAE;QAC7B,CAAC,CAAC,0CAA0C,CAAA;IAC7C,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,CAAA;IAC1B,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QACjC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC3B,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC,CAAA;QAC1B,CAAC;aAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC,CAAA;QAC3B,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,aAAa,GAAG,GAAG,CAAC,CAAA;QAC9B,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,GAAG,CAAC,KAAK,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAA;IACnD,CAAC;AACF,CAAC"}
@@ -1,9 +0,0 @@
1
- import { type PackageManager } from "../utils/detect-pm.js";
2
- export interface CreateOptions {
3
- surface?: string;
4
- skipInstall?: boolean;
5
- skipGit?: boolean;
6
- packageManager?: PackageManager;
7
- }
8
- export declare function create(projectName: string, options?: CreateOptions): Promise<void>;
9
- //# sourceMappingURL=create.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAKA,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,uBAAuB,CAAA;AA4B9B,MAAM,WAAW,aAAa;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc,CAAC,EAAE,cAAc,CAAA;CAC/B;AAED,wBAAsB,MAAM,CAC3B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,aAAkB,GACzB,OAAO,CAAC,IAAI,CAAC,CAoGf"}