@tscircuit/cli 0.0.83 → 0.0.85

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.
@@ -0,0 +1,23 @@
1
+ import type { AnySoupElement } from "@tscircuit/builder"
2
+ import { su } from "@tscircuit/soup-util"
3
+
4
+ export const deriveSelectorFromPcbComponentId = ({
5
+ soup,
6
+ pcb_component_id,
7
+ }: {
8
+ soup: AnySoupElement[]
9
+ pcb_component_id: string
10
+ }) => {
11
+ const source_component = su(soup).source_component.getUsing({
12
+ pcb_component_id,
13
+ })
14
+ if (!source_component) {
15
+ throw new Error(
16
+ `Could not find source component for pcb_component_id="${pcb_component_id}"`
17
+ )
18
+ }
19
+
20
+ // TODO travel up the tree to make the selector more specific
21
+
22
+ return `.${source_component.name}`
23
+ }
@@ -14,6 +14,7 @@ import { checkIfInitialized } from "./check-if-initialized"
14
14
  import { initCmd } from "../init"
15
15
  import { startExportRequestWatcher } from "./start-export-request-watcher"
16
16
  import $ from "dax-sh"
17
+ import { startEditEventWatcher } from "./start-edit-event-watcher"
17
18
 
18
19
  export const devCmd = async (ctx: AppContext, args: any) => {
19
20
  const params = z
@@ -75,9 +76,10 @@ export const devCmd = async (ctx: AppContext, args: any) => {
75
76
  console.log(`Loading examples...`)
76
77
  await uploadExamplesFromDirectory({ devServerAxios, cwd }, ctx)
77
78
 
78
- // Start watcher
79
+ // Start watchers
79
80
  const fs_watcher = await startFsWatcher({ cwd, devServerAxios }, ctx)
80
81
  const er_watcher = await startExportRequestWatcher({ devServerAxios }, ctx)
82
+ const ee_watcher = await startEditEventWatcher({ devServerAxios }, ctx)
81
83
 
82
84
  while (true) {
83
85
  const { action } = await prompts({
@@ -108,6 +110,7 @@ export const devCmd = async (ctx: AppContext, args: any) => {
108
110
  if (server.close) server.close()
109
111
  fs_watcher.stop()
110
112
  er_watcher.stop()
113
+ ee_watcher.stop()
111
114
  break
112
115
  }
113
116
  }
@@ -0,0 +1,229 @@
1
+ import { DevPackageExample } from "@server/db/get-db"
2
+ import { AxiosInstance } from "axios"
3
+ import kleur from "kleur"
4
+ import { AppContext } from "lib/util/app-context"
5
+ import fg from "fast-glob"
6
+ import fs from "fs"
7
+ import { Project, ts } from "ts-morph"
8
+ import * as Path from "path"
9
+ import { ManualPcbPosition } from "@tscircuit/builder"
10
+ import { deriveSelectorFromPcbComponentId } from "./derive-selector-from-pcb-component-id"
11
+
12
+ // TODO import from builder when builder exports it
13
+ type EditEvent = {
14
+ edit_event_id: string
15
+ pcb_edit_event_type: "edit_component_location"
16
+ pcb_component_id: string
17
+ original_center: { x: number; y: number }
18
+ new_center: { x: number; y: number }
19
+ }
20
+
21
+ export const startEditEventWatcher = async (
22
+ {
23
+ devServerAxios,
24
+ }: {
25
+ devServerAxios: AxiosInstance
26
+ },
27
+ ctx: AppContext
28
+ ) => {
29
+ let running = true
30
+
31
+ ;(async () => {
32
+ let last_edit_event_update_time: Record<string, string> = {}
33
+
34
+ while (running) {
35
+ try {
36
+ const dev_package_examples: DevPackageExample[] = await devServerAxios
37
+ .post("/api/dev_package_examples/list", {})
38
+ .then((r) => r.data.dev_package_examples)
39
+
40
+ for (const dev_package_example of dev_package_examples) {
41
+ const dev_package_example_id: number =
42
+ dev_package_example.dev_package_example_id as any
43
+
44
+ const last_recorded_update_time =
45
+ last_edit_event_update_time[dev_package_example_id]
46
+
47
+ if (
48
+ last_recorded_update_time !==
49
+ dev_package_example.edit_events_last_updated_at
50
+ ) {
51
+ console.log(
52
+ kleur.gray(
53
+ `Edit event detected for dev_package_example ${dev_package_example.dev_package_example_id}`
54
+ )
55
+ )
56
+ console.log(
57
+ kleur.gray(` file_path: ${dev_package_example.file_path}`)
58
+ )
59
+
60
+ last_edit_event_update_time[dev_package_example_id] =
61
+ dev_package_example.edit_events_last_updated_at // TODO last_edit_event_updated_at
62
+
63
+ console.log(kleur.gray(` getting new edit events...`))
64
+
65
+ const dev_package_example_full = await devServerAxios
66
+ .post("/api/dev_package_examples/get", {
67
+ dev_package_example_id,
68
+ })
69
+ .then((r) => r.data.dev_package_example)
70
+
71
+ // 1. Find the *.manual-edits.ts, if there are multiple error
72
+ const manual_edit_files = fg.sync(
73
+ ["**/*.manual-edits.ts", "**/manual-edits.ts"],
74
+ {
75
+ cwd: ctx.cwd,
76
+ }
77
+ )
78
+
79
+ if (manual_edit_files.length === 0) {
80
+ console.log(
81
+ kleur.red(
82
+ `No manual edit files found in "${ctx.cwd}", please create a file "manual-edits.ts" or "*.manual-edits.ts" to persist manual edits`
83
+ )
84
+ )
85
+ continue
86
+ }
87
+
88
+ if (manual_edit_files.length > 1) {
89
+ console.log(
90
+ kleur.red(
91
+ `Multiple manual edit files found, tsci currently doesn't know how to handle this, you should go upvote an issue`
92
+ )
93
+ )
94
+ for (let i = 0; i < manual_edit_files.length; i++) {
95
+ console.log(
96
+ kleur.gray(` file ${i + 1}: ${manual_edit_files[i]}`)
97
+ )
98
+ }
99
+ continue
100
+ }
101
+
102
+ const manual_edit_file = manual_edit_files[0]
103
+ const manual_edit_file_content = fs.readFileSync(
104
+ Path.join(ctx.cwd, manual_edit_file),
105
+ "utf-8"
106
+ )
107
+
108
+ console.log(
109
+ kleur.gray(` found manual edit file: ${manual_edit_file}`)
110
+ )
111
+
112
+ // 2. Convert the edit events into ManualPcbPosition[] and append,
113
+ // removing any old placements/positions for the same selector.
114
+ // We can completely rewrite the file here for now (we'll need
115
+ // to preserve comments etc. later)
116
+
117
+ const edit_events: EditEvent[] =
118
+ dev_package_example_full.completed_edit_events ?? []
119
+
120
+ if (edit_events.length === 0) continue
121
+
122
+ const project = new Project()
123
+
124
+ const ts_manual_edits_file = project.createSourceFile(
125
+ "manual-edits.ts",
126
+ manual_edit_file_content
127
+ )
128
+
129
+ // Access the default export declaration
130
+ const default_export_dec = ts_manual_edits_file
131
+ .getDefaultExportSymbol()!
132
+ .getDeclarations()[0]
133
+
134
+ // Get the object literal expression from the export default statement
135
+ const object_literal =
136
+ default_export_dec.getFirstChildByKindOrThrow(
137
+ ts.SyntaxKind.ObjectLiteralExpression
138
+ )
139
+
140
+ // Get the `pcb_placements` property
141
+ const pcb_placements_ts =
142
+ object_literal.getPropertyOrThrow("pcb_placements")
143
+
144
+ let pcb_placements: (ManualPcbPosition & {
145
+ _edit_event_id?: string
146
+ })[]
147
+ try {
148
+ pcb_placements = JSON.parse(
149
+ pcb_placements_ts.getText().replace(/pcb_placements:\s/, "")
150
+ )
151
+ } catch (e: any) {
152
+ console.log(
153
+ kleur.red(
154
+ `Error parsing pcb_placements from manual edits file: ${pcb_placements_ts.getText()} ${e.toString()}`
155
+ )
156
+ )
157
+ continue
158
+ }
159
+
160
+ const handled_edit_events = new Set<string>(
161
+ pcb_placements
162
+ .map((p) => (p as any)._edit_event_id)
163
+ .filter(Boolean)
164
+ )
165
+
166
+ // Add PCB placements from edit events
167
+ for (const edit_event of edit_events) {
168
+ if (handled_edit_events.has(edit_event.edit_event_id)) continue
169
+
170
+ // TODO Figure out a good selector for this pcb_component
171
+ const selector = deriveSelectorFromPcbComponentId({
172
+ soup: dev_package_example_full.tscircuit_soup,
173
+ pcb_component_id: edit_event.pcb_component_id,
174
+ })
175
+
176
+ const existing_placement_for_selector = pcb_placements.find(
177
+ (pp) => pp.selector === selector
178
+ )
179
+
180
+ if (!existing_placement_for_selector) {
181
+ console.log(
182
+ kleur.gray(
183
+ ` adding PCB placement from edit event for "${selector}"`
184
+ )
185
+ )
186
+
187
+ pcb_placements.push({
188
+ _edit_event_id: edit_event.edit_event_id,
189
+ selector,
190
+ center: edit_event.new_center,
191
+ relative_to: "group_center",
192
+ })
193
+ } else {
194
+ existing_placement_for_selector.center = edit_event.new_center
195
+ }
196
+
197
+ // Edit the pcb placements object
198
+ pcb_placements_ts.replaceWithText(
199
+ `pcb_placements: ${JSON.stringify(pcb_placements, null, " ")}`
200
+ )
201
+
202
+ // Save the file
203
+
204
+ fs.writeFileSync(
205
+ Path.join(ctx.cwd, manual_edit_file),
206
+ ts_manual_edits_file.getFullText()
207
+ )
208
+ await devServerAxios.post("/api/dev_package_examples/update", {
209
+ dev_package_example_id,
210
+ edit_events_last_applied_at:
211
+ dev_package_example.edit_events_last_updated_at,
212
+ })
213
+ }
214
+ }
215
+ }
216
+ } catch (err: any) {
217
+ console.log(kleur.red(`Error in edit event watcher: ${err.toString()}`))
218
+ }
219
+
220
+ await new Promise((resolve) => setTimeout(resolve, 100))
221
+ }
222
+ })()
223
+
224
+ return {
225
+ stop: () => {
226
+ running = false
227
+ },
228
+ }
229
+ }
@@ -15,7 +15,13 @@ export const startExportRequestWatcher = async (
15
15
 
16
16
  ;(async () => {
17
17
  while (running) {
18
- await fulfillExportRequests({ dev_server_axios: devServerAxios }, ctx)
18
+ try {
19
+ await fulfillExportRequests({ dev_server_axios: devServerAxios }, ctx)
20
+ } catch (err: any) {
21
+ console.log(
22
+ kleur.red(`Error in export request watcher: ${err.toString()}`)
23
+ )
24
+ }
19
25
  await new Promise((resolve) => setTimeout(resolve, 100))
20
26
  }
21
27
  })()
@@ -13,7 +13,7 @@ export const startFsWatcher = async (
13
13
  },
14
14
  ctx: { runtime: "node" | "bun" }
15
15
  ) => {
16
- const watcher = chokidar.watch(`${cwd}/**/*.tsx`, {
16
+ const watcher = chokidar.watch([`${cwd}/**/*.tsx`, `${cwd}/**/*.ts`], {
17
17
  ignored: /node_modules/,
18
18
  persistent: true,
19
19
  })
@@ -23,6 +23,7 @@ export const startFsWatcher = async (
23
23
  should_run: true,
24
24
  }
25
25
  watcher.on("change", async (path) => {
26
+ console.log(path)
26
27
  if (path.endsWith(".__tmp_entrypoint.tsx")) return
27
28
  console.log(`File ${path} has been changed`)
28
29
  // TODO analyze to determine which examples were impacted
@@ -111,15 +111,44 @@ export const initCmd = async (ctx: AppContext, args: any) => {
111
111
  mkdirSync("examples", { recursive: true })
112
112
  mkdirSync("lib", { recursive: true })
113
113
 
114
+ writeFileSync(
115
+ Path.join("lib", "MyCircuit.manual-edits.ts"),
116
+ `
117
+ /**
118
+ * DO NOT EDIT THIS FILE DIRECTLY!
119
+ *
120
+ * This file is automatically edited when running \`tsci dev\` and dragging things
121
+ * around. \`tsci dev\` searches for a file named "*.manual-edits.ts" and edits
122
+ * it when you e.g. move a footprint. If there are multiple files, it'll try
123
+ * to pick one based on context or ask.
124
+ *
125
+ * If you're not running \`tsci dev\`, you can safely edit this file.
126
+ */
127
+ export default {
128
+ // Generated when this file is created, this unique identifier is used to help
129
+ // determine which file to edit when there are many *.manual-edits.ts files
130
+ manual_edit_id: "abcdef",
131
+
132
+ // Manual pcb placements, added when you drag a footprint
133
+ pcb_placements: [],
134
+ }
135
+ `.trim()
136
+ )
137
+
114
138
  writeFileSync(
115
139
  Path.join("lib", "MyCircuit.tsx"),
116
140
  `
141
+ import { layout } from "tscircuit"
142
+ import manual_edits from "./MyCircuit.manual-edits"
143
+
117
144
  export const MyCircuit = () => (
118
- <resistor
119
- resistance="10kohm"
120
- name="R1"
121
- footprint="0805"
122
- />
145
+ <group layout={layout().manualPcbPositions(manual_edits.pcb_placements)}>
146
+ <resistor
147
+ resistance="10kohm"
148
+ name="R1"
149
+ footprint="0805"
150
+ />
151
+ </group>
123
152
  )
124
153
  `.trim()
125
154
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.0.83",
3
+ "version": "0.0.85",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Command line tool for developing, publishing and installing tscircuit circuits",
@@ -9,7 +9,8 @@
9
9
  "bootstrap": "bun i && cd dev-server-api && bun i && cd ../dev-server-frontend && bun i",
10
10
  "bootstrap:ci": "bun i --frozen-lockfile && cd dev-server-api && bun i --frozen-lockfile && cd ../dev-server-frontend && bun i --frozen-lockfile",
11
11
  "start": "bun cli.ts",
12
- "start:dev-server:dev": "TSCI_DEV_SERVER_DB=$(pwd)/.tscircuit/dev-server.sqlite concurrently 'cd dev-server-api && bun start' 'cd dev-server-frontend && bun start'",
12
+ "dev": "TSCI_DEV_SERVER_DB=$(pwd)/.tscircuit/dev-server.sqlite concurrently 'cd dev-server-api && bun run build && bun start' 'cd dev-server-frontend && bun start' 'bun run dev-with-test-project'",
13
+ "clear": "rm -rf .tscircuit ./dev-server-api/.edgespec",
13
14
  "start:dev-server": "bun build:dev-server && bun cli.ts dev -y --cwd ./tests/assets/example-project",
14
15
  "build:dev-server": "cd dev-server-api && bun run build && cd ../dev-server-frontend && bun run build",
15
16
  "build:dev-server:api": "cd dev-server-api && bun run build",
@@ -17,7 +18,7 @@
17
18
  "build": "bun build:dev-server && npm run build:cli",
18
19
  "dev-with-test-project": "bun cli.ts dev --cwd ./tests/assets/example-project",
19
20
  "test:init": "bun cli.ts init --dir ./tmp/test --name test",
20
- "update-deps": "bun add @tscircuit/builder@latest @tscircuit/react-fiber@latest && cd dev-server-frontend && bun run update-deps"
21
+ "update-deps": "npm add @tscircuit/builder@latest @tscircuit/react-fiber@latest && cd dev-server-frontend && npm run update-deps && cd ../tests/assets/example-project && npm add @tscircuit/builder@latest @tscircuit/react-fiber@latest"
21
22
  },
22
23
  "bin": {
23
24
  "tscircuit": "./dist/cli.js",
@@ -35,8 +36,9 @@
35
36
  "dependencies": {
36
37
  "@edge-runtime/primitives": "^4.1.0",
37
38
  "@hono/node-server": "^1.8.2",
38
- "@tscircuit/builder": "1.5.72",
39
- "@tscircuit/react-fiber": "^1.0.35",
39
+ "@tscircuit/builder": "^1.5.87",
40
+ "@tscircuit/react-fiber": "^1.0.39",
41
+ "@tscircuit/soup-util": "^0.0.1",
40
42
  "archiver": "^7.0.1",
41
43
  "axios": "^1.6.7",
42
44
  "better-sqlite3": "^9.4.3",
@@ -49,6 +51,7 @@
49
51
  "delay": "^6.0.0",
50
52
  "edgespec": "^0.0.69",
51
53
  "esbuild": "^0.20.2",
54
+ "fast-glob": "^3.3.2",
52
55
  "glob": "^10.3.10",
53
56
  "hono": "^4.1.0",
54
57
  "ignore": "^5.3.1",
@@ -63,6 +66,7 @@
63
66
  "prompts": "^2.4.2",
64
67
  "react": "^18.2.0",
65
68
  "semver": "^7.6.0",
69
+ "ts-morph": "^22.0.0",
66
70
  "tsup": "^8.0.2",
67
71
  "zod": "latest"
68
72
  },
@@ -1,16 +1,28 @@
1
+ import { layout } from "@tscircuit/layout"
2
+ import manual_edits from "../src/manual-edits"
3
+
1
4
  export const BasicBug = () => (
2
- <bug
3
- name="U2"
4
- port_arrangement={{
5
- left_size: 4,
6
- right_size: 4,
7
- }}
8
- center={[-10, 0]}
9
- port_labels={{
10
- "1": "GND",
11
- "2": "VBUS",
12
- "3": "D-",
13
- "4": "D+",
14
- }}
15
- />
5
+ <group
6
+ layout={layout()
7
+ .autoLayoutSchematic()
8
+ .manualPcbPlacement(manual_edits.pcb_placements)}
9
+ >
10
+ <bug
11
+ name="U2"
12
+ port_arrangement={{
13
+ left_size: 4,
14
+ right_size: 4,
15
+ }}
16
+ footprint="sparkfun:ssop16"
17
+ center={[-10, 0]}
18
+ port_labels={{
19
+ "1": "GND",
20
+ "2": "VBUS",
21
+ "3": "D-",
22
+ "4": "D+",
23
+ }}
24
+ />
25
+ <resistor name="R1" resistance="10kohm" footprint="0805" />
26
+ <trace from=".U2 > .1" to=".R1 > .left" />
27
+ </group>
16
28
  )
@@ -8,8 +8,8 @@
8
8
  "name": "example-project",
9
9
  "version": "1.2.26",
10
10
  "dependencies": {
11
- "@tscircuit/builder": "^1.5.61",
12
- "@tscircuit/react-fiber": "^1.0.34"
11
+ "@tscircuit/builder": "^1.5.87",
12
+ "@tscircuit/react-fiber": "^1.0.39"
13
13
  }
14
14
  },
15
15
  "node_modules/@babel/runtime": {
@@ -29,14 +29,17 @@
29
29
  "integrity": "sha512-iB+oaYyaVK1hQ0cODubnoSDg4gGYL9cp/4ad7G1b9Z0/IqehPztp5qE3KP2mV9Ns0UYmzwvtkEhTCmKUuhorbg=="
30
30
  },
31
31
  "node_modules/@tscircuit/builder": {
32
- "version": "1.5.61",
33
- "resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.61.tgz",
34
- "integrity": "sha512-pkaIte2C6Kksp3B79eQIG5f0/9KO2x0fdkHe/a0757lMYVUbcSvqjanL7RmJJ983C2wnEMo2au5ycgXvZseMUQ==",
32
+ "version": "1.5.87",
33
+ "resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.87.tgz",
34
+ "integrity": "sha512-ITtSXjOpHL4J03HemsVtnFl3DfFc0ELTctk5XfhYAdYHKvy+ege6EKWiYRT90CMLb6N0r9+6NaZUaHALJLgYRw==",
35
35
  "dependencies": {
36
36
  "@lume/kiwi": "^0.1.0",
37
37
  "@tscircuit/footprints": "^0.0.14",
38
+ "@tscircuit/layout": "^0.0.7",
38
39
  "@tscircuit/routing": "^1.3.1",
39
- "@tscircuit/sparkfun-packages": "^1.2.0",
40
+ "@tscircuit/schematic-autolayout": "^0.0.5",
41
+ "@tscircuit/soup-util": "^0.0.1",
42
+ "@tscircuit/sparkfun-packages": "^1.2.1",
40
43
  "convert-units": "^2.3.4",
41
44
  "fast-json-stable-stringify": "^2.1.0",
42
45
  "format-si-prefix": "^0.3.2",
@@ -57,6 +60,18 @@
57
60
  "typescript": "^5.0.0"
58
61
  }
59
62
  },
63
+ "node_modules/@tscircuit/layout": {
64
+ "version": "0.0.7",
65
+ "resolved": "https://registry.npmjs.org/@tscircuit/layout/-/layout-0.0.7.tgz",
66
+ "integrity": "sha512-Jdd6j0+p4yK8zAqFX7dgmb5PT8A9KJduDBhEgAm+OgwDrw3Mp0hQ80pbR2Mvm02UF2Gu9H7TWpMytACCoNqPdA==",
67
+ "dependencies": {
68
+ "transformation-matrix": "^2.16.1"
69
+ },
70
+ "peerDependencies": {
71
+ "@tscircuit/builder": "*",
72
+ "zod": "*"
73
+ }
74
+ },
60
75
  "node_modules/@tscircuit/mm": {
61
76
  "version": "0.0.4",
62
77
  "resolved": "https://registry.npmjs.org/@tscircuit/mm/-/mm-0.0.4.tgz",
@@ -69,9 +84,9 @@
69
84
  }
70
85
  },
71
86
  "node_modules/@tscircuit/react-fiber": {
72
- "version": "1.0.34",
73
- "resolved": "https://registry.npmjs.org/@tscircuit/react-fiber/-/react-fiber-1.0.34.tgz",
74
- "integrity": "sha512-kI5oOe/dbJGbeWlInx239hXNWPIRMRTgD8pO9IXvAvZ4YOldR6CJanx9DuT5vgTcZTjoswaXJzRJZZB1Ib2jmw==",
87
+ "version": "1.0.39",
88
+ "resolved": "https://registry.npmjs.org/@tscircuit/react-fiber/-/react-fiber-1.0.39.tgz",
89
+ "integrity": "sha512-xdEghvKDm9xr5j+zvEH8VVLj6haYCsQ5V8vNOyuXLoc63o7B/Maibsp5Yf6DdoC+SsxYYdZIt8cc0lAj7REfFg==",
75
90
  "dependencies": {
76
91
  "react-reconciler": "^0.29.0"
77
92
  },
@@ -89,10 +104,31 @@
89
104
  "react-error-boundary": "^4.0.11"
90
105
  }
91
106
  },
107
+ "node_modules/@tscircuit/schematic-autolayout": {
108
+ "version": "0.0.5",
109
+ "resolved": "https://registry.npmjs.org/@tscircuit/schematic-autolayout/-/schematic-autolayout-0.0.5.tgz",
110
+ "integrity": "sha512-I4CtLQfqTPTxDSumnquaJtkJkc16VjLC4bwU3jQdBXwwh9ODzBf88clUznUtDDzwV+BPM5P0W0VCfFhvPL3/Cw==",
111
+ "dependencies": {
112
+ "react": "^18.2.0",
113
+ "react-dom": "^18.2.0",
114
+ "react-supergrid": "^1.0.10",
115
+ "transformation-matrix": "^2.16.1",
116
+ "use-mouse-matrix-transform": "^1.1.12"
117
+ }
118
+ },
119
+ "node_modules/@tscircuit/soup-util": {
120
+ "version": "0.0.1",
121
+ "resolved": "https://registry.npmjs.org/@tscircuit/soup-util/-/soup-util-0.0.1.tgz",
122
+ "integrity": "sha512-hNJayJ/Z+Clms1uAv8j6TCkK2aVNrm/C0PnAUcbSMY3gZfA+os7ovTxS/hCJfC22K4wHoBwsbZ+mE8R3KxaFfQ==",
123
+ "peerDependencies": {
124
+ "@tscircuit/builder": "*",
125
+ "zod": "*"
126
+ }
127
+ },
92
128
  "node_modules/@tscircuit/sparkfun-packages": {
93
- "version": "1.2.0",
94
- "resolved": "https://registry.npmjs.org/@tscircuit/sparkfun-packages/-/sparkfun-packages-1.2.0.tgz",
95
- "integrity": "sha512-m+jCOaSBpwRzUN5trc9z5f8yh2zzLITANgNhuNQOtxNZRIrv98iYfL3dSSmf73xknh0Nz68EephNvKVZmproCQ==",
129
+ "version": "1.2.1",
130
+ "resolved": "https://registry.npmjs.org/@tscircuit/sparkfun-packages/-/sparkfun-packages-1.2.1.tgz",
131
+ "integrity": "sha512-2HzmmHydo5vgoKmNBAHd6RD93LaIMXRSt6t//1zx19/ZwrOA43qVOvb7cCTA82GHib1bSxoL7bqgii9sYudCHw==",
96
132
  "dependencies": {
97
133
  "change-case": "^5.4.3"
98
134
  }
@@ -359,10 +395,9 @@
359
395
  }
360
396
  },
361
397
  "node_modules/react": {
362
- "version": "18.2.0",
363
- "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
364
- "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
365
- "peer": true,
398
+ "version": "18.3.1",
399
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
400
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
366
401
  "dependencies": {
367
402
  "loose-envify": "^1.1.0"
368
403
  },
@@ -370,6 +405,18 @@
370
405
  "node": ">=0.10.0"
371
406
  }
372
407
  },
408
+ "node_modules/react-dom": {
409
+ "version": "18.3.1",
410
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
411
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
412
+ "dependencies": {
413
+ "loose-envify": "^1.1.0",
414
+ "scheduler": "^0.23.2"
415
+ },
416
+ "peerDependencies": {
417
+ "react": "^18.3.1"
418
+ }
419
+ },
373
420
  "node_modules/react-error-boundary": {
374
421
  "version": "4.0.13",
375
422
  "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz",
@@ -396,6 +443,16 @@
396
443
  "react": "^18.2.0"
397
444
  }
398
445
  },
446
+ "node_modules/react-supergrid": {
447
+ "version": "1.0.10",
448
+ "resolved": "https://registry.npmjs.org/react-supergrid/-/react-supergrid-1.0.10.tgz",
449
+ "integrity": "sha512-dJd9wkH6BJkdfkv62EcRAIBn59e2wj58bJFVXiW/ZHQzxz20qIql63fTU2qFMOujXnBIDaMG0uTod67/mjEGeA==",
450
+ "peerDependencies": {
451
+ "react": "*",
452
+ "react-dom": "*",
453
+ "transformation-matrix": "*"
454
+ }
455
+ },
399
456
  "node_modules/rectilinear-router": {
400
457
  "version": "1.0.1",
401
458
  "resolved": "https://registry.npmjs.org/rectilinear-router/-/rectilinear-router-1.0.1.tgz",
@@ -419,9 +476,9 @@
419
476
  }
420
477
  },
421
478
  "node_modules/scheduler": {
422
- "version": "0.23.0",
423
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
424
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
479
+ "version": "0.23.2",
480
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
481
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
425
482
  "dependencies": {
426
483
  "loose-envify": "^1.1.0"
427
484
  }
@@ -462,6 +519,26 @@
462
519
  "engines": {
463
520
  "node": ">=14.17"
464
521
  }
522
+ },
523
+ "node_modules/use-mouse-matrix-transform": {
524
+ "version": "1.1.13",
525
+ "resolved": "https://registry.npmjs.org/use-mouse-matrix-transform/-/use-mouse-matrix-transform-1.1.13.tgz",
526
+ "integrity": "sha512-NsP0j0Ifv9TywhqrNGfIhjpGzuyEzPK553ahn+LBVvZHZ6Gv+2T3tn41pJV6Syos1W7crWKolbP+XLfqa5BpCQ==",
527
+ "dependencies": {
528
+ "transformation-matrix": "^2.14.0"
529
+ },
530
+ "peerDependencies": {
531
+ "react": "^18.2.0"
532
+ }
533
+ },
534
+ "node_modules/zod": {
535
+ "version": "3.23.6",
536
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.6.tgz",
537
+ "integrity": "sha512-RTHJlZhsRbuA8Hmp/iNL7jnfc4nZishjsanDAfEY1QpDQZCahUp3xDzl+zfweE9BklxMUcgBgS1b7Lvie/ZVwA==",
538
+ "peer": true,
539
+ "funding": {
540
+ "url": "https://github.com/sponsors/colinhacks"
541
+ }
465
542
  }
466
543
  }
467
544
  }
@@ -4,7 +4,7 @@
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "dependencies": {
7
- "@tscircuit/builder": "^1.5.61",
8
- "@tscircuit/react-fiber": "^1.0.34"
7
+ "@tscircuit/builder": "^1.5.87",
8
+ "@tscircuit/react-fiber": "^1.0.39"
9
9
  }
10
10
  }