@tscircuit/core 0.0.78 → 0.0.80
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 +29 -1
- package/dist/index.js +102 -29
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as zod from 'zod';
|
|
2
2
|
import { ZodType, z } from 'zod';
|
|
3
3
|
import { AnySoupElement, PCBTraceError, PCBPlacementError, AnySourceComponent, RouteHintPoint } from '@tscircuit/soup';
|
|
4
|
+
import { LayerRef } from 'circuit-json';
|
|
4
5
|
import { SoupUtilObjects } from '@tscircuit/soup-util';
|
|
5
6
|
import { ReactElement } from 'react';
|
|
6
7
|
import { Matrix } from 'transformation-matrix';
|
|
@@ -17,6 +18,13 @@ declare class Circuit {
|
|
|
17
18
|
_hasRenderedAtleastOnce: boolean;
|
|
18
19
|
constructor();
|
|
19
20
|
add(componentOrElm: PrimitiveComponent | ReactElement): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get the main board for this Circuit.
|
|
23
|
+
*/
|
|
24
|
+
_getBoard(): PrimitiveComponent & {
|
|
25
|
+
boardThickness: number;
|
|
26
|
+
allLayers: LayerRef[];
|
|
27
|
+
};
|
|
20
28
|
_guessRootComponent(): void;
|
|
21
29
|
render(): void;
|
|
22
30
|
getSoup(): AnySoupElement[];
|
|
@@ -158,6 +166,17 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
158
166
|
width: number;
|
|
159
167
|
height: number;
|
|
160
168
|
};
|
|
169
|
+
/**
|
|
170
|
+
* Determine if this pcb primitive should be flipped because the primitive
|
|
171
|
+
* container is flipped
|
|
172
|
+
*
|
|
173
|
+
* TODO use footprint.originalLayer instead of assuming everything is defined
|
|
174
|
+
* relative to the top layer
|
|
175
|
+
*/
|
|
176
|
+
_getPcbPrimitiveFlippedHelpers(): {
|
|
177
|
+
isFlipped: boolean;
|
|
178
|
+
maybeFlipLayer: (layer: LayerRef) => LayerRef;
|
|
179
|
+
};
|
|
161
180
|
/**
|
|
162
181
|
* Set the position of this component from the layout solver. This method
|
|
163
182
|
* should operate using CircuitJson associated with this component, like
|
|
@@ -707,6 +726,11 @@ declare class Board extends Group<typeof boardProps> {
|
|
|
707
726
|
}[] | undefined;
|
|
708
727
|
}>;
|
|
709
728
|
};
|
|
729
|
+
get boardThickness(): number;
|
|
730
|
+
/**
|
|
731
|
+
* Get all available layers for the board
|
|
732
|
+
*/
|
|
733
|
+
get allLayers(): string[];
|
|
710
734
|
doInitialPcbComponentRender(): void;
|
|
711
735
|
removePcbComponentRender(): void;
|
|
712
736
|
_computePcbGlobalTransformBeforeLayout(): Matrix;
|
|
@@ -801,7 +825,6 @@ declare class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
|
|
|
801
825
|
height: number;
|
|
802
826
|
};
|
|
803
827
|
doInitialPortMatching(): void;
|
|
804
|
-
getAvailablePcbLayers(): string[];
|
|
805
828
|
doInitialPcbPrimitiveRender(): void;
|
|
806
829
|
doInitialPcbPortAttachment(): void;
|
|
807
830
|
_getPcbCircuitJsonBounds(): {
|
|
@@ -4075,7 +4098,12 @@ declare class Hole extends PrimitiveComponent<typeof holeProps> {
|
|
|
4075
4098
|
}
|
|
4076
4099
|
|
|
4077
4100
|
declare class SilkscreenText extends PrimitiveComponent<typeof silkscreenTextProps> {
|
|
4101
|
+
isPcbPrimitive: boolean;
|
|
4078
4102
|
doInitialPcbPrimitiveRender(): void;
|
|
4103
|
+
getPcbSize(): {
|
|
4104
|
+
width: number;
|
|
4105
|
+
height: number;
|
|
4106
|
+
};
|
|
4079
4107
|
}
|
|
4080
4108
|
|
|
4081
4109
|
declare class Keepout extends PrimitiveComponent<typeof pcbKeepoutProps> {
|
package/dist/index.js
CHANGED
|
@@ -135,6 +135,7 @@ var Renderable = class {
|
|
|
135
135
|
import {
|
|
136
136
|
applyToPoint,
|
|
137
137
|
compose,
|
|
138
|
+
flipY,
|
|
138
139
|
identity,
|
|
139
140
|
rotate,
|
|
140
141
|
translate
|
|
@@ -270,6 +271,25 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
270
271
|
)
|
|
271
272
|
);
|
|
272
273
|
}
|
|
274
|
+
if (this.isPcbPrimitive) {
|
|
275
|
+
const primitiveContainer = this.getPrimitiveContainer();
|
|
276
|
+
if (primitiveContainer) {
|
|
277
|
+
const isFlipped = primitiveContainer._parsedProps.layer === "bottom";
|
|
278
|
+
const containerCenter = primitiveContainer._getGlobalPcbPositionBeforeLayout();
|
|
279
|
+
if (isFlipped) {
|
|
280
|
+
const flipOperation = compose(
|
|
281
|
+
translate(containerCenter.x, containerCenter.y),
|
|
282
|
+
flipY(),
|
|
283
|
+
translate(-containerCenter.x, -containerCenter.y)
|
|
284
|
+
);
|
|
285
|
+
return compose(
|
|
286
|
+
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity(),
|
|
287
|
+
flipY(),
|
|
288
|
+
this.computePcbPropsTransform()
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
273
293
|
return compose(
|
|
274
294
|
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity(),
|
|
275
295
|
this.computePcbPropsTransform()
|
|
@@ -291,6 +311,24 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
291
311
|
height: 0
|
|
292
312
|
};
|
|
293
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Determine if this pcb primitive should be flipped because the primitive
|
|
316
|
+
* container is flipped
|
|
317
|
+
*
|
|
318
|
+
* TODO use footprint.originalLayer instead of assuming everything is defined
|
|
319
|
+
* relative to the top layer
|
|
320
|
+
*/
|
|
321
|
+
_getPcbPrimitiveFlippedHelpers() {
|
|
322
|
+
const container = this.getPrimitiveContainer();
|
|
323
|
+
const isFlipped = !container ? false : container._parsedProps.layer === "bottom";
|
|
324
|
+
const maybeFlipLayer = (layer) => {
|
|
325
|
+
if (isFlipped) {
|
|
326
|
+
return layer === "top" ? "bottom" : "top";
|
|
327
|
+
}
|
|
328
|
+
return layer;
|
|
329
|
+
};
|
|
330
|
+
return { isFlipped, maybeFlipLayer };
|
|
331
|
+
}
|
|
294
332
|
/**
|
|
295
333
|
* Set the position of this component from the layout solver. This method
|
|
296
334
|
* should operate using CircuitJson associated with this component, like
|
|
@@ -474,9 +512,16 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
474
512
|
}
|
|
475
513
|
getAvailablePcbLayers() {
|
|
476
514
|
if (this.isPcbPrimitive) {
|
|
477
|
-
|
|
515
|
+
const { maybeFlipLayer } = this._getPcbPrimitiveFlippedHelpers();
|
|
516
|
+
if ("layer" in this._parsedProps) {
|
|
517
|
+
const layer = maybeFlipLayer(this._parsedProps.layer ?? "top");
|
|
518
|
+
return [layer];
|
|
519
|
+
}
|
|
520
|
+
if ("layers" in this._parsedProps) {
|
|
521
|
+
return this._parsedProps.layers;
|
|
522
|
+
}
|
|
478
523
|
if (this.componentName === "PlatedHole") {
|
|
479
|
-
return ["top", "bottom"];
|
|
524
|
+
return this.root?._getBoard()?.allLayers ?? ["top", "bottom"];
|
|
480
525
|
}
|
|
481
526
|
return [];
|
|
482
527
|
}
|
|
@@ -1097,7 +1142,9 @@ function getPortFromHints(hints) {
|
|
|
1097
1142
|
|
|
1098
1143
|
// lib/components/primitive-components/SmtPad.ts
|
|
1099
1144
|
import { smtPadProps } from "@tscircuit/props";
|
|
1100
|
-
import {
|
|
1145
|
+
import {
|
|
1146
|
+
decomposeTSR
|
|
1147
|
+
} from "transformation-matrix";
|
|
1101
1148
|
var SmtPad = class extends PrimitiveComponent {
|
|
1102
1149
|
pcb_smtpad_id = null;
|
|
1103
1150
|
matchedPort = null;
|
|
@@ -1134,18 +1181,18 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
1134
1181
|
}
|
|
1135
1182
|
}
|
|
1136
1183
|
}
|
|
1137
|
-
getAvailablePcbLayers() {
|
|
1138
|
-
return this.props.layer ? [this.props.layer] : [];
|
|
1139
|
-
}
|
|
1140
1184
|
doInitialPcbPrimitiveRender() {
|
|
1141
1185
|
const { db } = this.root;
|
|
1142
1186
|
const { _parsedProps: props } = this;
|
|
1143
1187
|
if (!props.portHints) return;
|
|
1188
|
+
const container = this.getPrimitiveContainer();
|
|
1144
1189
|
const position = this._getGlobalPcbPositionBeforeLayout();
|
|
1190
|
+
const containerCenter = container?._getGlobalPcbPositionBeforeLayout();
|
|
1145
1191
|
const decomposedMat = decomposeTSR(
|
|
1146
1192
|
this._computePcbGlobalTransformBeforeLayout()
|
|
1147
1193
|
);
|
|
1148
1194
|
const isRotated90 = Math.abs(decomposedMat.rotation.angle * (180 / Math.PI) - 90) < 0.01;
|
|
1195
|
+
const { maybeFlipLayer } = this._getPcbPrimitiveFlippedHelpers();
|
|
1149
1196
|
let pcb_smtpad = null;
|
|
1150
1197
|
const pcb_component_id = this.parent?.pcb_component_id ?? this.getPrimitiveContainer()?.pcb_component_id;
|
|
1151
1198
|
if (props.shape === "circle") {
|
|
@@ -1153,7 +1200,7 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
1153
1200
|
pcb_component_id,
|
|
1154
1201
|
pcb_port_id: this.matchedPort?.pcb_port_id,
|
|
1155
1202
|
// port likely isn't matched
|
|
1156
|
-
layer: props.layer ?? "top",
|
|
1203
|
+
layer: maybeFlipLayer(props.layer ?? "top"),
|
|
1157
1204
|
shape: "circle",
|
|
1158
1205
|
// @ts-ignore: no idea why this is triggering
|
|
1159
1206
|
radius: props.radius,
|
|
@@ -1166,7 +1213,7 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
1166
1213
|
pcb_component_id,
|
|
1167
1214
|
pcb_port_id: this.matchedPort?.pcb_port_id,
|
|
1168
1215
|
// port likely isn't matched
|
|
1169
|
-
layer: props.layer ?? "top",
|
|
1216
|
+
layer: maybeFlipLayer(props.layer ?? "top"),
|
|
1170
1217
|
shape: "rect",
|
|
1171
1218
|
...isRotated90 ? { width: props.height, height: props.width } : { width: props.width, height: props.height },
|
|
1172
1219
|
port_hints: props.portHints.map((ph) => ph.toString()),
|
|
@@ -1229,7 +1276,7 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
1229
1276
|
|
|
1230
1277
|
// lib/components/primitive-components/SilkscreenPath.ts
|
|
1231
1278
|
import { silkscreenPathProps } from "@tscircuit/props";
|
|
1232
|
-
import { applyToPoint as
|
|
1279
|
+
import { applyToPoint as applyToPoint4 } from "transformation-matrix";
|
|
1233
1280
|
var SilkscreenPath = class extends PrimitiveComponent {
|
|
1234
1281
|
pcb_silkscreen_path_id = null;
|
|
1235
1282
|
get config() {
|
|
@@ -1251,7 +1298,7 @@ var SilkscreenPath = class extends PrimitiveComponent {
|
|
|
1251
1298
|
pcb_component_id: this.parent?.pcb_component_id,
|
|
1252
1299
|
layer,
|
|
1253
1300
|
route: props.route.map((p) => {
|
|
1254
|
-
const transformedPosition =
|
|
1301
|
+
const transformedPosition = applyToPoint4(transform, {
|
|
1255
1302
|
x: p.x,
|
|
1256
1303
|
y: p.y
|
|
1257
1304
|
});
|
|
@@ -1736,13 +1783,6 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1736
1783
|
if (!footprint) return;
|
|
1737
1784
|
if (typeof footprint === "string") {
|
|
1738
1785
|
const fpSoup = fp.string(footprint).soup();
|
|
1739
|
-
if (this.props.layer) {
|
|
1740
|
-
for (const elm of fpSoup) {
|
|
1741
|
-
if ("layer" in elm) {
|
|
1742
|
-
elm.layer = this.props.layer;
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
1786
|
const fpComponents = createComponentsFromSoup(fpSoup);
|
|
1747
1787
|
this.addAll(fpComponents);
|
|
1748
1788
|
}
|
|
@@ -1984,6 +2024,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1984
2024
|
}
|
|
1985
2025
|
doInitialCadModelRender() {
|
|
1986
2026
|
const { db } = this.root;
|
|
2027
|
+
const { boardThickness = 0 } = this.root?._getBoard() ?? {};
|
|
1987
2028
|
const { _parsedProps: props } = this;
|
|
1988
2029
|
if (props.cadModel) {
|
|
1989
2030
|
const bounds = this._getPcbCircuitJsonBounds();
|
|
@@ -1993,14 +2034,17 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1993
2034
|
}
|
|
1994
2035
|
const cad_model = db.cad_component.insert({
|
|
1995
2036
|
// TODO z maybe depends on layer
|
|
1996
|
-
position: {
|
|
2037
|
+
position: {
|
|
2038
|
+
x: bounds.center.x,
|
|
2039
|
+
y: bounds.center.y,
|
|
2040
|
+
z: this.props.layer === "bottom" ? -boardThickness / 2 : boardThickness / 2
|
|
2041
|
+
},
|
|
1997
2042
|
pcb_component_id: this.pcb_component_id,
|
|
1998
2043
|
source_component_id: this.source_component_id,
|
|
1999
2044
|
model_stl_url: "stlUrl" in cadModel ? cadModel.stlUrl : void 0,
|
|
2000
2045
|
model_obj_url: "objUrl" in cadModel ? cadModel.objUrl : void 0,
|
|
2001
|
-
model_jscad: "jscad" in cadModel ? cadModel.jscad : void 0
|
|
2002
|
-
|
|
2003
|
-
// footprinter_string:
|
|
2046
|
+
model_jscad: "jscad" in cadModel ? cadModel.jscad : void 0,
|
|
2047
|
+
footprinter_string: typeof this.props.footprint === "string" && !cadModel ? this.props.footprint : void 0
|
|
2004
2048
|
});
|
|
2005
2049
|
}
|
|
2006
2050
|
}
|
|
@@ -2019,7 +2063,7 @@ import "zod";
|
|
|
2019
2063
|
|
|
2020
2064
|
// lib/components/primitive-components/TraceHint.ts
|
|
2021
2065
|
import "@tscircuit/props";
|
|
2022
|
-
import { applyToPoint as
|
|
2066
|
+
import { applyToPoint as applyToPoint5 } from "transformation-matrix";
|
|
2023
2067
|
var TraceHint = class extends PrimitiveComponent {
|
|
2024
2068
|
matchedPort = null;
|
|
2025
2069
|
doInitialPortMatching() {
|
|
@@ -2053,7 +2097,7 @@ var TraceHint = class extends PrimitiveComponent {
|
|
|
2053
2097
|
const globalTransform = this._computePcbGlobalTransformBeforeLayout();
|
|
2054
2098
|
return offsets.map(
|
|
2055
2099
|
(offset) => ({
|
|
2056
|
-
...
|
|
2100
|
+
...applyToPoint5(globalTransform, offset),
|
|
2057
2101
|
via: offset.via,
|
|
2058
2102
|
to_layer: offset.to_layer,
|
|
2059
2103
|
trace_width: offset.trace_width
|
|
@@ -2107,6 +2151,16 @@ var Board = class extends Group {
|
|
|
2107
2151
|
zodProps: boardProps
|
|
2108
2152
|
};
|
|
2109
2153
|
}
|
|
2154
|
+
get boardThickness() {
|
|
2155
|
+
const { _parsedProps: props } = this;
|
|
2156
|
+
return 1.4;
|
|
2157
|
+
}
|
|
2158
|
+
/**
|
|
2159
|
+
* Get all available layers for the board
|
|
2160
|
+
*/
|
|
2161
|
+
get allLayers() {
|
|
2162
|
+
return ["top", "bottom", "inner1", "inner2"];
|
|
2163
|
+
}
|
|
2110
2164
|
doInitialPcbComponentRender() {
|
|
2111
2165
|
const { db } = this.root;
|
|
2112
2166
|
const { _parsedProps: props } = this;
|
|
@@ -3437,23 +3491,34 @@ var Hole = class extends PrimitiveComponent {
|
|
|
3437
3491
|
// lib/components/primitive-components/SilkscreenText.ts
|
|
3438
3492
|
import "@tscircuit/props";
|
|
3439
3493
|
var SilkscreenText = class extends PrimitiveComponent {
|
|
3494
|
+
isPcbPrimitive = true;
|
|
3440
3495
|
doInitialPcbPrimitiveRender() {
|
|
3441
3496
|
const { db } = this.root;
|
|
3442
3497
|
const { _parsedProps: props } = this;
|
|
3443
3498
|
const container = this.getPrimitiveContainer();
|
|
3499
|
+
const position = this._getGlobalPcbPositionBeforeLayout();
|
|
3500
|
+
const { maybeFlipLayer } = this._getPcbPrimitiveFlippedHelpers();
|
|
3444
3501
|
db.pcb_silkscreen_text.insert({
|
|
3445
3502
|
anchor_alignment: props.anchorAlignment,
|
|
3446
3503
|
anchor_position: {
|
|
3447
|
-
x:
|
|
3448
|
-
y:
|
|
3504
|
+
x: position.x,
|
|
3505
|
+
y: position.y
|
|
3449
3506
|
},
|
|
3450
3507
|
font: props.font ?? "tscircuit2024",
|
|
3451
3508
|
font_size: props.fontSize ?? 1,
|
|
3452
|
-
layer: "top",
|
|
3509
|
+
layer: maybeFlipLayer(props.layer ?? "top"),
|
|
3453
3510
|
text: props.text ?? "",
|
|
3454
3511
|
pcb_component_id: container.pcb_component_id
|
|
3455
3512
|
});
|
|
3456
3513
|
}
|
|
3514
|
+
getPcbSize() {
|
|
3515
|
+
const { _parsedProps: props } = this;
|
|
3516
|
+
const fontSize = props.fontSize ?? 1;
|
|
3517
|
+
const text = props.text ?? "";
|
|
3518
|
+
const textWidth = text.length * fontSize;
|
|
3519
|
+
const textHeight = fontSize;
|
|
3520
|
+
return { width: textWidth * fontSize, height: textHeight * fontSize };
|
|
3521
|
+
}
|
|
3457
3522
|
};
|
|
3458
3523
|
|
|
3459
3524
|
// lib/components/primitive-components/FabricationNoteText.ts
|
|
@@ -3481,7 +3546,7 @@ var FabricationNoteText = class extends PrimitiveComponent {
|
|
|
3481
3546
|
|
|
3482
3547
|
// lib/components/primitive-components/FabricationNotePath.ts
|
|
3483
3548
|
import { fabricationNotePathProps } from "@tscircuit/props";
|
|
3484
|
-
import { applyToPoint as
|
|
3549
|
+
import { applyToPoint as applyToPoint6 } from "transformation-matrix";
|
|
3485
3550
|
var FabricationNotePath = class extends PrimitiveComponent {
|
|
3486
3551
|
fabrication_note_path_id = null;
|
|
3487
3552
|
get config() {
|
|
@@ -3504,7 +3569,7 @@ var FabricationNotePath = class extends PrimitiveComponent {
|
|
|
3504
3569
|
layer,
|
|
3505
3570
|
color: props.color,
|
|
3506
3571
|
route: props.route.map((p) => {
|
|
3507
|
-
const transformedPosition =
|
|
3572
|
+
const transformedPosition = applyToPoint6(transform, {
|
|
3508
3573
|
x: p.x,
|
|
3509
3574
|
y: p.y
|
|
3510
3575
|
});
|
|
@@ -3520,7 +3585,7 @@ var FabricationNotePath = class extends PrimitiveComponent {
|
|
|
3520
3585
|
}
|
|
3521
3586
|
};
|
|
3522
3587
|
|
|
3523
|
-
// lib/
|
|
3588
|
+
// lib/Circuit.ts
|
|
3524
3589
|
import { su } from "@tscircuit/soup-util";
|
|
3525
3590
|
import { isValidElement as isValidElement2 } from "react";
|
|
3526
3591
|
import { identity as identity5 } from "transformation-matrix";
|
|
@@ -3545,6 +3610,14 @@ var Circuit = class {
|
|
|
3545
3610
|
}
|
|
3546
3611
|
this.children.push(component);
|
|
3547
3612
|
}
|
|
3613
|
+
/**
|
|
3614
|
+
* Get the main board for this Circuit.
|
|
3615
|
+
*/
|
|
3616
|
+
_getBoard() {
|
|
3617
|
+
return this.children.find(
|
|
3618
|
+
(c) => c.componentName === "Board"
|
|
3619
|
+
);
|
|
3620
|
+
}
|
|
3548
3621
|
_guessRootComponent() {
|
|
3549
3622
|
if (this.firstChild) return;
|
|
3550
3623
|
if (this.children.length === 1) {
|