@tscircuit/cli 0.0.82 → 0.0.84

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,219 @@
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
+ // TODO use last_edit_event_updated_at
48
+ if (
49
+ last_recorded_update_time !== dev_package_example.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.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
+ continue
95
+ }
96
+
97
+ const manual_edit_file = manual_edit_files[0]
98
+ const manual_edit_file_content = fs.readFileSync(
99
+ Path.join(ctx.cwd, manual_edit_file),
100
+ "utf-8"
101
+ )
102
+
103
+ console.log(
104
+ kleur.gray(` found manual edit file: ${manual_edit_file}`)
105
+ )
106
+
107
+ // 2. Convert the edit events into ManualPcbPosition[] and append,
108
+ // removing any old placements/positions for the same selector.
109
+ // We can completely rewrite the file here for now (we'll need
110
+ // to preserve comments etc. later)
111
+
112
+ const edit_events: EditEvent[] =
113
+ dev_package_example_full.completed_edit_events ?? []
114
+
115
+ if (edit_events.length === 0) continue
116
+
117
+ const project = new Project()
118
+
119
+ const ts_manual_edits_file = project.createSourceFile(
120
+ "manual-edits.ts",
121
+ manual_edit_file_content
122
+ )
123
+
124
+ // Access the default export declaration
125
+ const default_export_dec = ts_manual_edits_file
126
+ .getDefaultExportSymbol()!
127
+ .getDeclarations()[0]
128
+
129
+ // Get the object literal expression from the export default statement
130
+ const object_literal =
131
+ default_export_dec.getFirstChildByKindOrThrow(
132
+ ts.SyntaxKind.ObjectLiteralExpression
133
+ )
134
+
135
+ // Get the `pcb_placements` property
136
+ const pcb_placements_ts =
137
+ object_literal.getPropertyOrThrow("pcb_placements")
138
+
139
+ let pcb_placements: (ManualPcbPosition & {
140
+ _edit_event_id?: string
141
+ })[]
142
+ try {
143
+ pcb_placements = JSON.parse(
144
+ pcb_placements_ts.getText().replace(/pcb_placements:\s/, "")
145
+ )
146
+ } catch (e: any) {
147
+ console.log(
148
+ kleur.red(
149
+ `Error parsing pcb_placements from manual edits file: ${pcb_placements_ts.getText()} ${e.toString()}`
150
+ )
151
+ )
152
+ continue
153
+ }
154
+
155
+ const handled_edit_events = new Set<string>(
156
+ pcb_placements
157
+ .map((p) => (p as any)._edit_event_id)
158
+ .filter(Boolean)
159
+ )
160
+
161
+ // Add PCB placements from edit events
162
+ for (const edit_event of edit_events) {
163
+ if (handled_edit_events.has(edit_event.edit_event_id)) continue
164
+
165
+ // TODO Figure out a good selector for this pcb_component
166
+ const selector = deriveSelectorFromPcbComponentId({
167
+ soup: dev_package_example_full.tscircuit_soup,
168
+ pcb_component_id: edit_event.pcb_component_id,
169
+ })
170
+
171
+ const existing_placement_for_selector = pcb_placements.find(
172
+ (pp) => pp.selector === selector
173
+ )
174
+
175
+ if (!existing_placement_for_selector) {
176
+ console.log(
177
+ kleur.gray(
178
+ ` adding PCB placement from edit event for "${selector}"`
179
+ )
180
+ )
181
+
182
+ pcb_placements.push({
183
+ _edit_event_id: edit_event.edit_event_id,
184
+ selector,
185
+ center: edit_event.new_center,
186
+ relative_to: "group_center",
187
+ })
188
+ } else {
189
+ existing_placement_for_selector.center = edit_event.new_center
190
+ }
191
+
192
+ // Edit the pcb placements object
193
+ pcb_placements_ts.replaceWithText(
194
+ `pcb_placements: ${JSON.stringify(pcb_placements, null, " ")}`
195
+ )
196
+
197
+ // Save the file
198
+
199
+ fs.writeFileSync(
200
+ Path.join(ctx.cwd, manual_edit_file),
201
+ ts_manual_edits_file.getFullText()
202
+ )
203
+ }
204
+ }
205
+ }
206
+ } catch (err: any) {
207
+ console.log(kleur.red(`Error in edit event watcher: ${err.toString()}`))
208
+ }
209
+
210
+ await new Promise((resolve) => setTimeout(resolve, 100))
211
+ }
212
+ })()
213
+
214
+ return {
215
+ stop: () => {
216
+ running = false
217
+ },
218
+ }
219
+ }
@@ -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
  })()
@@ -45,7 +45,7 @@ export const initCmd = async (ctx: AppContext, args: any) => {
45
45
  }
46
46
  }
47
47
 
48
- let runtime = params.runtime
48
+ let runtime = params.runtime ?? ctx.runtime
49
49
  if (!runtime) {
50
50
  const bunExists = $.commandExistsSync("bun")
51
51
 
@@ -94,6 +94,10 @@ export const initCmd = async (ctx: AppContext, args: any) => {
94
94
  packageJson.scripts.build = "tsup ./index.ts --sourcemap --dts"
95
95
  writeFileSync("package.json", JSON.stringify(packageJson, null, 2))
96
96
 
97
+ console.log('Making package type: "module"...')
98
+ packageJson.type = "module"
99
+ writeFileSync("package.json", JSON.stringify(packageJson, null, 2))
100
+
97
101
  console.log(`Adding ".tscircuit" to .gitignore`)
98
102
  appendFileSync(".gitignore", "\n.tscircuit\n*.__tmp_entrypoint.tsx\ndist", {
99
103
  encoding: "utf-8",
@@ -107,15 +111,44 @@ export const initCmd = async (ctx: AppContext, args: any) => {
107
111
  mkdirSync("examples", { recursive: true })
108
112
  mkdirSync("lib", { recursive: true })
109
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
+
110
138
  writeFileSync(
111
139
  Path.join("lib", "MyCircuit.tsx"),
112
140
  `
141
+ import { layout } from "tscircuit"
142
+ import manual_edits from "./MyCircuit.manual-edits"
143
+
113
144
  export const MyCircuit = () => (
114
- <resistor
115
- resistance="10kohm"
116
- name="R1"
117
- footprint="0805"
118
- />
145
+ <group layout={layout().manualPcbPositions(manual_edits.pcb_placements)}>
146
+ <resistor
147
+ resistance="10kohm"
148
+ name="R1"
149
+ footprint="0805"
150
+ />
151
+ </group>
119
152
  )
120
153
  `.trim()
121
154
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.0.82",
3
+ "version": "0.0.84",
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",
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.86",
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.86",
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.86",
33
+ "resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.86.tgz",
34
+ "integrity": "sha512-hZZvpo6t84kd66BfLE120eTLgoEUv42iEjxtQS6IeOUXk7y+pSMYwS16L+HHjmivKKRx0BOO+KmYFRsqi18mdw==",
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.86",
8
+ "@tscircuit/react-fiber": "^1.0.39"
9
9
  }
10
10
  }
@@ -1,7 +1,15 @@
1
1
  import "@tscircuit/react-fiber"
2
+ import { layout } from "@tscircuit/layout"
3
+ import manual_edits from "./manual-edits"
2
4
 
3
5
  export const MyCircuit = () => (
4
- <board width="40mm" height="40mm" center_x={0} center_y={0}>
6
+ <board
7
+ width="40mm"
8
+ height="40mm"
9
+ center_x={0}
10
+ center_y={0}
11
+ layout={layout().manualPcbPlacement(manual_edits.pcb_placements)}
12
+ >
5
13
  <resistor
6
14
  name="R1"
7
15
  resistance="20kohm"