@tscircuit/core 0.0.79 → 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 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';
@@ -22,6 +23,7 @@ declare class Circuit {
22
23
  */
23
24
  _getBoard(): PrimitiveComponent & {
24
25
  boardThickness: number;
26
+ allLayers: LayerRef[];
25
27
  };
26
28
  _guessRootComponent(): void;
27
29
  render(): void;
@@ -164,6 +166,17 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
164
166
  width: number;
165
167
  height: number;
166
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
+ };
167
180
  /**
168
181
  * Set the position of this component from the layout solver. This method
169
182
  * should operate using CircuitJson associated with this component, like
@@ -714,6 +727,10 @@ declare class Board extends Group<typeof boardProps> {
714
727
  }>;
715
728
  };
716
729
  get boardThickness(): number;
730
+ /**
731
+ * Get all available layers for the board
732
+ */
733
+ get allLayers(): string[];
717
734
  doInitialPcbComponentRender(): void;
718
735
  removePcbComponentRender(): void;
719
736
  _computePcbGlobalTransformBeforeLayout(): Matrix;
@@ -808,7 +825,6 @@ declare class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
808
825
  height: number;
809
826
  };
810
827
  doInitialPortMatching(): void;
811
- getAvailablePcbLayers(): string[];
812
828
  doInitialPcbPrimitiveRender(): void;
813
829
  doInitialPcbPortAttachment(): void;
814
830
  _getPcbCircuitJsonBounds(): {
@@ -4082,7 +4098,12 @@ declare class Hole extends PrimitiveComponent<typeof holeProps> {
4082
4098
  }
4083
4099
 
4084
4100
  declare class SilkscreenText extends PrimitiveComponent<typeof silkscreenTextProps> {
4101
+ isPcbPrimitive: boolean;
4085
4102
  doInitialPcbPrimitiveRender(): void;
4103
+ getPcbSize(): {
4104
+ width: number;
4105
+ height: number;
4106
+ };
4086
4107
  }
4087
4108
 
4088
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
- if (this.props.layer) return [this.props.layer];
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 { decomposeTSR } from "transformation-matrix";
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 applyToPoint3 } from "transformation-matrix";
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 = applyToPoint3(transform, {
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
  }
@@ -2023,7 +2063,7 @@ import "zod";
2023
2063
 
2024
2064
  // lib/components/primitive-components/TraceHint.ts
2025
2065
  import "@tscircuit/props";
2026
- import { applyToPoint as applyToPoint4 } from "transformation-matrix";
2066
+ import { applyToPoint as applyToPoint5 } from "transformation-matrix";
2027
2067
  var TraceHint = class extends PrimitiveComponent {
2028
2068
  matchedPort = null;
2029
2069
  doInitialPortMatching() {
@@ -2057,7 +2097,7 @@ var TraceHint = class extends PrimitiveComponent {
2057
2097
  const globalTransform = this._computePcbGlobalTransformBeforeLayout();
2058
2098
  return offsets.map(
2059
2099
  (offset) => ({
2060
- ...applyToPoint4(globalTransform, offset),
2100
+ ...applyToPoint5(globalTransform, offset),
2061
2101
  via: offset.via,
2062
2102
  to_layer: offset.to_layer,
2063
2103
  trace_width: offset.trace_width
@@ -2115,6 +2155,12 @@ var Board = class extends Group {
2115
2155
  const { _parsedProps: props } = this;
2116
2156
  return 1.4;
2117
2157
  }
2158
+ /**
2159
+ * Get all available layers for the board
2160
+ */
2161
+ get allLayers() {
2162
+ return ["top", "bottom", "inner1", "inner2"];
2163
+ }
2118
2164
  doInitialPcbComponentRender() {
2119
2165
  const { db } = this.root;
2120
2166
  const { _parsedProps: props } = this;
@@ -3445,23 +3491,34 @@ var Hole = class extends PrimitiveComponent {
3445
3491
  // lib/components/primitive-components/SilkscreenText.ts
3446
3492
  import "@tscircuit/props";
3447
3493
  var SilkscreenText = class extends PrimitiveComponent {
3494
+ isPcbPrimitive = true;
3448
3495
  doInitialPcbPrimitiveRender() {
3449
3496
  const { db } = this.root;
3450
3497
  const { _parsedProps: props } = this;
3451
3498
  const container = this.getPrimitiveContainer();
3499
+ const position = this._getGlobalPcbPositionBeforeLayout();
3500
+ const { maybeFlipLayer } = this._getPcbPrimitiveFlippedHelpers();
3452
3501
  db.pcb_silkscreen_text.insert({
3453
3502
  anchor_alignment: props.anchorAlignment,
3454
3503
  anchor_position: {
3455
- x: props.pcbX ?? 0,
3456
- y: props.pcbY ?? 0
3504
+ x: position.x,
3505
+ y: position.y
3457
3506
  },
3458
3507
  font: props.font ?? "tscircuit2024",
3459
3508
  font_size: props.fontSize ?? 1,
3460
- layer: "top",
3509
+ layer: maybeFlipLayer(props.layer ?? "top"),
3461
3510
  text: props.text ?? "",
3462
3511
  pcb_component_id: container.pcb_component_id
3463
3512
  });
3464
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
+ }
3465
3522
  };
3466
3523
 
3467
3524
  // lib/components/primitive-components/FabricationNoteText.ts
@@ -3489,7 +3546,7 @@ var FabricationNoteText = class extends PrimitiveComponent {
3489
3546
 
3490
3547
  // lib/components/primitive-components/FabricationNotePath.ts
3491
3548
  import { fabricationNotePathProps } from "@tscircuit/props";
3492
- import { applyToPoint as applyToPoint5 } from "transformation-matrix";
3549
+ import { applyToPoint as applyToPoint6 } from "transformation-matrix";
3493
3550
  var FabricationNotePath = class extends PrimitiveComponent {
3494
3551
  fabrication_note_path_id = null;
3495
3552
  get config() {
@@ -3512,7 +3569,7 @@ var FabricationNotePath = class extends PrimitiveComponent {
3512
3569
  layer,
3513
3570
  color: props.color,
3514
3571
  route: props.route.map((p) => {
3515
- const transformedPosition = applyToPoint5(transform, {
3572
+ const transformedPosition = applyToPoint6(transform, {
3516
3573
  x: p.x,
3517
3574
  y: p.y
3518
3575
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.79",
4
+ "version": "0.0.80",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",