@tscircuit/core 0.0.29 → 0.0.30
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 +10 -7
- package/dist/index.js +93 -57
- package/lib/Project.ts +16 -15
- package/lib/components/base-components/NormalComponent.ts +57 -11
- package/lib/components/base-components/PrimitiveComponent.ts +5 -11
- package/lib/components/base-components/Renderable.ts +1 -0
- package/lib/components/normal-components/Board.ts +2 -2
- 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/Net.ts +2 -2
- package/lib/components/primitive-components/PlatedHole.ts +1 -1
- package/lib/components/primitive-components/Port.ts +4 -4
- package/lib/components/primitive-components/SilkscreenPath.ts +1 -1
- package/lib/components/primitive-components/SmtPad.ts +1 -1
- package/lib/components/primitive-components/Trace.ts +5 -5
- package/lib/components/primitive-components/TraceHint.ts +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -9,9 +9,11 @@ import * as Props from '@tscircuit/props';
|
|
|
9
9
|
import { traceProps, groupProps, boardProps, footprintProps, smtPadProps, resistorProps, ledProps, capacitorProps, traceHintProps, chipProps, jumperProps, silkscreenPathProps, platedHoleProps } from '@tscircuit/props';
|
|
10
10
|
|
|
11
11
|
declare class Circuit {
|
|
12
|
-
|
|
12
|
+
firstChild: PrimitiveComponent | null;
|
|
13
13
|
children: PrimitiveComponent[];
|
|
14
14
|
db: SoupUtilObjects;
|
|
15
|
+
root: Circuit | null;
|
|
16
|
+
isRoot: boolean;
|
|
15
17
|
_hasRenderedAtleastOnce: boolean;
|
|
16
18
|
constructor();
|
|
17
19
|
add(componentOrElm: PrimitiveComponent | ReactElement): void;
|
|
@@ -27,8 +29,8 @@ declare class Circuit {
|
|
|
27
29
|
previewName: string;
|
|
28
30
|
tscircuitApiKey?: string;
|
|
29
31
|
}): Promise<void>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
computeSchematicGlobalTransform(): Matrix;
|
|
33
|
+
computePcbGlobalTransform(): Matrix;
|
|
32
34
|
selectAll(selector: string): PrimitiveComponent[];
|
|
33
35
|
selectOne(selector: string, opts?: {
|
|
34
36
|
type?: "component" | "port";
|
|
@@ -36,7 +38,7 @@ declare class Circuit {
|
|
|
36
38
|
}
|
|
37
39
|
declare const Project: typeof Circuit;
|
|
38
40
|
|
|
39
|
-
declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "CreateNetsFromProps", "CreateTracesFromProps", "SourceRender", "SourceParentAttachment", "PortDiscovery", "PortMatching", "SourceTraceRender", "SchematicComponentRender", "SchematicLayout", "SchematicPortRender", "SchematicTraceRender", "PcbComponentRender", "PcbPortRender", "PcbPrimitiveRender", "PcbParentAttachment", "PcbLayout", "PcbTraceRender", "PcbRouteNetIslands", "PcbComponentSizeCalculation", "CadModelRender"];
|
|
41
|
+
declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InitializePortsFromChildren", "CreateNetsFromProps", "CreateTracesFromProps", "SourceRender", "SourceParentAttachment", "PortDiscovery", "PortMatching", "SourceTraceRender", "SchematicComponentRender", "SchematicLayout", "SchematicPortRender", "SchematicTraceRender", "PcbComponentRender", "PcbPortRender", "PcbPrimitiveRender", "PcbParentAttachment", "PcbLayout", "PcbTraceRender", "PcbRouteNetIslands", "PcbComponentSizeCalculation", "CadModelRender"];
|
|
40
42
|
type RenderPhase = (typeof orderedRenderPhases)[number];
|
|
41
43
|
type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
|
|
42
44
|
type RenderPhaseStates = Record<RenderPhase, {
|
|
@@ -91,7 +93,6 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
91
93
|
children: PrimitiveComponent[];
|
|
92
94
|
childrenPendingRemoval: PrimitiveComponent[];
|
|
93
95
|
get config(): BaseComponentConfig;
|
|
94
|
-
project: Circuit | null;
|
|
95
96
|
props: z.input<ZodProps>;
|
|
96
97
|
_parsedProps: z.infer<ZodProps>;
|
|
97
98
|
componentName: string;
|
|
@@ -103,14 +104,13 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
103
104
|
* subcircuits and their selectors will not interact with each other (even if the
|
|
104
105
|
* components share the same names) unless you explicitly break out some ports
|
|
105
106
|
*/
|
|
106
|
-
get isSubcircuit():
|
|
107
|
+
get isSubcircuit(): any;
|
|
107
108
|
source_group_id: string | null;
|
|
108
109
|
source_component_id: string | null;
|
|
109
110
|
schematic_component_id: string | null;
|
|
110
111
|
pcb_component_id: string | null;
|
|
111
112
|
cad_component_id: string | null;
|
|
112
113
|
constructor(props: z.input<ZodProps>);
|
|
113
|
-
setProject(project: Circuit): void;
|
|
114
114
|
setProps(props: Partial<z.input<ZodProps>>): void;
|
|
115
115
|
/**
|
|
116
116
|
* Computes a transformation matrix from the props of this component for PCB
|
|
@@ -152,6 +152,7 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
152
152
|
x: number;
|
|
153
153
|
y: number;
|
|
154
154
|
};
|
|
155
|
+
get root(): Circuit | null;
|
|
155
156
|
onAddToParent(parent: PrimitiveComponent): void;
|
|
156
157
|
/**
|
|
157
158
|
* Called whenever the props change
|
|
@@ -558,7 +559,9 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
|
|
|
558
559
|
*/
|
|
559
560
|
doInitialPcbComponentSizeCalculation(): void;
|
|
560
561
|
_renderReactSubtree(element: ReactElement): ReactSubtree;
|
|
562
|
+
doInitialInitializePortsFromChildren(): void;
|
|
561
563
|
doInitialReactSubtreesRender(): void;
|
|
564
|
+
_hasExistingPortExactly(port1: Port): boolean;
|
|
562
565
|
add(componentOrElm: PrimitiveComponent | ReactElement): void;
|
|
563
566
|
getPortsFromFootprint(): Port[];
|
|
564
567
|
getPortsFromSchematicSymbol(): Port[];
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import "react";
|
|
|
37
37
|
var orderedRenderPhases = [
|
|
38
38
|
"ReactSubtreesRender",
|
|
39
39
|
// probably going to be removed b/c subtrees should render instantly
|
|
40
|
+
"InitializePortsFromChildren",
|
|
40
41
|
"CreateNetsFromProps",
|
|
41
42
|
"CreateTracesFromProps",
|
|
42
43
|
"SourceRender",
|
|
@@ -169,7 +170,6 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
169
170
|
zodProps: z.object({}).passthrough()
|
|
170
171
|
};
|
|
171
172
|
}
|
|
172
|
-
project = null;
|
|
173
173
|
props;
|
|
174
174
|
_parsedProps;
|
|
175
175
|
componentName = "";
|
|
@@ -183,7 +183,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
183
183
|
*/
|
|
184
184
|
get isSubcircuit() {
|
|
185
185
|
return Boolean(this.props.subcircuit) || // Implied opaque group for top-level group
|
|
186
|
-
this.lowercaseComponentName === "group" && this?.parent?.
|
|
186
|
+
this.lowercaseComponentName === "group" && this?.parent?.isRoot;
|
|
187
187
|
}
|
|
188
188
|
source_group_id = null;
|
|
189
189
|
source_component_id = null;
|
|
@@ -204,12 +204,6 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
204
204
|
this.lowercaseComponentName = this.componentName.toLowerCase();
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
-
setProject(project) {
|
|
208
|
-
this.project = project;
|
|
209
|
-
for (const c of this.children) {
|
|
210
|
-
c.setProject(project);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
207
|
setProps(props) {
|
|
214
208
|
const newProps = this.config.zodProps.parse({
|
|
215
209
|
...this.props,
|
|
@@ -315,9 +309,11 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
315
309
|
getGlobalSchematicPosition() {
|
|
316
310
|
return applyToPoint(this.computeSchematicGlobalTransform(), { x: 0, y: 0 });
|
|
317
311
|
}
|
|
312
|
+
get root() {
|
|
313
|
+
return this.parent?.root ?? null;
|
|
314
|
+
}
|
|
318
315
|
onAddToParent(parent) {
|
|
319
316
|
this.parent = parent;
|
|
320
|
-
this.project = parent.project;
|
|
321
317
|
}
|
|
322
318
|
/**
|
|
323
319
|
* Called whenever the props change
|
|
@@ -581,7 +577,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
581
577
|
return connectedTraces;
|
|
582
578
|
}
|
|
583
579
|
doInitialSourceRender() {
|
|
584
|
-
const { db } = this.
|
|
580
|
+
const { db } = this.root;
|
|
585
581
|
const { _parsedProps: props } = this;
|
|
586
582
|
const port_hints = this.getNameAndAliases();
|
|
587
583
|
const source_port = db.source_port.insert({
|
|
@@ -593,7 +589,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
593
589
|
this.source_port_id = source_port.source_port_id;
|
|
594
590
|
}
|
|
595
591
|
doInitialSourceParentAttachment() {
|
|
596
|
-
const { db } = this.
|
|
592
|
+
const { db } = this.root;
|
|
597
593
|
if (!this.parent?.source_component_id) {
|
|
598
594
|
throw new Error(
|
|
599
595
|
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`
|
|
@@ -610,7 +606,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
610
606
|
* to exist)
|
|
611
607
|
*/
|
|
612
608
|
doInitialPcbPortRender() {
|
|
613
|
-
const { db } = this.
|
|
609
|
+
const { db } = this.root;
|
|
614
610
|
const { matchedComponents } = this;
|
|
615
611
|
if (!this.parent?.pcb_component_id) {
|
|
616
612
|
throw new Error(
|
|
@@ -640,7 +636,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
640
636
|
}
|
|
641
637
|
}
|
|
642
638
|
doInitialSchematicPortRender() {
|
|
643
|
-
const { db } = this.
|
|
639
|
+
const { db } = this.root;
|
|
644
640
|
const { _parsedProps: props } = this;
|
|
645
641
|
if (!this.parent) return;
|
|
646
642
|
const center = this.getGlobalSchematicPosition();
|
|
@@ -871,7 +867,7 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
871
867
|
}
|
|
872
868
|
}
|
|
873
869
|
doInitialPcbPrimitiveRender() {
|
|
874
|
-
const { db } = this.
|
|
870
|
+
const { db } = this.root;
|
|
875
871
|
const { _parsedProps: props } = this;
|
|
876
872
|
if (!props.portHints) return;
|
|
877
873
|
const position = this.getGlobalPcbPosition();
|
|
@@ -919,7 +915,7 @@ var SilkscreenPath = class extends PrimitiveComponent {
|
|
|
919
915
|
};
|
|
920
916
|
}
|
|
921
917
|
doInitialPcbPrimitiveRender() {
|
|
922
|
-
const { db } = this.
|
|
918
|
+
const { db } = this.root;
|
|
923
919
|
const { _parsedProps: props } = this;
|
|
924
920
|
const layer = props.layer ?? "top";
|
|
925
921
|
if (layer !== "top" && layer !== "bottom") {
|
|
@@ -987,7 +983,7 @@ var PlatedHole = class extends PrimitiveComponent {
|
|
|
987
983
|
}
|
|
988
984
|
}
|
|
989
985
|
doInitialPcbPrimitiveRender() {
|
|
990
|
-
const { db } = this.
|
|
986
|
+
const { db } = this.root;
|
|
991
987
|
const { _parsedProps: props } = this;
|
|
992
988
|
if (!props.portHints) return;
|
|
993
989
|
const position = this.getGlobalPcbPosition();
|
|
@@ -1085,7 +1081,7 @@ var Net = class extends PrimitiveComponent {
|
|
|
1085
1081
|
return `net.${this.props.name}`;
|
|
1086
1082
|
}
|
|
1087
1083
|
doInitialSourceComponentRender() {
|
|
1088
|
-
const { db } = this.
|
|
1084
|
+
const { db } = this.root;
|
|
1089
1085
|
const { _parsedProps: props } = this;
|
|
1090
1086
|
const net = db.source_net.insert({
|
|
1091
1087
|
name: props.name,
|
|
@@ -1134,7 +1130,7 @@ var Net = class extends PrimitiveComponent {
|
|
|
1134
1130
|
* such that the nets are fully connected
|
|
1135
1131
|
*/
|
|
1136
1132
|
doInitialPcbRouteNetIslands() {
|
|
1137
|
-
const { db } = this.
|
|
1133
|
+
const { db } = this.root;
|
|
1138
1134
|
const { _parsedProps: props } = this;
|
|
1139
1135
|
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
1140
1136
|
(trace) => (trace._portsRoutedOnPcb?.length ?? 0) > 0
|
|
@@ -1240,6 +1236,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1240
1236
|
*/
|
|
1241
1237
|
initPorts() {
|
|
1242
1238
|
const { config } = this;
|
|
1239
|
+
const portsToCreate = [];
|
|
1243
1240
|
if (config.schematicSymbolName) {
|
|
1244
1241
|
const sym = symbols3[`${config.schematicSymbolName}_horz`];
|
|
1245
1242
|
if (!sym) return;
|
|
@@ -1247,27 +1244,31 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1247
1244
|
const port = getPortFromHints(symPort.labels);
|
|
1248
1245
|
if (port) {
|
|
1249
1246
|
port.schematicSymbolPortDef = symPort;
|
|
1250
|
-
|
|
1247
|
+
portsToCreate.push(port);
|
|
1251
1248
|
}
|
|
1252
1249
|
}
|
|
1250
|
+
this.addAll(portsToCreate);
|
|
1253
1251
|
return;
|
|
1254
1252
|
}
|
|
1255
1253
|
const portsFromFootprint = this.getPortsFromFootprint();
|
|
1256
|
-
|
|
1254
|
+
portsToCreate.push(...portsFromFootprint);
|
|
1257
1255
|
const pinLabels = this._parsedProps.pinLabels;
|
|
1258
1256
|
if (pinLabels) {
|
|
1259
1257
|
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
1260
1258
|
pinNumber = pinNumber.replace("pin", "");
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1259
|
+
const existingPort = portsToCreate.find(
|
|
1260
|
+
(p) => p._parsedProps.pinNumber === Number(pinNumber)
|
|
1261
|
+
);
|
|
1262
|
+
if (!existingPort) {
|
|
1263
1263
|
throw new Error(
|
|
1264
1264
|
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`
|
|
1265
1265
|
);
|
|
1266
1266
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1267
|
+
existingPort.externallyAddedAliases.push(label);
|
|
1268
|
+
existingPort.props.name = label;
|
|
1269
1269
|
}
|
|
1270
1270
|
}
|
|
1271
|
+
this.addAll(portsToCreate);
|
|
1271
1272
|
}
|
|
1272
1273
|
_addChildrenFromStringFootprint() {
|
|
1273
1274
|
const { footprint } = this.props;
|
|
@@ -1305,7 +1306,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1305
1306
|
doInitialSourceRender() {
|
|
1306
1307
|
const ftype = this.config.sourceFtype;
|
|
1307
1308
|
if (!ftype) return;
|
|
1308
|
-
const { db } = this.
|
|
1309
|
+
const { db } = this.root;
|
|
1309
1310
|
const { _parsedProps: props } = this;
|
|
1310
1311
|
const source_component = db.source_component.insert({
|
|
1311
1312
|
ftype,
|
|
@@ -1322,7 +1323,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1322
1323
|
* You can override this method to do more complicated things.
|
|
1323
1324
|
*/
|
|
1324
1325
|
doInitialSchematicComponentRender() {
|
|
1325
|
-
const { db } = this.
|
|
1326
|
+
const { db } = this.root;
|
|
1326
1327
|
const { schematicSymbolName } = this.config;
|
|
1327
1328
|
if (!schematicSymbolName) return;
|
|
1328
1329
|
const symbol_name = `${this.config.schematicSymbolName}_horz`;
|
|
@@ -1341,7 +1342,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1341
1342
|
this.schematic_component_id = schematic_component2.schematic_component_id;
|
|
1342
1343
|
}
|
|
1343
1344
|
doInitialPcbComponentRender() {
|
|
1344
|
-
const { db } = this.
|
|
1345
|
+
const { db } = this.root;
|
|
1345
1346
|
const { _parsedProps: props } = this;
|
|
1346
1347
|
const pcb_component = db.pcb_component.insert({
|
|
1347
1348
|
center: this.getGlobalPcbPosition(),
|
|
@@ -1360,7 +1361,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1360
1361
|
*/
|
|
1361
1362
|
doInitialPcbComponentSizeCalculation() {
|
|
1362
1363
|
if (!this.pcb_component_id) return;
|
|
1363
|
-
const { db } = this.
|
|
1364
|
+
const { db } = this.root;
|
|
1364
1365
|
const { _parsedProps: props } = this;
|
|
1365
1366
|
let minX = Infinity;
|
|
1366
1367
|
let minY = Infinity;
|
|
@@ -1389,6 +1390,9 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1389
1390
|
component: createInstanceFromReactElement(element)
|
|
1390
1391
|
};
|
|
1391
1392
|
}
|
|
1393
|
+
doInitialInitializePortsFromChildren() {
|
|
1394
|
+
this.initPorts();
|
|
1395
|
+
}
|
|
1392
1396
|
doInitialReactSubtreesRender() {
|
|
1393
1397
|
if (isReactElement2(this.props.footprint)) {
|
|
1394
1398
|
if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
|
|
@@ -1398,6 +1402,16 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1398
1402
|
this.add(subtree.component);
|
|
1399
1403
|
}
|
|
1400
1404
|
}
|
|
1405
|
+
_hasExistingPortExactly(port1) {
|
|
1406
|
+
const existingPorts = this.children.filter(
|
|
1407
|
+
(c) => c.componentName === "Port"
|
|
1408
|
+
);
|
|
1409
|
+
return existingPorts.some((port2) => {
|
|
1410
|
+
const aliases1 = port1.getNameAndAliases();
|
|
1411
|
+
const aliases2 = port2.getNameAndAliases();
|
|
1412
|
+
return aliases1.length === aliases2.length && aliases1.every((alias) => aliases2.includes(alias));
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1401
1415
|
add(componentOrElm) {
|
|
1402
1416
|
let component;
|
|
1403
1417
|
if (isReactElement2(componentOrElm)) {
|
|
@@ -1407,6 +1421,20 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1407
1421
|
} else {
|
|
1408
1422
|
component = componentOrElm;
|
|
1409
1423
|
}
|
|
1424
|
+
if (component.componentName === "Port") {
|
|
1425
|
+
if (this._hasExistingPortExactly(component)) return;
|
|
1426
|
+
const existingPorts = this.children.filter(
|
|
1427
|
+
(c) => c.componentName === "Port"
|
|
1428
|
+
);
|
|
1429
|
+
const conflictingPort = existingPorts.find(
|
|
1430
|
+
(p) => p.isMatchingAnyOf(component.getNameAndAliases())
|
|
1431
|
+
);
|
|
1432
|
+
if (conflictingPort) {
|
|
1433
|
+
throw new Error(
|
|
1434
|
+
`Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1410
1438
|
super.add(component);
|
|
1411
1439
|
}
|
|
1412
1440
|
getPortsFromFootprint() {
|
|
@@ -1434,6 +1462,11 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1434
1462
|
if (!newPort) continue;
|
|
1435
1463
|
newPorts2.push(newPort);
|
|
1436
1464
|
}
|
|
1465
|
+
if (newPorts2.length === 0) {
|
|
1466
|
+
throw new Error(
|
|
1467
|
+
`No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1437
1470
|
return newPorts2;
|
|
1438
1471
|
}
|
|
1439
1472
|
const newPorts = [];
|
|
@@ -1526,7 +1559,7 @@ var Board = class extends Group {
|
|
|
1526
1559
|
};
|
|
1527
1560
|
}
|
|
1528
1561
|
doInitialPcbComponentRender() {
|
|
1529
|
-
const { db } = this.
|
|
1562
|
+
const { db } = this.root;
|
|
1530
1563
|
const { _parsedProps: props } = this;
|
|
1531
1564
|
if (!props.width || !props.height) {
|
|
1532
1565
|
throw new Error("Board width and height or an outline are required");
|
|
@@ -1539,7 +1572,7 @@ var Board = class extends Group {
|
|
|
1539
1572
|
this.pcb_board_id = pcb_board.pcb_board_id;
|
|
1540
1573
|
}
|
|
1541
1574
|
removePcbComponentRender() {
|
|
1542
|
-
const { db } = this.
|
|
1575
|
+
const { db } = this.root;
|
|
1543
1576
|
if (!this.pcb_board_id) return;
|
|
1544
1577
|
db.pcb_board.delete(this.pcb_board_id);
|
|
1545
1578
|
this.pcb_board_id = null;
|
|
@@ -1752,7 +1785,7 @@ var Trace = class extends PrimitiveComponent {
|
|
|
1752
1785
|
);
|
|
1753
1786
|
}
|
|
1754
1787
|
_findConnectedPorts() {
|
|
1755
|
-
const { db } = this.
|
|
1788
|
+
const { db } = this.root;
|
|
1756
1789
|
const { _parsedProps: props, parent } = this;
|
|
1757
1790
|
if (!parent) throw new Error("Trace has no parent");
|
|
1758
1791
|
const portSelectors = this.getTracePortPathSelectors();
|
|
@@ -1836,7 +1869,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1836
1869
|
createNetsFromProps(this, this.getTracePathNetSelectors());
|
|
1837
1870
|
}
|
|
1838
1871
|
doInitialSourceTraceRender() {
|
|
1839
|
-
const { db } = this.
|
|
1872
|
+
const { db } = this.root;
|
|
1840
1873
|
const { _parsedProps: props, parent } = this;
|
|
1841
1874
|
if (!parent) {
|
|
1842
1875
|
this.renderError("Trace has no parent");
|
|
@@ -1852,7 +1885,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1852
1885
|
this.source_trace_id = trace.source_trace_id;
|
|
1853
1886
|
}
|
|
1854
1887
|
doInitialPcbTraceRender() {
|
|
1855
|
-
const { db } = this.
|
|
1888
|
+
const { db } = this.root;
|
|
1856
1889
|
const { _parsedProps: props, parent } = this;
|
|
1857
1890
|
if (!parent) throw new Error("Trace has no parent");
|
|
1858
1891
|
const { allPortsFound, ports } = this._findConnectedPorts();
|
|
@@ -1933,7 +1966,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1933
1966
|
`Could not find a common layer (using hints) for trace ${this.getString()}`
|
|
1934
1967
|
);
|
|
1935
1968
|
}
|
|
1936
|
-
const obstacles = getObstaclesFromSoup(this.
|
|
1969
|
+
const obstacles = getObstaclesFromSoup(this.root.db.toArray());
|
|
1937
1970
|
markObstaclesAsConnected(
|
|
1938
1971
|
obstacles,
|
|
1939
1972
|
orderedRouteObjectives,
|
|
@@ -1999,7 +2032,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1999
2032
|
this.pcb_trace_id = pcb_trace.pcb_trace_id;
|
|
2000
2033
|
}
|
|
2001
2034
|
doInitialSchematicTraceRender() {
|
|
2002
|
-
const { db } = this.
|
|
2035
|
+
const { db } = this.root;
|
|
2003
2036
|
const { _parsedProps: props, parent } = this;
|
|
2004
2037
|
if (!parent) throw new Error("Trace has no parent");
|
|
2005
2038
|
const { allPortsFound, portsWithSelectors: ports } = this._findConnectedPorts();
|
|
@@ -2093,7 +2126,7 @@ var Resistor = class extends NormalComponent {
|
|
|
2093
2126
|
}
|
|
2094
2127
|
}
|
|
2095
2128
|
doInitialSourceRender() {
|
|
2096
|
-
const { db } = this.
|
|
2129
|
+
const { db } = this.root;
|
|
2097
2130
|
const { _parsedProps: props } = this;
|
|
2098
2131
|
const source_component = db.source_component.insert({
|
|
2099
2132
|
ftype: "simple_resistor",
|
|
@@ -2171,7 +2204,7 @@ var Capacitor = class extends NormalComponent {
|
|
|
2171
2204
|
}
|
|
2172
2205
|
}
|
|
2173
2206
|
doInitialSourceRender() {
|
|
2174
|
-
const { db } = this.
|
|
2207
|
+
const { db } = this.root;
|
|
2175
2208
|
const { _parsedProps: props } = this;
|
|
2176
2209
|
const source_component = db.source_component.insert({
|
|
2177
2210
|
ftype: "simple_capacitor",
|
|
@@ -2191,7 +2224,7 @@ import { applyToPoint as applyToPoint4 } from "transformation-matrix";
|
|
|
2191
2224
|
var TraceHint = class extends PrimitiveComponent {
|
|
2192
2225
|
matchedPort = null;
|
|
2193
2226
|
doInitialPortMatching() {
|
|
2194
|
-
const { db } = this.
|
|
2227
|
+
const { db } = this.root;
|
|
2195
2228
|
const { _parsedProps: props, parent } = this;
|
|
2196
2229
|
if (!parent) return;
|
|
2197
2230
|
if (parent.componentName === "Trace") {
|
|
@@ -2522,7 +2555,7 @@ var Chip = class extends NormalComponent {
|
|
|
2522
2555
|
};
|
|
2523
2556
|
}
|
|
2524
2557
|
doInitialSourceRender() {
|
|
2525
|
-
const { db } = this.
|
|
2558
|
+
const { db } = this.root;
|
|
2526
2559
|
const { _parsedProps: props } = this;
|
|
2527
2560
|
const source_component = db.source_component.insert({
|
|
2528
2561
|
ftype: "simple_chip",
|
|
@@ -2533,7 +2566,7 @@ var Chip = class extends NormalComponent {
|
|
|
2533
2566
|
this.source_component_id = source_component.source_component_id;
|
|
2534
2567
|
}
|
|
2535
2568
|
doInitialSchematicComponentRender() {
|
|
2536
|
-
const { db } = this.
|
|
2569
|
+
const { db } = this.root;
|
|
2537
2570
|
const { _parsedProps: props } = this;
|
|
2538
2571
|
const ports = this.children.filter((child) => child instanceof Port);
|
|
2539
2572
|
const pinSpacing = props.schPinSpacing ?? 0.2;
|
|
@@ -2565,7 +2598,7 @@ var Chip = class extends NormalComponent {
|
|
|
2565
2598
|
this.schematic_component_id = schematic_component2.schematic_component_id;
|
|
2566
2599
|
}
|
|
2567
2600
|
doInitialPcbComponentRender() {
|
|
2568
|
-
const { db } = this.
|
|
2601
|
+
const { db } = this.root;
|
|
2569
2602
|
const { _parsedProps: props } = this;
|
|
2570
2603
|
const pcb_component = db.pcb_component.insert({
|
|
2571
2604
|
center: { x: props.pcbX ?? 0, y: props.pcbY ?? 0 },
|
|
@@ -2591,7 +2624,7 @@ var Jumper = class extends NormalComponent {
|
|
|
2591
2624
|
};
|
|
2592
2625
|
}
|
|
2593
2626
|
doInitialSourceRender() {
|
|
2594
|
-
const { db } = this.
|
|
2627
|
+
const { db } = this.root;
|
|
2595
2628
|
const { _parsedProps: props } = this;
|
|
2596
2629
|
const source_component = db.source_component.insert({
|
|
2597
2630
|
ftype: "simple_chip",
|
|
@@ -2603,7 +2636,7 @@ var Jumper = class extends NormalComponent {
|
|
|
2603
2636
|
this.source_component_id = source_component.source_component_id;
|
|
2604
2637
|
}
|
|
2605
2638
|
doInitialSchematicComponentRender() {
|
|
2606
|
-
const { db } = this.
|
|
2639
|
+
const { db } = this.root;
|
|
2607
2640
|
const { _parsedProps: props } = this;
|
|
2608
2641
|
const ports = this.children.filter((child) => child instanceof Port);
|
|
2609
2642
|
const pinSpacing = props.schPinSpacing ?? 0.2;
|
|
@@ -2638,7 +2671,7 @@ var Jumper = class extends NormalComponent {
|
|
|
2638
2671
|
this.schematic_component_id = schematic_component2.schematic_component_id;
|
|
2639
2672
|
}
|
|
2640
2673
|
doInitialPcbComponentRender() {
|
|
2641
|
-
const { db } = this.
|
|
2674
|
+
const { db } = this.root;
|
|
2642
2675
|
const { _parsedProps: props } = this;
|
|
2643
2676
|
const pcb_component = db.pcb_component.insert({
|
|
2644
2677
|
center: { x: props.pcbX ?? 0, y: props.pcbY ?? 0 },
|
|
@@ -2659,13 +2692,16 @@ import { su } from "@tscircuit/soup-util";
|
|
|
2659
2692
|
import { isValidElement as isValidElement2 } from "react";
|
|
2660
2693
|
import { identity as identity5 } from "transformation-matrix";
|
|
2661
2694
|
var Circuit = class {
|
|
2662
|
-
|
|
2695
|
+
firstChild = null;
|
|
2663
2696
|
children;
|
|
2664
2697
|
db;
|
|
2698
|
+
root = null;
|
|
2699
|
+
isRoot = true;
|
|
2665
2700
|
_hasRenderedAtleastOnce = false;
|
|
2666
2701
|
constructor() {
|
|
2667
2702
|
this.children = [];
|
|
2668
2703
|
this.db = su([]);
|
|
2704
|
+
this.root = this;
|
|
2669
2705
|
}
|
|
2670
2706
|
add(componentOrElm) {
|
|
2671
2707
|
let component;
|
|
@@ -2677,9 +2713,9 @@ var Circuit = class {
|
|
|
2677
2713
|
this.children.push(component);
|
|
2678
2714
|
}
|
|
2679
2715
|
_guessRootComponent() {
|
|
2680
|
-
if (this.
|
|
2716
|
+
if (this.firstChild) return;
|
|
2681
2717
|
if (this.children.length === 1) {
|
|
2682
|
-
this.
|
|
2718
|
+
this.firstChild = this.children[0];
|
|
2683
2719
|
return;
|
|
2684
2720
|
}
|
|
2685
2721
|
if (this.children.length === 0) {
|
|
@@ -2690,7 +2726,7 @@ var Circuit = class {
|
|
|
2690
2726
|
if (this.children.length > 0) {
|
|
2691
2727
|
const board = this.children.find((c) => c.componentName === "Board") ?? null;
|
|
2692
2728
|
if (board) {
|
|
2693
|
-
this.
|
|
2729
|
+
this.firstChild = board;
|
|
2694
2730
|
return;
|
|
2695
2731
|
}
|
|
2696
2732
|
}
|
|
@@ -2699,13 +2735,13 @@ var Circuit = class {
|
|
|
2699
2735
|
);
|
|
2700
2736
|
}
|
|
2701
2737
|
render() {
|
|
2702
|
-
if (!this.
|
|
2738
|
+
if (!this.firstChild) {
|
|
2703
2739
|
this._guessRootComponent();
|
|
2704
2740
|
}
|
|
2705
|
-
const {
|
|
2706
|
-
if (!
|
|
2707
|
-
|
|
2708
|
-
|
|
2741
|
+
const { firstChild, db } = this;
|
|
2742
|
+
if (!firstChild) throw new Error("Project has no root component");
|
|
2743
|
+
firstChild.parent = this;
|
|
2744
|
+
firstChild.runRenderCycle();
|
|
2709
2745
|
this._hasRenderedAtleastOnce = true;
|
|
2710
2746
|
}
|
|
2711
2747
|
getSoup() {
|
|
@@ -2729,17 +2765,17 @@ var Circuit = class {
|
|
|
2729
2765
|
const previewOpts = typeof previewNameOrOpts === "object" ? previewNameOrOpts : { previewName: previewNameOrOpts };
|
|
2730
2766
|
throw new Error("project.preview is not yet implemented");
|
|
2731
2767
|
}
|
|
2732
|
-
|
|
2768
|
+
computeSchematicGlobalTransform() {
|
|
2733
2769
|
return identity5();
|
|
2734
2770
|
}
|
|
2735
|
-
|
|
2771
|
+
computePcbGlobalTransform() {
|
|
2736
2772
|
return identity5();
|
|
2737
2773
|
}
|
|
2738
2774
|
selectAll(selector) {
|
|
2739
|
-
return this.
|
|
2775
|
+
return this.firstChild?.selectAll(selector) ?? [];
|
|
2740
2776
|
}
|
|
2741
2777
|
selectOne(selector, opts) {
|
|
2742
|
-
return this.
|
|
2778
|
+
return this.firstChild?.selectOne(selector, opts) ?? null;
|
|
2743
2779
|
}
|
|
2744
2780
|
};
|
|
2745
2781
|
var Project = Circuit;
|
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,23 +104,23 @@ 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
|
+
computePcbGlobalTransform(): 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
|
|
|
@@ -68,6 +68,7 @@ export class NormalComponent<
|
|
|
68
68
|
*/
|
|
69
69
|
initPorts() {
|
|
70
70
|
const { config } = this
|
|
71
|
+
const portsToCreate: Port[] = []
|
|
71
72
|
if (config.schematicSymbolName) {
|
|
72
73
|
const sym = symbols[
|
|
73
74
|
`${config.schematicSymbolName}_horz` as keyof typeof symbols
|
|
@@ -79,32 +80,36 @@ export class NormalComponent<
|
|
|
79
80
|
|
|
80
81
|
if (port) {
|
|
81
82
|
port.schematicSymbolPortDef = symPort
|
|
82
|
-
|
|
83
|
+
portsToCreate.push(port)
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
this.addAll(portsToCreate)
|
|
86
88
|
return
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
const portsFromFootprint = this.getPortsFromFootprint()
|
|
90
|
-
|
|
91
|
-
this.addAll(portsFromFootprint)
|
|
92
|
+
portsToCreate.push(...portsFromFootprint)
|
|
92
93
|
|
|
93
94
|
const pinLabels: Record<string, string> | undefined =
|
|
94
95
|
this._parsedProps.pinLabels
|
|
95
96
|
if (pinLabels) {
|
|
96
97
|
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
97
98
|
pinNumber = pinNumber.replace("pin", "")
|
|
98
|
-
const
|
|
99
|
-
|
|
99
|
+
const existingPort = portsToCreate.find(
|
|
100
|
+
(p) => p._parsedProps.pinNumber === Number(pinNumber),
|
|
101
|
+
)
|
|
102
|
+
if (!existingPort) {
|
|
100
103
|
throw new Error(
|
|
101
104
|
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`,
|
|
102
105
|
)
|
|
103
106
|
}
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
existingPort.externallyAddedAliases.push(label)
|
|
108
|
+
existingPort.props.name = label
|
|
106
109
|
}
|
|
107
110
|
}
|
|
111
|
+
|
|
112
|
+
this.addAll(portsToCreate)
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
_addChildrenFromStringFootprint() {
|
|
@@ -148,7 +153,7 @@ export class NormalComponent<
|
|
|
148
153
|
doInitialSourceRender() {
|
|
149
154
|
const ftype = this.config.sourceFtype
|
|
150
155
|
if (!ftype) return
|
|
151
|
-
const { db } = this.
|
|
156
|
+
const { db } = this.root!
|
|
152
157
|
const { _parsedProps: props } = this
|
|
153
158
|
const source_component = db.source_component.insert({
|
|
154
159
|
ftype,
|
|
@@ -166,7 +171,7 @@ export class NormalComponent<
|
|
|
166
171
|
* You can override this method to do more complicated things.
|
|
167
172
|
*/
|
|
168
173
|
doInitialSchematicComponentRender() {
|
|
169
|
-
const { db } = this.
|
|
174
|
+
const { db } = this.root!
|
|
170
175
|
const { schematicSymbolName } = this.config
|
|
171
176
|
if (!schematicSymbolName) return
|
|
172
177
|
// TODO switch between horizontal and vertical based on schRotation
|
|
@@ -191,7 +196,7 @@ export class NormalComponent<
|
|
|
191
196
|
}
|
|
192
197
|
|
|
193
198
|
doInitialPcbComponentRender() {
|
|
194
|
-
const { db } = this.
|
|
199
|
+
const { db } = this.root!
|
|
195
200
|
const { _parsedProps: props } = this
|
|
196
201
|
const pcb_component = db.pcb_component.insert({
|
|
197
202
|
center: this.getGlobalPcbPosition(),
|
|
@@ -211,7 +216,7 @@ export class NormalComponent<
|
|
|
211
216
|
*/
|
|
212
217
|
doInitialPcbComponentSizeCalculation(): void {
|
|
213
218
|
if (!this.pcb_component_id) return
|
|
214
|
-
const { db } = this.
|
|
219
|
+
const { db } = this.root!
|
|
215
220
|
const { _parsedProps: props } = this
|
|
216
221
|
|
|
217
222
|
let minX = Infinity
|
|
@@ -246,6 +251,10 @@ export class NormalComponent<
|
|
|
246
251
|
}
|
|
247
252
|
}
|
|
248
253
|
|
|
254
|
+
doInitialInitializePortsFromChildren(): void {
|
|
255
|
+
this.initPorts()
|
|
256
|
+
}
|
|
257
|
+
|
|
249
258
|
doInitialReactSubtreesRender(): void {
|
|
250
259
|
if (isReactElement(this.props.footprint)) {
|
|
251
260
|
if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
|
|
@@ -256,6 +265,20 @@ export class NormalComponent<
|
|
|
256
265
|
}
|
|
257
266
|
}
|
|
258
267
|
|
|
268
|
+
_hasExistingPortExactly(port1: Port): boolean {
|
|
269
|
+
const existingPorts = this.children.filter(
|
|
270
|
+
(c) => c.componentName === "Port",
|
|
271
|
+
) as Port[]
|
|
272
|
+
return existingPorts.some((port2) => {
|
|
273
|
+
const aliases1 = port1.getNameAndAliases()
|
|
274
|
+
const aliases2 = port2.getNameAndAliases()
|
|
275
|
+
return (
|
|
276
|
+
aliases1.length === aliases2.length &&
|
|
277
|
+
aliases1.every((alias) => aliases2.includes(alias))
|
|
278
|
+
)
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
|
|
259
282
|
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
260
283
|
let component: PrimitiveComponent
|
|
261
284
|
if (isReactElement(componentOrElm)) {
|
|
@@ -266,6 +289,23 @@ export class NormalComponent<
|
|
|
266
289
|
component = componentOrElm as PrimitiveComponent
|
|
267
290
|
}
|
|
268
291
|
|
|
292
|
+
if (component.componentName === "Port") {
|
|
293
|
+
if (this._hasExistingPortExactly(component as Port)) return
|
|
294
|
+
// Check if this port is already contained in the children, skip if it's
|
|
295
|
+
// already defined
|
|
296
|
+
const existingPorts = this.children.filter(
|
|
297
|
+
(c) => c.componentName === "Port",
|
|
298
|
+
) as Port[]
|
|
299
|
+
const conflictingPort = existingPorts.find((p) =>
|
|
300
|
+
p.isMatchingAnyOf(component.getNameAndAliases()),
|
|
301
|
+
)
|
|
302
|
+
if (conflictingPort) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`,
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
269
309
|
super.add(component)
|
|
270
310
|
}
|
|
271
311
|
|
|
@@ -304,6 +344,12 @@ export class NormalComponent<
|
|
|
304
344
|
newPorts.push(newPort)
|
|
305
345
|
}
|
|
306
346
|
|
|
347
|
+
if (newPorts.length === 0) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`,
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
|
|
307
353
|
return newPorts
|
|
308
354
|
}
|
|
309
355
|
|
|
@@ -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,8 +59,7 @@ 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
|
|
|
@@ -86,13 +84,6 @@ export abstract class PrimitiveComponent<
|
|
|
86
84
|
}
|
|
87
85
|
}
|
|
88
86
|
|
|
89
|
-
setProject(project: Circuit) {
|
|
90
|
-
this.project = project
|
|
91
|
-
for (const c of this.children) {
|
|
92
|
-
c.setProject(project)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
87
|
setProps(props: Partial<z.input<ZodProps>>) {
|
|
97
88
|
const newProps = this.config.zodProps.parse({
|
|
98
89
|
...this.props,
|
|
@@ -227,9 +218,12 @@ export abstract class PrimitiveComponent<
|
|
|
227
218
|
return applyToPoint(this.computeSchematicGlobalTransform(), { x: 0, y: 0 })
|
|
228
219
|
}
|
|
229
220
|
|
|
221
|
+
get root(): Circuit | null {
|
|
222
|
+
return this.parent?.root ?? null
|
|
223
|
+
}
|
|
224
|
+
|
|
230
225
|
onAddToParent(parent: PrimitiveComponent) {
|
|
231
226
|
this.parent = parent
|
|
232
|
-
this.project = parent.project
|
|
233
227
|
}
|
|
234
228
|
|
|
235
229
|
/**
|
|
@@ -3,6 +3,7 @@ import { Component, createElement, type ReactElement } from "react"
|
|
|
3
3
|
|
|
4
4
|
export const orderedRenderPhases = [
|
|
5
5
|
"ReactSubtreesRender", // probably going to be removed b/c subtrees should render instantly
|
|
6
|
+
"InitializePortsFromChildren",
|
|
6
7
|
"CreateNetsFromProps",
|
|
7
8
|
"CreateTracesFromProps",
|
|
8
9
|
"SourceRender",
|
|
@@ -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,7 +36,7 @@ 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
|
|
@@ -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",
|
|
@@ -18,7 +18,7 @@ export class Net extends PrimitiveComponent<typeof netProps> {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
doInitialSourceComponentRender(): void {
|
|
21
|
-
const { db } = this.
|
|
21
|
+
const { db } = this.root!
|
|
22
22
|
const { _parsedProps: props } = this
|
|
23
23
|
|
|
24
24
|
const net = db.source_net.insert({
|
|
@@ -77,7 +77,7 @@ export class Net extends PrimitiveComponent<typeof netProps> {
|
|
|
77
77
|
* such that the nets are fully connected
|
|
78
78
|
*/
|
|
79
79
|
doInitialPcbRouteNetIslands(): void {
|
|
80
|
-
const { db } = this.
|
|
80
|
+
const { db } = this.root!
|
|
81
81
|
const { _parsedProps: props } = this
|
|
82
82
|
|
|
83
83
|
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
@@ -46,7 +46,7 @@ export class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
doInitialPcbPrimitiveRender(): void {
|
|
49
|
-
const { db } = this.
|
|
49
|
+
const { db } = this.root!
|
|
50
50
|
const { _parsedProps: props } = this
|
|
51
51
|
if (!props.portHints) return
|
|
52
52
|
const position = this.getGlobalPcbPosition()
|
|
@@ -116,7 +116,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
doInitialSourceRender(): void {
|
|
119
|
-
const { db } = this.
|
|
119
|
+
const { db } = this.root!
|
|
120
120
|
const { _parsedProps: props } = this
|
|
121
121
|
|
|
122
122
|
const port_hints = this.getNameAndAliases()
|
|
@@ -132,7 +132,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
doInitialSourceParentAttachment(): void {
|
|
135
|
-
const { db } = this.
|
|
135
|
+
const { db } = this.root!
|
|
136
136
|
if (!this.parent?.source_component_id) {
|
|
137
137
|
throw new Error(
|
|
138
138
|
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`,
|
|
@@ -152,7 +152,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
152
152
|
* to exist)
|
|
153
153
|
*/
|
|
154
154
|
doInitialPcbPortRender(): void {
|
|
155
|
-
const { db } = this.
|
|
155
|
+
const { db } = this.root!
|
|
156
156
|
const { matchedComponents } = this
|
|
157
157
|
|
|
158
158
|
if (!this.parent?.pcb_component_id) {
|
|
@@ -191,7 +191,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
doInitialSchematicPortRender(): void {
|
|
194
|
-
const { db } = this.
|
|
194
|
+
const { db } = this.root!
|
|
195
195
|
const { _parsedProps: props } = this
|
|
196
196
|
|
|
197
197
|
if (!this.parent) return
|
|
@@ -50,7 +50,7 @@ export class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
doInitialPcbPrimitiveRender(): void {
|
|
53
|
-
const { db } = this.
|
|
53
|
+
const { db } = this.root!
|
|
54
54
|
const { _parsedProps: props } = this
|
|
55
55
|
if (!props.portHints) return
|
|
56
56
|
const position = this.getGlobalPcbPosition()
|
|
@@ -104,7 +104,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
104
104
|
ports?: undefined
|
|
105
105
|
portsWithSelectors?: undefined
|
|
106
106
|
} {
|
|
107
|
-
const { db } = this.
|
|
107
|
+
const { db } = this.root!
|
|
108
108
|
const { _parsedProps: props, parent } = this
|
|
109
109
|
|
|
110
110
|
if (!parent) throw new Error("Trace has no parent")
|
|
@@ -215,7 +215,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
doInitialSourceTraceRender(): void {
|
|
218
|
-
const { db } = this.
|
|
218
|
+
const { db } = this.root!
|
|
219
219
|
const { _parsedProps: props, parent } = this
|
|
220
220
|
|
|
221
221
|
if (!parent) {
|
|
@@ -238,7 +238,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
doInitialPcbTraceRender(): void {
|
|
241
|
-
const { db } = this.
|
|
241
|
+
const { db } = this.root!
|
|
242
242
|
const { _parsedProps: props, parent } = this
|
|
243
243
|
|
|
244
244
|
if (!parent) throw new Error("Trace has no parent")
|
|
@@ -365,7 +365,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
365
365
|
|
|
366
366
|
// Cache the PCB obstacles, they'll be needed for each segment between
|
|
367
367
|
// ports/hints
|
|
368
|
-
const obstacles = getObstaclesFromSoup(this.
|
|
368
|
+
const obstacles = getObstaclesFromSoup(this.root!.db.toArray())
|
|
369
369
|
markObstaclesAsConnected(
|
|
370
370
|
obstacles,
|
|
371
371
|
orderedRouteObjectives,
|
|
@@ -445,7 +445,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
doInitialSchematicTraceRender(): void {
|
|
448
|
-
const { db } = this.
|
|
448
|
+
const { db } = this.root!
|
|
449
449
|
const { _parsedProps: props, parent } = this
|
|
450
450
|
|
|
451
451
|
if (!parent) throw new Error("Trace has no parent")
|
|
@@ -8,7 +8,7 @@ export class TraceHint extends PrimitiveComponent<typeof traceHintProps> {
|
|
|
8
8
|
matchedPort: Port | null = null
|
|
9
9
|
|
|
10
10
|
doInitialPortMatching(): void {
|
|
11
|
-
const { db } = this.
|
|
11
|
+
const { db } = this.root!
|
|
12
12
|
const { _parsedProps: props, parent } = this
|
|
13
13
|
|
|
14
14
|
if (!parent) return
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.30",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"files": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@tscircuit/infgrid-ijump-astar": "^0.0.6",
|
|
35
|
-
"@tscircuit/props": "^0.0.
|
|
35
|
+
"@tscircuit/props": "^0.0.52",
|
|
36
36
|
"@tscircuit/soup": "^0.0.58",
|
|
37
37
|
"@tscircuit/soup-util": "0.0.18",
|
|
38
38
|
"footprinter": "^0.0.44",
|