@tscircuit/core 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +208 -56
- package/dist/index.js +368 -97
- package/lib/Project.ts +19 -15
- package/lib/components/base-components/NormalComponent.ts +61 -13
- package/lib/components/base-components/PrimitiveComponent.ts +63 -19
- package/lib/components/base-components/Renderable.ts +5 -3
- package/lib/components/index.ts +1 -0
- package/lib/components/normal-components/Board.ts +3 -3
- package/lib/components/normal-components/Capacitor.ts +1 -1
- package/lib/components/normal-components/Chip.ts +3 -3
- package/lib/components/normal-components/Jumper.ts +3 -3
- package/lib/components/normal-components/Resistor.ts +1 -1
- package/lib/components/primitive-components/Constraint.ts +49 -0
- package/lib/components/primitive-components/Footprint.ts +158 -1
- package/lib/components/primitive-components/Net.ts +4 -4
- package/lib/components/primitive-components/PlatedHole.ts +2 -2
- package/lib/components/primitive-components/Port.ts +12 -17
- package/lib/components/primitive-components/SilkscreenPath.ts +2 -2
- package/lib/components/primitive-components/SmtPad.ts +55 -5
- package/lib/components/primitive-components/Trace.ts +7 -7
- package/lib/components/primitive-components/TraceHint.ts +2 -2
- package/lib/fiber/intrinsic-jsx.ts +2 -0
- package/lib/utils/getClosest.ts +9 -3
- package/package.json +5 -2
package/lib/Project.ts
CHANGED
|
@@ -7,15 +7,18 @@ import { createInstanceFromReactElement } from "./fiber/create-instance-from-rea
|
|
|
7
7
|
import { identity, type Matrix } from "transformation-matrix"
|
|
8
8
|
|
|
9
9
|
export class Circuit {
|
|
10
|
-
|
|
10
|
+
firstChild: PrimitiveComponent | null = null
|
|
11
11
|
children: PrimitiveComponent[]
|
|
12
12
|
db: SoupUtilObjects
|
|
13
|
+
root: Circuit | null = null
|
|
14
|
+
isRoot = true
|
|
13
15
|
|
|
14
16
|
_hasRenderedAtleastOnce = false
|
|
15
17
|
|
|
16
18
|
constructor() {
|
|
17
19
|
this.children = []
|
|
18
20
|
this.db = su([])
|
|
21
|
+
this.root = this
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
@@ -30,9 +33,9 @@ export class Circuit {
|
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
_guessRootComponent() {
|
|
33
|
-
if (this.
|
|
36
|
+
if (this.firstChild) return
|
|
34
37
|
if (this.children.length === 1) {
|
|
35
|
-
this.
|
|
38
|
+
this.firstChild = this.children[0]
|
|
36
39
|
return
|
|
37
40
|
}
|
|
38
41
|
if (this.children.length === 0) {
|
|
@@ -46,7 +49,7 @@ export class Circuit {
|
|
|
46
49
|
this.children.find((c) => c.componentName === "Board") ?? null
|
|
47
50
|
|
|
48
51
|
if (board) {
|
|
49
|
-
this.
|
|
52
|
+
this.firstChild = board
|
|
50
53
|
return
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -56,16 +59,14 @@ export class Circuit {
|
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
render() {
|
|
59
|
-
if (!this.
|
|
62
|
+
if (!this.firstChild) {
|
|
60
63
|
this._guessRootComponent()
|
|
61
64
|
}
|
|
62
|
-
const {
|
|
65
|
+
const { firstChild, db } = this
|
|
63
66
|
|
|
64
|
-
if (!
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
rootComponent.runRenderCycle()
|
|
67
|
+
if (!firstChild) throw new Error("Project has no root component")
|
|
68
|
+
firstChild.parent = this as any
|
|
69
|
+
firstChild.runRenderCycle()
|
|
69
70
|
this._hasRenderedAtleastOnce = true
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -103,24 +104,27 @@ export class Circuit {
|
|
|
103
104
|
throw new Error("project.preview is not yet implemented")
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
computeSchematicGlobalTransform(): Matrix {
|
|
107
108
|
return identity()
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
_computePcbGlobalTransformBeforeLayout(): Matrix {
|
|
111
112
|
return identity()
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
selectAll(selector: string): PrimitiveComponent[] {
|
|
115
|
-
return this.
|
|
116
|
+
return this.firstChild?.selectAll(selector) ?? []
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
selectOne(
|
|
119
120
|
selector: string,
|
|
120
121
|
opts?: { type?: "component" | "port" },
|
|
121
122
|
): PrimitiveComponent | null {
|
|
122
|
-
return this.
|
|
123
|
+
return this.firstChild?.selectOne(selector, opts) ?? null
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
|
|
127
|
+
/**
|
|
128
|
+
* @deprecated
|
|
129
|
+
*/
|
|
126
130
|
export const Project = Circuit
|
|
@@ -46,6 +46,8 @@ export class NormalComponent<
|
|
|
46
46
|
> extends PrimitiveComponent<ZodProps> {
|
|
47
47
|
reactSubtrees: Array<ReactSubtree> = []
|
|
48
48
|
|
|
49
|
+
isPrimitiveContainer = true
|
|
50
|
+
|
|
49
51
|
constructor(props: z.input<ZodProps>) {
|
|
50
52
|
super(props)
|
|
51
53
|
this._addChildrenFromStringFootprint()
|
|
@@ -68,6 +70,7 @@ export class NormalComponent<
|
|
|
68
70
|
*/
|
|
69
71
|
initPorts() {
|
|
70
72
|
const { config } = this
|
|
73
|
+
const portsToCreate: Port[] = []
|
|
71
74
|
if (config.schematicSymbolName) {
|
|
72
75
|
const sym = symbols[
|
|
73
76
|
`${config.schematicSymbolName}_horz` as keyof typeof symbols
|
|
@@ -79,32 +82,36 @@ export class NormalComponent<
|
|
|
79
82
|
|
|
80
83
|
if (port) {
|
|
81
84
|
port.schematicSymbolPortDef = symPort
|
|
82
|
-
|
|
85
|
+
portsToCreate.push(port)
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
89
|
+
this.addAll(portsToCreate)
|
|
86
90
|
return
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
const portsFromFootprint = this.getPortsFromFootprint()
|
|
90
|
-
|
|
91
|
-
this.addAll(portsFromFootprint)
|
|
94
|
+
portsToCreate.push(...portsFromFootprint)
|
|
92
95
|
|
|
93
96
|
const pinLabels: Record<string, string> | undefined =
|
|
94
97
|
this._parsedProps.pinLabels
|
|
95
98
|
if (pinLabels) {
|
|
96
99
|
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
97
100
|
pinNumber = pinNumber.replace("pin", "")
|
|
98
|
-
const
|
|
99
|
-
|
|
101
|
+
const existingPort = portsToCreate.find(
|
|
102
|
+
(p) => p._parsedProps.pinNumber === Number(pinNumber),
|
|
103
|
+
)
|
|
104
|
+
if (!existingPort) {
|
|
100
105
|
throw new Error(
|
|
101
106
|
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`,
|
|
102
107
|
)
|
|
103
108
|
}
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
existingPort.externallyAddedAliases.push(label)
|
|
110
|
+
existingPort.props.name = label
|
|
106
111
|
}
|
|
107
112
|
}
|
|
113
|
+
|
|
114
|
+
this.addAll(portsToCreate)
|
|
108
115
|
}
|
|
109
116
|
|
|
110
117
|
_addChildrenFromStringFootprint() {
|
|
@@ -148,7 +155,7 @@ export class NormalComponent<
|
|
|
148
155
|
doInitialSourceRender() {
|
|
149
156
|
const ftype = this.config.sourceFtype
|
|
150
157
|
if (!ftype) return
|
|
151
|
-
const { db } = this.
|
|
158
|
+
const { db } = this.root!
|
|
152
159
|
const { _parsedProps: props } = this
|
|
153
160
|
const source_component = db.source_component.insert({
|
|
154
161
|
ftype,
|
|
@@ -166,7 +173,7 @@ export class NormalComponent<
|
|
|
166
173
|
* You can override this method to do more complicated things.
|
|
167
174
|
*/
|
|
168
175
|
doInitialSchematicComponentRender() {
|
|
169
|
-
const { db } = this.
|
|
176
|
+
const { db } = this.root!
|
|
170
177
|
const { schematicSymbolName } = this.config
|
|
171
178
|
if (!schematicSymbolName) return
|
|
172
179
|
// TODO switch between horizontal and vertical based on schRotation
|
|
@@ -191,10 +198,10 @@ export class NormalComponent<
|
|
|
191
198
|
}
|
|
192
199
|
|
|
193
200
|
doInitialPcbComponentRender() {
|
|
194
|
-
const { db } = this.
|
|
201
|
+
const { db } = this.root!
|
|
195
202
|
const { _parsedProps: props } = this
|
|
196
203
|
const pcb_component = db.pcb_component.insert({
|
|
197
|
-
center: this.
|
|
204
|
+
center: this._getGlobalPcbPositionBeforeLayout(),
|
|
198
205
|
// width/height are computed in the PcbComponentSizeCalculation phase
|
|
199
206
|
width: 0,
|
|
200
207
|
height: 0,
|
|
@@ -211,7 +218,7 @@ export class NormalComponent<
|
|
|
211
218
|
*/
|
|
212
219
|
doInitialPcbComponentSizeCalculation(): void {
|
|
213
220
|
if (!this.pcb_component_id) return
|
|
214
|
-
const { db } = this.
|
|
221
|
+
const { db } = this.root!
|
|
215
222
|
const { _parsedProps: props } = this
|
|
216
223
|
|
|
217
224
|
let minX = Infinity
|
|
@@ -221,7 +228,7 @@ export class NormalComponent<
|
|
|
221
228
|
|
|
222
229
|
for (const child of this.children) {
|
|
223
230
|
if (child.isPcbPrimitive) {
|
|
224
|
-
const { x, y } = child.
|
|
231
|
+
const { x, y } = child._getGlobalPcbPositionBeforeLayout()
|
|
225
232
|
const { width, height } = child.getPcbSize()
|
|
226
233
|
minX = Math.min(minX, x - width / 2)
|
|
227
234
|
minY = Math.min(minY, y - height / 2)
|
|
@@ -246,6 +253,10 @@ export class NormalComponent<
|
|
|
246
253
|
}
|
|
247
254
|
}
|
|
248
255
|
|
|
256
|
+
doInitialInitializePortsFromChildren(): void {
|
|
257
|
+
this.initPorts()
|
|
258
|
+
}
|
|
259
|
+
|
|
249
260
|
doInitialReactSubtreesRender(): void {
|
|
250
261
|
if (isReactElement(this.props.footprint)) {
|
|
251
262
|
if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
|
|
@@ -256,6 +267,20 @@ export class NormalComponent<
|
|
|
256
267
|
}
|
|
257
268
|
}
|
|
258
269
|
|
|
270
|
+
_hasExistingPortExactly(port1: Port): boolean {
|
|
271
|
+
const existingPorts = this.children.filter(
|
|
272
|
+
(c) => c.componentName === "Port",
|
|
273
|
+
) as Port[]
|
|
274
|
+
return existingPorts.some((port2) => {
|
|
275
|
+
const aliases1 = port1.getNameAndAliases()
|
|
276
|
+
const aliases2 = port2.getNameAndAliases()
|
|
277
|
+
return (
|
|
278
|
+
aliases1.length === aliases2.length &&
|
|
279
|
+
aliases1.every((alias) => aliases2.includes(alias))
|
|
280
|
+
)
|
|
281
|
+
})
|
|
282
|
+
}
|
|
283
|
+
|
|
259
284
|
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
260
285
|
let component: PrimitiveComponent
|
|
261
286
|
if (isReactElement(componentOrElm)) {
|
|
@@ -266,6 +291,23 @@ export class NormalComponent<
|
|
|
266
291
|
component = componentOrElm as PrimitiveComponent
|
|
267
292
|
}
|
|
268
293
|
|
|
294
|
+
if (component.componentName === "Port") {
|
|
295
|
+
if (this._hasExistingPortExactly(component as Port)) return
|
|
296
|
+
// Check if this port is already contained in the children, skip if it's
|
|
297
|
+
// already defined
|
|
298
|
+
const existingPorts = this.children.filter(
|
|
299
|
+
(c) => c.componentName === "Port",
|
|
300
|
+
) as Port[]
|
|
301
|
+
const conflictingPort = existingPorts.find((p) =>
|
|
302
|
+
p.isMatchingAnyOf(component.getNameAndAliases()),
|
|
303
|
+
)
|
|
304
|
+
if (conflictingPort) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`,
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
269
311
|
super.add(component)
|
|
270
312
|
}
|
|
271
313
|
|
|
@@ -304,6 +346,12 @@ export class NormalComponent<
|
|
|
304
346
|
newPorts.push(newPort)
|
|
305
347
|
}
|
|
306
348
|
|
|
349
|
+
if (newPorts.length === 0) {
|
|
350
|
+
throw new Error(
|
|
351
|
+
`No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`,
|
|
352
|
+
)
|
|
353
|
+
}
|
|
354
|
+
|
|
307
355
|
return newPorts
|
|
308
356
|
}
|
|
309
357
|
|
|
@@ -41,7 +41,6 @@ export abstract class PrimitiveComponent<
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
project: Circuit | null = null
|
|
45
44
|
props: z.input<ZodProps>
|
|
46
45
|
_parsedProps: z.infer<ZodProps>
|
|
47
46
|
|
|
@@ -60,11 +59,22 @@ export abstract class PrimitiveComponent<
|
|
|
60
59
|
return (
|
|
61
60
|
Boolean(this.props.subcircuit) ||
|
|
62
61
|
// Implied opaque group for top-level group
|
|
63
|
-
(this.lowercaseComponentName === "group" &&
|
|
64
|
-
this?.parent?.props?.name === "$root")
|
|
62
|
+
(this.lowercaseComponentName === "group" && (this?.parent as any)?.isRoot)
|
|
65
63
|
)
|
|
66
64
|
}
|
|
67
65
|
|
|
66
|
+
/**
|
|
67
|
+
* A primitive container is a component that contains one or more ports and
|
|
68
|
+
* primitive components that are designed to interact.
|
|
69
|
+
*
|
|
70
|
+
* For example a resistor contains ports and smtpads that interact, so the
|
|
71
|
+
* resistor is a primitive container. Inside a primitive container, the ports
|
|
72
|
+
* and pads are likely to reference each other and look for eachother during
|
|
73
|
+
* the port matching phase.
|
|
74
|
+
*
|
|
75
|
+
*/
|
|
76
|
+
isPrimitiveContainer = false
|
|
77
|
+
|
|
68
78
|
source_group_id: string | null = null
|
|
69
79
|
source_component_id: string | null = null
|
|
70
80
|
schematic_component_id: string | null = null
|
|
@@ -86,13 +96,6 @@ export abstract class PrimitiveComponent<
|
|
|
86
96
|
}
|
|
87
97
|
}
|
|
88
98
|
|
|
89
|
-
setProject(project: Circuit) {
|
|
90
|
-
this.project = project
|
|
91
|
-
for (const c of this.children) {
|
|
92
|
-
c.setProject(project)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
99
|
setProps(props: Partial<z.input<ZodProps>>) {
|
|
97
100
|
const newProps = this.config.zodProps.parse({
|
|
98
101
|
...this.props,
|
|
@@ -129,9 +132,9 @@ export abstract class PrimitiveComponent<
|
|
|
129
132
|
* components, including this component's translation and rotation.
|
|
130
133
|
*
|
|
131
134
|
* This is used to compute this component's position as well as all children
|
|
132
|
-
* components positions
|
|
135
|
+
* components positions before layout is applied
|
|
133
136
|
*/
|
|
134
|
-
|
|
137
|
+
_computePcbGlobalTransformBeforeLayout(): Matrix {
|
|
135
138
|
const { _parsedProps: props } = this
|
|
136
139
|
const manualPlacement =
|
|
137
140
|
this.getSubcircuit()._getManualPlacementForComponent(this)
|
|
@@ -143,7 +146,7 @@ export abstract class PrimitiveComponent<
|
|
|
143
146
|
this.props.pcbY === undefined
|
|
144
147
|
) {
|
|
145
148
|
return compose(
|
|
146
|
-
this.parent?.
|
|
149
|
+
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity(),
|
|
147
150
|
compose(
|
|
148
151
|
translate(manualPlacement.x, manualPlacement.y),
|
|
149
152
|
rotate(((props.pcbRotation ?? 0) * Math.PI) / 180),
|
|
@@ -152,11 +155,46 @@ export abstract class PrimitiveComponent<
|
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
return compose(
|
|
155
|
-
this.parent?.
|
|
158
|
+
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity(),
|
|
156
159
|
this.computePcbPropsTransform(),
|
|
157
160
|
)
|
|
158
161
|
}
|
|
159
162
|
|
|
163
|
+
getPrimitiveContainer(): PrimitiveComponent | null {
|
|
164
|
+
if (this.isPrimitiveContainer) return this
|
|
165
|
+
return this.parent?.getPrimitiveContainer?.() ?? null
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Compute the bounds of this component the circuit json elements associated
|
|
170
|
+
* with it.
|
|
171
|
+
*/
|
|
172
|
+
_getCircuitJsonBounds(): {
|
|
173
|
+
center: { x: number; y: number }
|
|
174
|
+
bounds: { left: number; top: number; right: number; bottom: number }
|
|
175
|
+
width: number
|
|
176
|
+
height: number
|
|
177
|
+
} {
|
|
178
|
+
return {
|
|
179
|
+
center: { x: 0, y: 0 },
|
|
180
|
+
bounds: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
181
|
+
width: 0,
|
|
182
|
+
height: 0,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Set the position of this component from the layout solver. This method
|
|
188
|
+
* should operate using CircuitJson associated with this component, like
|
|
189
|
+
* _getCircuitJsonBounds it can be called multiple times as different
|
|
190
|
+
* parents apply layout to their children.
|
|
191
|
+
*/
|
|
192
|
+
_setPositionFromLayout(newCenter: { x: number; y: number }) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`_setPositionFromLayout not implemented for ${this.componentName}`,
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
|
|
160
198
|
/**
|
|
161
199
|
* Computes a transformation matrix from the props of this component for
|
|
162
200
|
* schematic components
|
|
@@ -209,7 +247,7 @@ export abstract class PrimitiveComponent<
|
|
|
209
247
|
for (const position of placementConfig.positions) {
|
|
210
248
|
if (isMatchingSelector(component, position.selector)) {
|
|
211
249
|
const center = applyToPoint(
|
|
212
|
-
this.
|
|
250
|
+
this._computePcbGlobalTransformBeforeLayout(),
|
|
213
251
|
position.center,
|
|
214
252
|
)
|
|
215
253
|
return center
|
|
@@ -219,17 +257,23 @@ export abstract class PrimitiveComponent<
|
|
|
219
257
|
return null
|
|
220
258
|
}
|
|
221
259
|
|
|
222
|
-
|
|
223
|
-
return applyToPoint(this.
|
|
260
|
+
_getGlobalPcbPositionBeforeLayout(): { x: number; y: number } {
|
|
261
|
+
return applyToPoint(this._computePcbGlobalTransformBeforeLayout(), {
|
|
262
|
+
x: 0,
|
|
263
|
+
y: 0,
|
|
264
|
+
})
|
|
224
265
|
}
|
|
225
266
|
|
|
226
|
-
|
|
267
|
+
_getGlobalSchematicPositionBeforeLayout(): { x: number; y: number } {
|
|
227
268
|
return applyToPoint(this.computeSchematicGlobalTransform(), { x: 0, y: 0 })
|
|
228
269
|
}
|
|
229
270
|
|
|
271
|
+
get root(): Circuit | null {
|
|
272
|
+
return this.parent?.root ?? null
|
|
273
|
+
}
|
|
274
|
+
|
|
230
275
|
onAddToParent(parent: PrimitiveComponent) {
|
|
231
276
|
this.parent = parent
|
|
232
|
-
this.project = parent.project
|
|
233
277
|
}
|
|
234
278
|
|
|
235
279
|
/**
|
|
@@ -2,12 +2,13 @@ import type { PCBPlacementError, PCBTraceError } from "@tscircuit/soup"
|
|
|
2
2
|
import { Component, createElement, type ReactElement } from "react"
|
|
3
3
|
|
|
4
4
|
export const orderedRenderPhases = [
|
|
5
|
-
"ReactSubtreesRender",
|
|
5
|
+
"ReactSubtreesRender",
|
|
6
|
+
"InitializePortsFromChildren",
|
|
6
7
|
"CreateNetsFromProps",
|
|
7
8
|
"CreateTracesFromProps",
|
|
8
9
|
"SourceRender",
|
|
9
10
|
"SourceParentAttachment",
|
|
10
|
-
"PortDiscovery",
|
|
11
|
+
"PortDiscovery",
|
|
11
12
|
"PortMatching",
|
|
12
13
|
"SourceTraceRender",
|
|
13
14
|
"SchematicComponentRender",
|
|
@@ -15,8 +16,9 @@ export const orderedRenderPhases = [
|
|
|
15
16
|
"SchematicPortRender",
|
|
16
17
|
"SchematicTraceRender",
|
|
17
18
|
"PcbComponentRender",
|
|
18
|
-
"PcbPortRender",
|
|
19
19
|
"PcbPrimitiveRender",
|
|
20
|
+
"PcbFootprintLayout",
|
|
21
|
+
"PcbPortRender",
|
|
20
22
|
"PcbParentAttachment",
|
|
21
23
|
"PcbLayout",
|
|
22
24
|
"PcbTraceRender",
|
package/lib/components/index.ts
CHANGED
|
@@ -16,3 +16,4 @@ export { Chip } from "./normal-components/Chip"
|
|
|
16
16
|
export { Jumper } from "./normal-components/Jumper"
|
|
17
17
|
export { SilkscreenPath } from "./primitive-components/SilkscreenPath"
|
|
18
18
|
export { PlatedHole } from "./primitive-components/PlatedHole"
|
|
19
|
+
export { Constraint } from "./primitive-components/Constraint"
|
|
@@ -18,7 +18,7 @@ export class Board extends Group<typeof boardProps> {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
doInitialPcbComponentRender(): void {
|
|
21
|
-
const { db } = this.
|
|
21
|
+
const { db } = this.root!
|
|
22
22
|
const { _parsedProps: props } = this
|
|
23
23
|
|
|
24
24
|
if (!props.width || !props.height) {
|
|
@@ -36,13 +36,13 @@ export class Board extends Group<typeof boardProps> {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
removePcbComponentRender(): void {
|
|
39
|
-
const { db } = this.
|
|
39
|
+
const { db } = this.root!
|
|
40
40
|
if (!this.pcb_board_id) return
|
|
41
41
|
db.pcb_board.delete(this.pcb_board_id!)
|
|
42
42
|
this.pcb_board_id = null
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
_computePcbGlobalTransformBeforeLayout(): Matrix {
|
|
46
46
|
return identity()
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -54,7 +54,7 @@ export class Capacitor extends NormalComponent<
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
doInitialSourceRender() {
|
|
57
|
-
const { db } = this.
|
|
57
|
+
const { db } = this.root!
|
|
58
58
|
const { _parsedProps: props } = this
|
|
59
59
|
const source_component = db.source_component.insert({
|
|
60
60
|
ftype: "simple_capacitor",
|
|
@@ -22,7 +22,7 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
doInitialSourceRender(): void {
|
|
25
|
-
const { db } = this.
|
|
25
|
+
const { db } = this.root!
|
|
26
26
|
const { _parsedProps: props } = this
|
|
27
27
|
|
|
28
28
|
const source_component = db.source_component.insert({
|
|
@@ -36,7 +36,7 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
doInitialSchematicComponentRender() {
|
|
39
|
-
const { db } = this.
|
|
39
|
+
const { db } = this.root!
|
|
40
40
|
const { _parsedProps: props } = this
|
|
41
41
|
|
|
42
42
|
const ports = this.children.filter((child) => child instanceof Port)
|
|
@@ -81,7 +81,7 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
doInitialPcbComponentRender() {
|
|
84
|
-
const { db } = this.
|
|
84
|
+
const { db } = this.root!
|
|
85
85
|
const { _parsedProps: props } = this
|
|
86
86
|
|
|
87
87
|
const pcb_component = db.pcb_component.insert({
|
|
@@ -22,7 +22,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
doInitialSourceRender(): void {
|
|
25
|
-
const { db } = this.
|
|
25
|
+
const { db } = this.root!
|
|
26
26
|
const { _parsedProps: props } = this
|
|
27
27
|
|
|
28
28
|
const source_component = db.source_component.insert({
|
|
@@ -36,7 +36,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
doInitialSchematicComponentRender() {
|
|
39
|
-
const { db } = this.
|
|
39
|
+
const { db } = this.root!
|
|
40
40
|
const { _parsedProps: props } = this
|
|
41
41
|
|
|
42
42
|
const ports = this.children.filter((child) => child instanceof Port)
|
|
@@ -84,7 +84,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
doInitialPcbComponentRender() {
|
|
87
|
-
const { db } = this.
|
|
87
|
+
const { db } = this.root!
|
|
88
88
|
const { _parsedProps: props } = this
|
|
89
89
|
|
|
90
90
|
const pcb_component = db.pcb_component.insert({
|
|
@@ -43,7 +43,7 @@ export class Resistor extends NormalComponent<
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
doInitialSourceRender() {
|
|
46
|
-
const { db } = this.
|
|
46
|
+
const { db } = this.root!
|
|
47
47
|
const { _parsedProps: props } = this
|
|
48
48
|
const source_component = db.source_component.insert({
|
|
49
49
|
ftype: "simple_resistor",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { constraintProps } from "@tscircuit/props"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
import { PrimitiveComponent } from "../base-components/PrimitiveComponent"
|
|
4
|
+
|
|
5
|
+
export class Constraint extends PrimitiveComponent<typeof constraintProps> {
|
|
6
|
+
get config() {
|
|
7
|
+
return {
|
|
8
|
+
zodProps: constraintProps,
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
constructor(props: z.input<typeof constraintProps>) {
|
|
13
|
+
super(props)
|
|
14
|
+
if ("xdist" in props || "ydist" in props) {
|
|
15
|
+
if (!("edgeToEdge" in props) && !("centerToCenter" in props)) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
"edgeToEdge, centerToCenter (or from*/to* props) must be set for xdist or ydist for <constraint />",
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_getAllReferencedComponents(): {
|
|
24
|
+
componentsWithSelectors: Array<{
|
|
25
|
+
component: PrimitiveComponent<any>
|
|
26
|
+
selector: string
|
|
27
|
+
}>
|
|
28
|
+
} {
|
|
29
|
+
const componentsWithSelectors: Array<{
|
|
30
|
+
component: PrimitiveComponent<any>
|
|
31
|
+
selector: string
|
|
32
|
+
}> = []
|
|
33
|
+
|
|
34
|
+
for (const key of ["left", "right", "top", "bottom"]) {
|
|
35
|
+
if (key in this._parsedProps) {
|
|
36
|
+
const selector = (this._parsedProps as any)[key] as string
|
|
37
|
+
const component = this.getSubcircuit().selectOne(selector)
|
|
38
|
+
if (component) {
|
|
39
|
+
componentsWithSelectors.push({
|
|
40
|
+
selector,
|
|
41
|
+
component,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { componentsWithSelectors }
|
|
48
|
+
}
|
|
49
|
+
}
|