@tscircuit/core 0.0.72 → 0.0.74

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 (58) hide show
  1. package/README.md +0 -4
  2. package/package.json +2 -4
  3. package/index.ts +0 -1
  4. package/lib/Project.ts +0 -131
  5. package/lib/components/base-components/NormalComponent.ts +0 -419
  6. package/lib/components/base-components/PrimitiveComponent.ts +0 -478
  7. package/lib/components/base-components/Renderable.ts +0 -126
  8. package/lib/components/index.ts +0 -25
  9. package/lib/components/normal-components/Board.ts +0 -49
  10. package/lib/components/normal-components/Capacitor.ts +0 -70
  11. package/lib/components/normal-components/Chip.ts +0 -98
  12. package/lib/components/normal-components/Diode.ts +0 -27
  13. package/lib/components/normal-components/Jumper.ts +0 -101
  14. package/lib/components/normal-components/Led.ts +0 -27
  15. package/lib/components/normal-components/Resistor.ts +0 -59
  16. package/lib/components/primitive-components/Constraint.ts +0 -91
  17. package/lib/components/primitive-components/FabricationNotePath.ts +0 -50
  18. package/lib/components/primitive-components/FabricationNoteText.ts +0 -26
  19. package/lib/components/primitive-components/Footprint.ts +0 -239
  20. package/lib/components/primitive-components/Group.ts +0 -42
  21. package/lib/components/primitive-components/Hole.ts +0 -65
  22. package/lib/components/primitive-components/Keepout.ts +0 -58
  23. package/lib/components/primitive-components/Net.ts +0 -171
  24. package/lib/components/primitive-components/PlatedHole.ts +0 -116
  25. package/lib/components/primitive-components/Port.ts +0 -236
  26. package/lib/components/primitive-components/SilkscreenPath.ts +0 -48
  27. package/lib/components/primitive-components/SilkscreenText.ts +0 -25
  28. package/lib/components/primitive-components/SmtPad.ts +0 -162
  29. package/lib/components/primitive-components/Trace.ts +0 -635
  30. package/lib/components/primitive-components/TraceHint.ts +0 -71
  31. package/lib/fiber/catalogue.ts +0 -22
  32. package/lib/fiber/create-instance-from-react-element.ts +0 -179
  33. package/lib/fiber/intrinsic-jsx.ts +0 -48
  34. package/lib/index.ts +0 -5
  35. package/lib/register-catalogue.ts +0 -12
  36. package/lib/soup/underscorifyPinStyles.ts +0 -25
  37. package/lib/soup/underscorifyPortArrangement.ts +0 -51
  38. package/lib/utils/autorouting/SimpleRouteJson.ts +0 -48
  39. package/lib/utils/autorouting/computeObstacleBounds.ts +0 -10
  40. package/lib/utils/autorouting/findPossibleTraceLayerCombinations.ts +0 -102
  41. package/lib/utils/autorouting/mergeRoutes.ts +0 -71
  42. package/lib/utils/components/createNetsFromProps.ts +0 -15
  43. package/lib/utils/constants.ts +0 -35
  44. package/lib/utils/createComponentsFromSoup.ts +0 -79
  45. package/lib/utils/extend-aliases.ts +0 -12
  46. package/lib/utils/get-bounds-of-pcb-components.ts +0 -41
  47. package/lib/utils/get-relative-direction.ts +0 -14
  48. package/lib/utils/getClosest.ts +0 -35
  49. package/lib/utils/getPortFromHints.ts +0 -10
  50. package/lib/utils/pairs.ts +0 -10
  51. package/lib/utils/projectPointInDirection.ts +0 -18
  52. package/lib/utils/range.ts +0 -8
  53. package/lib/utils/schematic/getAllDimensionsForSchematicBox.ts +0 -330
  54. package/lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts +0 -47
  55. package/lib/utils/selector-matching/index.ts +0 -2
  56. package/lib/utils/selector-matching/is-matching-path-selector.ts +0 -32
  57. package/lib/utils/selector-matching/is-matching-selector.ts +0 -64
  58. package/lib/utils/try-now.ts +0 -7
package/README.md CHANGED
@@ -2,10 +2,6 @@
2
2
 
3
3
  [tscircuit](https://github.com/tscircuit/tscircuit) · [Development Guide](./docs/DEVELOPMENT.md)
4
4
 
5
- > [!WARNING]
6
- > You should use [@tscircuit/builder](https://github.com/tscircuit/builder) instead, this package is
7
- > going to be in alpha for a while.
8
-
9
5
  A rewrite of [tscircuit builder](https://github.com/tscircuit/builder) with a ThreeJS/react-three-like API and architecture.
10
6
 
11
7
  ## Usage
package/package.json CHANGED
@@ -1,13 +1,11 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
- "module": "index.ts",
4
3
  "type": "module",
5
- "version": "0.0.72",
4
+ "version": "0.0.74",
6
5
  "types": "dist/index.d.ts",
7
6
  "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
8
  "files": [
9
- "index.ts",
10
- "lib",
11
9
  "dist"
12
10
  ],
13
11
  "scripts": {
package/index.ts DELETED
@@ -1 +0,0 @@
1
- export * from "./lib/index"
package/lib/Project.ts DELETED
@@ -1,131 +0,0 @@
1
- import type { AnySoupElement } from "@tscircuit/soup"
2
- import type { PrimitiveComponent } from "./components/base-components/PrimitiveComponent"
3
- import type { SoupUtilObjects } from "@tscircuit/soup-util"
4
- import { su } from "@tscircuit/soup-util"
5
- import { isValidElement, type ReactElement } from "react"
6
- import { createInstanceFromReactElement } from "./fiber/create-instance-from-react-element"
7
- import { identity, type Matrix } from "transformation-matrix"
8
-
9
- export class Circuit {
10
- firstChild: PrimitiveComponent | null = null
11
- children: PrimitiveComponent[]
12
- db: SoupUtilObjects
13
- root: Circuit | null = null
14
- isRoot = true
15
-
16
- _hasRenderedAtleastOnce = false
17
-
18
- constructor() {
19
- this.children = []
20
- this.db = su([])
21
- // TODO rename to rootCircuit
22
- this.root = this
23
- }
24
-
25
- add(componentOrElm: PrimitiveComponent | ReactElement) {
26
- let component: PrimitiveComponent
27
- if (isValidElement(componentOrElm)) {
28
- // TODO store subtree
29
- component = createInstanceFromReactElement(componentOrElm)
30
- } else {
31
- component = componentOrElm as PrimitiveComponent
32
- }
33
- this.children.push(component)
34
- }
35
-
36
- _guessRootComponent() {
37
- if (this.firstChild) return
38
- if (this.children.length === 1) {
39
- this.firstChild = this.children[0]
40
- return
41
- }
42
- if (this.children.length === 0) {
43
- throw new Error(
44
- "Not able to guess root component: Project has no children (use project.add(...))",
45
- )
46
- }
47
-
48
- if (this.children.length > 0) {
49
- const board =
50
- this.children.find((c) => c.componentName === "Board") ?? null
51
-
52
- if (board) {
53
- this.firstChild = board
54
- return
55
- }
56
- }
57
- throw new Error(
58
- "Not able to guess root component: Project has multiple children and no board",
59
- )
60
- }
61
-
62
- render() {
63
- if (!this.firstChild) {
64
- this._guessRootComponent()
65
- }
66
- const { firstChild, db } = this
67
-
68
- if (!firstChild) throw new Error("Project has no root component")
69
- firstChild.parent = this as any
70
- firstChild.runRenderCycle()
71
- this._hasRenderedAtleastOnce = true
72
- }
73
-
74
- getSoup(): AnySoupElement[] {
75
- if (!this._hasRenderedAtleastOnce) this.render()
76
- return this.db.toArray()
77
- }
78
-
79
- getCircuitJson(): AnySoupElement[] {
80
- return this.getSoup()
81
- }
82
-
83
- async getSvg(options: { view: "pcb"; layer?: string }): Promise<string> {
84
- const circuitToSvg = await import("circuit-to-svg").catch((e) => {
85
- throw new Error(
86
- `To use project.getSvg, you must install the "circuit-to-svg" package.\n\n"${e.message}"`,
87
- )
88
- })
89
-
90
- return circuitToSvg.circuitJsonToPcbSvg(this.getCircuitJson())
91
- }
92
-
93
- async preview(
94
- previewNameOrOpts:
95
- | string
96
- | {
97
- previewName: string
98
- tscircuitApiKey?: string
99
- },
100
- ) {
101
- const previewOpts =
102
- typeof previewNameOrOpts === "object"
103
- ? previewNameOrOpts
104
- : { previewName: previewNameOrOpts }
105
- throw new Error("project.preview is not yet implemented")
106
- }
107
-
108
- computeSchematicGlobalTransform(): Matrix {
109
- return identity()
110
- }
111
-
112
- _computePcbGlobalTransformBeforeLayout(): Matrix {
113
- return identity()
114
- }
115
-
116
- selectAll(selector: string): PrimitiveComponent[] {
117
- return this.firstChild?.selectAll(selector) ?? []
118
- }
119
-
120
- selectOne(
121
- selector: string,
122
- opts?: { type?: "component" | "port" },
123
- ): PrimitiveComponent | null {
124
- return this.firstChild?.selectOne(selector, opts) ?? null
125
- }
126
- }
127
-
128
- /**
129
- * @deprecated
130
- */
131
- export const Project = Circuit
@@ -1,419 +0,0 @@
1
- import { Footprint } from "../primitive-components/Footprint"
2
- import { ZodType, z } from "zod"
3
- import { PrimitiveComponent } from "./PrimitiveComponent"
4
- import { Port } from "../primitive-components/Port"
5
- import { symbols, type BaseSymbolName, type SchSymbol } from "schematic-symbols"
6
- import { fp } from "footprinter"
7
- import {
8
- isValidElement as isReactElement,
9
- isValidElement,
10
- type ReactElement,
11
- type ReactNode,
12
- } from "react"
13
- import {
14
- createInstanceFromReactElement,
15
- type ReactSubtree,
16
- } from "lib/fiber/create-instance-from-react-element"
17
- import { getPortFromHints } from "lib/utils/getPortFromHints"
18
- import { createComponentsFromSoup } from "lib/utils/createComponentsFromSoup"
19
- import { Net } from "../primitive-components/Net"
20
- import { createNetsFromProps } from "lib/utils/components/createNetsFromProps"
21
- import { getBoundsOfPcbComponents } from "lib/utils/get-bounds-of-pcb-components"
22
-
23
- export type PortMap<T extends string> = {
24
- [K in T]: Port
25
- }
26
-
27
- /**
28
- * A NormalComponent is the base class for most components that a user will
29
- * interact with. It has the ability to set a footprint and discover ports.
30
- *
31
- * When you're extending a NormalComponent, you almost always want to override
32
- * initPorts() to create ports for the component.
33
- *
34
- * class Led extends NormalComponent<typeof resistorProps> {
35
- * pin1: Port = this.portMap.pin1
36
- * pin2: Port = this.portMap.pin2
37
- *
38
- * initPorts() {
39
- * this.add(new Port({ pinNumber: 1, aliases: ["anode", "pos"] }))
40
- * this.add(new Port({ pinNumber: 2, aliases: ["cathode", "neg"] }))
41
- * }
42
- * }
43
- */
44
- export class NormalComponent<
45
- ZodProps extends ZodType = any,
46
- PortNames extends string = never,
47
- > extends PrimitiveComponent<ZodProps> {
48
- reactSubtrees: Array<ReactSubtree> = []
49
-
50
- isPrimitiveContainer = true
51
-
52
- constructor(props: z.input<ZodProps>) {
53
- super(props)
54
- this._addChildrenFromStringFootprint()
55
- this.initPorts()
56
- }
57
-
58
- /**
59
- * Override this method for better control over the auto-discovery of ports.
60
- *
61
- * If you override this method just do something like:
62
- * initPorts() {
63
- * this.add(new Port({ pinNumber: 1, aliases: ["anode", "pos"] }))
64
- * this.add(new Port({ pinNumber: 2, aliases: ["cathode", "neg"] }))
65
- * }
66
- *
67
- * By default, we'll pull the ports from the first place we find them:
68
- * 1. `config.schematicSymbolName`
69
- * 2. `props.footprint`
70
- *
71
- */
72
- initPorts() {
73
- const { config } = this
74
- const portsToCreate: Port[] = []
75
- if (config.schematicSymbolName) {
76
- const sym = symbols[
77
- `${config.schematicSymbolName}_horz` as keyof typeof symbols
78
- ] as SchSymbol | undefined
79
- if (!sym) return
80
-
81
- for (const symPort of sym.ports) {
82
- const port = getPortFromHints(symPort.labels)
83
-
84
- if (port) {
85
- port.schematicSymbolPortDef = symPort
86
- portsToCreate.push(port)
87
- }
88
- }
89
-
90
- this.addAll(portsToCreate)
91
- return
92
- }
93
-
94
- const portsFromFootprint = this.getPortsFromFootprint()
95
- portsToCreate.push(...portsFromFootprint)
96
-
97
- const pinLabels: Record<string, string> | undefined =
98
- this._parsedProps.pinLabels
99
- if (pinLabels) {
100
- for (let [pinNumber, label] of Object.entries(pinLabels)) {
101
- pinNumber = pinNumber.replace("pin", "")
102
- const existingPort = portsToCreate.find(
103
- (p) => p._parsedProps.pinNumber === Number(pinNumber),
104
- )
105
- if (!existingPort) {
106
- throw new Error(
107
- `Could not find port for pin number ${pinNumber} in chip ${this.getString()}`,
108
- )
109
- }
110
- existingPort.externallyAddedAliases.push(label)
111
- existingPort.props.name = label
112
- }
113
- }
114
-
115
- this.addAll(portsToCreate)
116
- }
117
-
118
- _addChildrenFromStringFootprint() {
119
- const { footprint } = this.props
120
- if (!footprint) return
121
- if (typeof footprint === "string") {
122
- const fpSoup = fp.string(footprint).soup()
123
- // Adjust the layer of the footprint to match the layer of the component
124
- if (this.props.layer) {
125
- for (const elm of fpSoup) {
126
- if ("layer" in elm) {
127
- elm.layer = this.props.layer
128
- }
129
- }
130
- }
131
- const fpComponents = createComponentsFromSoup(fpSoup)
132
- this.addAll(fpComponents)
133
- }
134
- }
135
-
136
- get portMap(): PortMap<PortNames> {
137
- return new Proxy(
138
- {},
139
- {
140
- get: (target, prop): Port => {
141
- const port = this.children.find(
142
- (c) =>
143
- c.componentName === "Port" &&
144
- (c as Port).isMatchingNameOrAlias(prop as string),
145
- )
146
- if (!port) {
147
- throw new Error(
148
- `There was an issue finding the port "${prop.toString()}" inside of a ${this.componentName} component with name: "${this.props.name}". This is a bug in @tscircuit/core`,
149
- )
150
- }
151
- return port as Port
152
- },
153
- },
154
- ) as any
155
- }
156
-
157
- getInstanceForReactElement(element: ReactElement): NormalComponent | null {
158
- for (const subtree of this.reactSubtrees) {
159
- if (subtree.element === element) return subtree.component
160
- }
161
- return null
162
- }
163
-
164
- doInitialSourceRender() {
165
- const ftype = this.config.sourceFtype
166
- if (!ftype) return
167
- const { db } = this.root!
168
- const { _parsedProps: props } = this
169
- const source_component = db.source_component.insert({
170
- ftype,
171
- name: props.name,
172
- manufacturer_part_number: props.manufacturerPartNumber ?? props.mfn,
173
- supplier_part_numbers: props.supplierPartNumbers,
174
- })
175
- this.source_component_id = source_component.source_component_id
176
- }
177
-
178
- /**
179
- * Render the schematic component for this NormalComponent using the
180
- * config.schematicSymbolName if it exists.
181
- *
182
- * You can override this method to do more complicated things.
183
- */
184
- doInitialSchematicComponentRender() {
185
- const { db } = this.root!
186
- const { schematicSymbolName } = this.config
187
- if (!schematicSymbolName) return
188
- // TODO switch between horizontal and vertical based on schRotation
189
- const symbol_name = `${this.config.schematicSymbolName}_horz`
190
-
191
- const symbol = (symbols as any)[symbol_name] as SchSymbol | undefined
192
-
193
- if (!symbol) {
194
- throw new Error(`Could not find schematic-symbol "${symbol_name}"`)
195
- }
196
-
197
- const schematic_component = db.schematic_component.insert({
198
- center: { x: this.props.schX ?? 0, y: this.props.schY ?? 0 },
199
- rotation: this.props.schRotation ?? 0,
200
- size: symbol.size,
201
- source_component_id: this.source_component_id!,
202
-
203
- // @ts-ignore
204
- symbol_name,
205
- })
206
- this.schematic_component_id = schematic_component.schematic_component_id
207
- }
208
-
209
- doInitialPcbComponentRender() {
210
- const { db } = this.root!
211
- const { _parsedProps: props } = this
212
- const pcb_component = db.pcb_component.insert({
213
- center: this._getGlobalPcbPositionBeforeLayout(),
214
- // width/height are computed in the PcbComponentSizeCalculation phase
215
- width: 0,
216
- height: 0,
217
- layer: props.layer ?? "top",
218
- rotation: props.pcbRotation ?? 0,
219
- source_component_id: this.source_component_id!,
220
- })
221
- this.pcb_component_id = pcb_component.pcb_component_id
222
- }
223
-
224
- /**
225
- * At this stage, the smtpads/pcb primitives are placed, so we can compute
226
- * the width/height of the component
227
- */
228
- doInitialPcbComponentSizeCalculation(): void {
229
- if (!this.pcb_component_id) return
230
- const { db } = this.root!
231
- const { _parsedProps: props } = this
232
-
233
- const bounds = getBoundsOfPcbComponents(this.children)
234
-
235
- db.pcb_component.update(this.pcb_component_id!, {
236
- width: bounds.width,
237
- height: bounds.height,
238
- })
239
- }
240
-
241
- _renderReactSubtree(element: ReactElement): ReactSubtree {
242
- return {
243
- element,
244
- component: createInstanceFromReactElement(element),
245
- }
246
- }
247
-
248
- doInitialInitializePortsFromChildren(): void {
249
- this.initPorts()
250
- }
251
-
252
- doInitialReactSubtreesRender(): void {
253
- if (isReactElement(this.props.footprint)) {
254
- if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
255
- return
256
- const subtree = this._renderReactSubtree(this.props.footprint)
257
- this.reactSubtrees.push(subtree)
258
- this.add(subtree.component)
259
- }
260
- }
261
-
262
- _hasExistingPortExactly(port1: Port): boolean {
263
- const existingPorts = this.children.filter(
264
- (c) => c.componentName === "Port",
265
- ) as Port[]
266
- return existingPorts.some((port2) => {
267
- const aliases1 = port1.getNameAndAliases()
268
- const aliases2 = port2.getNameAndAliases()
269
- return (
270
- aliases1.length === aliases2.length &&
271
- aliases1.every((alias) => aliases2.includes(alias))
272
- )
273
- })
274
- }
275
-
276
- add(componentOrElm: PrimitiveComponent | ReactElement) {
277
- let component: PrimitiveComponent
278
- if (isReactElement(componentOrElm)) {
279
- const subtree = this._renderReactSubtree(componentOrElm)
280
- this.reactSubtrees.push(subtree)
281
- component = subtree.component
282
- } else {
283
- component = componentOrElm as PrimitiveComponent
284
- }
285
-
286
- if (component.componentName === "Port") {
287
- if (this._hasExistingPortExactly(component as Port)) return
288
- // Check if this port is already contained in the children, skip if it's
289
- // already defined
290
- const existingPorts = this.children.filter(
291
- (c) => c.componentName === "Port",
292
- ) as Port[]
293
- const conflictingPort = existingPorts.find((p) =>
294
- p.isMatchingAnyOf(component.getNameAndAliases()),
295
- )
296
- if (conflictingPort) {
297
- throw new Error(
298
- `Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`,
299
- )
300
- }
301
- }
302
-
303
- super.add(component)
304
- }
305
-
306
- getPortsFromFootprint(): Port[] {
307
- let { footprint } = this.props
308
-
309
- if (!footprint || isValidElement(footprint)) {
310
- footprint = this.children.find((c) => c.componentName === "Footprint")
311
- }
312
-
313
- if (typeof footprint === "string") {
314
- const fpSoup = fp.string(footprint).soup()
315
-
316
- const newPorts: Port[] = []
317
- for (const elm of fpSoup) {
318
- if ("port_hints" in elm && elm.port_hints) {
319
- const newPort = getPortFromHints(elm.port_hints)
320
- if (!newPort) continue
321
- newPorts.push(newPort)
322
- }
323
- }
324
-
325
- return newPorts
326
- }
327
- if (
328
- !isValidElement(footprint) &&
329
- footprint &&
330
- footprint.componentName === "Footprint"
331
- ) {
332
- const fp = footprint as Footprint
333
-
334
- const newPorts: Port[] = []
335
- for (const fpChild of fp.children) {
336
- const newPort = getPortFromHints(fpChild.props.portHints ?? [])
337
- if (!newPort) continue
338
- newPorts.push(newPort)
339
- }
340
-
341
- if (newPorts.length === 0) {
342
- throw new Error(
343
- `No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`,
344
- )
345
- }
346
-
347
- return newPorts
348
- }
349
-
350
- // Explore children for possible smtpads etc.
351
- const newPorts: Port[] = []
352
- if (!footprint) {
353
- for (const child of this.children) {
354
- if (child.props.portHints && child.isPcbPrimitive) {
355
- const port = getPortFromHints(child.props.portHints)
356
- if (port) newPorts.push(port)
357
- }
358
- }
359
- }
360
- return newPorts
361
- }
362
-
363
- getPortsFromSchematicSymbol(): Port[] {
364
- const { config } = this
365
- if (!config.schematicSymbolName) return []
366
- const symbol: SchSymbol = (symbols as any)[config.schematicSymbolName]
367
- if (!symbol) return []
368
- const newPorts: Port[] = []
369
- for (const symbolPort of symbol.ports) {
370
- const port = getPortFromHints(symbolPort.labels)
371
- if (port) {
372
- port.schematicSymbolPortDef = symbolPort
373
- newPorts.push(port)
374
- }
375
- }
376
- return newPorts
377
- }
378
-
379
- _createNetsFromProps(propsWithConnections: (string | undefined | null)[]) {
380
- createNetsFromProps(this, propsWithConnections)
381
- }
382
-
383
- /**
384
- * Use data from our props to create ports for this component.
385
- *
386
- * Generally, this is done by looking at the schematic and the footprint,
387
- * reading the pins, making sure there aren't duplicates.
388
- *
389
- * Can probably be removed in favor of initPorts()
390
- *
391
- */
392
- doInitialPortDiscovery(): void {
393
- const newPorts = [
394
- ...this.getPortsFromFootprint(),
395
- ...this.getPortsFromSchematicSymbol(),
396
- ]
397
-
398
- const existingPorts = this.children.filter(
399
- (c) => c.componentName === "Port",
400
- ) as Port[]
401
-
402
- for (const newPort of newPorts) {
403
- const existingPort = existingPorts.find((p) =>
404
- p.isMatchingAnyOf(newPort.getNameAndAliases()),
405
- )
406
- if (existingPort) {
407
- if (
408
- !existingPort.schematicSymbolPortDef &&
409
- newPort.schematicSymbolPortDef
410
- ) {
411
- existingPort.schematicSymbolPortDef = newPort.schematicSymbolPortDef
412
- }
413
- continue
414
- }
415
- existingPorts.push(newPort)
416
- this.add(newPort)
417
- }
418
- }
419
- }