@tscircuit/core 0.0.172 → 0.0.174

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
@@ -711,6 +711,7 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
711
711
  _impliedFootprint?: string | undefined;
712
712
  isPrimitiveContainer: boolean;
713
713
  _asyncSupplierPartNumbers?: SupplierPartNumbers;
714
+ pcb_missing_footprint_error_id?: string;
714
715
  constructor(props: z.input<ZodProps>);
715
716
  /**
716
717
  * Override this method for better control over the auto-discovery of ports.
@@ -6126,6 +6127,7 @@ declare class PinHeader extends NormalComponent<typeof pinHeaderProps> {
6126
6127
  holeDiameter: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
6127
6128
  platedDiameter: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
6128
6129
  pinLabels: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
6130
+ facingDirection: zod.ZodOptional<zod.ZodEnum<["left", "right"]>>;
6129
6131
  }>, "strip", zod.ZodTypeAny, {
6130
6132
  name: string;
6131
6133
  pinCount: number;
@@ -6201,6 +6203,7 @@ declare class PinHeader extends NormalComponent<typeof pinHeaderProps> {
6201
6203
  showSilkscreenPinLabels?: boolean | undefined;
6202
6204
  doubleRow?: boolean | undefined;
6203
6205
  platedDiameter?: number | undefined;
6206
+ facingDirection?: "left" | "right" | undefined;
6204
6207
  }, {
6205
6208
  name: string;
6206
6209
  pinCount: number;
@@ -6278,6 +6281,7 @@ declare class PinHeader extends NormalComponent<typeof pinHeaderProps> {
6278
6281
  showSilkscreenPinLabels?: boolean | undefined;
6279
6282
  doubleRow?: boolean | undefined;
6280
6283
  platedDiameter?: string | number | undefined;
6284
+ facingDirection?: "left" | "right" | undefined;
6281
6285
  }>;
6282
6286
  shouldRenderAsSchematicBox: boolean;
6283
6287
  };
package/dist/index.js CHANGED
@@ -1638,9 +1638,9 @@ function getRelativeDirection(pointA, pointB) {
1638
1638
  const dx = pointB.x - pointA.x;
1639
1639
  const dy = pointB.y - pointA.y;
1640
1640
  if (Math.abs(dx) > Math.abs(dy)) {
1641
- return dx > 0 ? "right" : "left";
1641
+ return dx >= 0 ? "right" : "left";
1642
1642
  }
1643
- return dy > 0 ? "down" : "up";
1643
+ return dy >= 0 ? "up" : "down";
1644
1644
  }
1645
1645
 
1646
1646
  // lib/components/primitive-components/Port.ts
@@ -1860,15 +1860,16 @@ var Port = class extends PrimitiveComponent {
1860
1860
  label: "obstacle"
1861
1861
  });
1862
1862
  }
1863
- if (!localPortInfo?.side)
1863
+ if (!localPortInfo?.side) {
1864
1864
  this.facingDirection = getRelativeDirection(containerCenter, portCenter);
1865
- else
1865
+ } else {
1866
1866
  this.facingDirection = {
1867
1867
  left: "left",
1868
1868
  right: "right",
1869
1869
  top: "up",
1870
1870
  bottom: "down"
1871
1871
  }[localPortInfo.side];
1872
+ }
1872
1873
  const sourcePort = db.source_port.get(this.source_port_id);
1873
1874
  let bestDisplayPinLabel = void 0;
1874
1875
  for (const portHint of sourcePort?.port_hints ?? []) {
@@ -1947,6 +1948,31 @@ var getSizeOfSidesFromPortArrangement = (pa) => {
1947
1948
  return { leftSize, rightSize, topSize, bottomSize };
1948
1949
  };
1949
1950
 
1951
+ // lib/utils/schematic/parsePinNumberFromLabelsOrThrow.ts
1952
+ var parsePinNumberFromLabelsOrThrow = (pinNumberOrLabel, pinLabels) => {
1953
+ if (typeof pinNumberOrLabel === "number") {
1954
+ return pinNumberOrLabel;
1955
+ }
1956
+ if (pinNumberOrLabel.startsWith("pin")) {
1957
+ const pinNumber = Number(pinNumberOrLabel.slice(3));
1958
+ return pinNumber;
1959
+ }
1960
+ if (!pinLabels) {
1961
+ throw new Error(
1962
+ `No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`
1963
+ );
1964
+ }
1965
+ for (const pinNumberKey in pinLabels) {
1966
+ const aliases = Array.isArray(pinLabels[pinNumberKey]) ? pinLabels[pinNumberKey] : [pinLabels[pinNumberKey]];
1967
+ if (aliases.includes(pinNumberOrLabel)) {
1968
+ return Number(pinNumberKey.replace("pin", ""));
1969
+ }
1970
+ }
1971
+ throw new Error(
1972
+ `No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`
1973
+ );
1974
+ };
1975
+
1950
1976
  // lib/utils/schematic/getAllDimensionsForSchematicBox.ts
1951
1977
  function isExplicitPinMappingArrangement(arrangement) {
1952
1978
  return arrangement.leftSide !== void 0;
@@ -1985,11 +2011,40 @@ var getAllDimensionsForSchematicBox = (params) => {
1985
2011
  bottomSize: 0
1986
2012
  };
1987
2013
  }
2014
+ const getPinNumberUsingSideIndex = ({
2015
+ side,
2016
+ sideIndex,
2017
+ truePinIndex: truePinIndex2
2018
+ }) => {
2019
+ if (!params.schPortArrangement) return truePinIndex2 + 1;
2020
+ if (!isExplicitPinMappingArrangement(params.schPortArrangement))
2021
+ return truePinIndex2 + 1;
2022
+ const normalCcwDirection = {
2023
+ left: "top-to-bottom",
2024
+ bottom: "left-to-right",
2025
+ right: "bottom-to-top",
2026
+ top: "right-to-left"
2027
+ }[side];
2028
+ const directionAlongSide = params.schPortArrangement?.[`${side}Side`]?.direction ?? normalCcwDirection;
2029
+ const pinsDefinitionForSide = params.schPortArrangement?.[`${side}Side`]?.pins;
2030
+ let sideIndexWithDirectionCorrection = sideIndex;
2031
+ if (directionAlongSide !== normalCcwDirection) {
2032
+ sideIndexWithDirectionCorrection = pinsDefinitionForSide.length - sideIndex - 1;
2033
+ }
2034
+ return parsePinNumberFromLabelsOrThrow(
2035
+ pinsDefinitionForSide[sideIndexWithDirectionCorrection],
2036
+ params.pinLabels
2037
+ );
2038
+ };
1988
2039
  const orderedTruePorts = [];
1989
2040
  let currentDistanceFromEdge = 0;
1990
2041
  let truePinIndex = 0;
1991
2042
  for (let sideIndex = 0; sideIndex < sidePinCounts.leftSize; sideIndex++) {
1992
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement?.leftSide?.pins[sideIndex] : truePinIndex + 1;
2043
+ const pinNumber = getPinNumberUsingSideIndex({
2044
+ side: "left",
2045
+ sideIndex,
2046
+ truePinIndex
2047
+ });
1993
2048
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
1994
2049
  if (pinStyle?.topMargin) {
1995
2050
  currentDistanceFromEdge += pinStyle.topMargin;
@@ -2013,7 +2068,11 @@ var getAllDimensionsForSchematicBox = (params) => {
2013
2068
  }
2014
2069
  currentDistanceFromEdge = 0;
2015
2070
  for (let sideIndex = 0; sideIndex < sidePinCounts.bottomSize; sideIndex++) {
2016
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.bottomSide?.pins[sideIndex] : truePinIndex + 1;
2071
+ const pinNumber = getPinNumberUsingSideIndex({
2072
+ side: "bottom",
2073
+ sideIndex,
2074
+ truePinIndex
2075
+ });
2017
2076
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
2018
2077
  if (pinStyle?.leftMargin) {
2019
2078
  currentDistanceFromEdge += pinStyle.leftMargin;
@@ -2037,7 +2096,11 @@ var getAllDimensionsForSchematicBox = (params) => {
2037
2096
  }
2038
2097
  currentDistanceFromEdge = 0;
2039
2098
  for (let sideIndex = 0; sideIndex < sidePinCounts.rightSize; sideIndex++) {
2040
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.rightSide?.pins[sideIndex] : truePinIndex + 1;
2099
+ const pinNumber = getPinNumberUsingSideIndex({
2100
+ side: "right",
2101
+ sideIndex,
2102
+ truePinIndex
2103
+ });
2041
2104
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
2042
2105
  if (pinStyle?.bottomMargin) {
2043
2106
  currentDistanceFromEdge += pinStyle.bottomMargin;
@@ -2061,7 +2124,11 @@ var getAllDimensionsForSchematicBox = (params) => {
2061
2124
  }
2062
2125
  currentDistanceFromEdge = 0;
2063
2126
  for (let sideIndex = 0; sideIndex < sidePinCounts.topSize; sideIndex++) {
2064
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.topSide?.pins[sideIndex] : truePinIndex + 1;
2127
+ const pinNumber = getPinNumberUsingSideIndex({
2128
+ side: "top",
2129
+ sideIndex,
2130
+ truePinIndex
2131
+ });
2065
2132
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
2066
2133
  if (pinStyle?.rightMargin) {
2067
2134
  currentDistanceFromEdge += pinStyle.rightMargin;
@@ -2096,7 +2163,7 @@ var getAllDimensionsForSchematicBox = (params) => {
2096
2163
  // Estimated text width
2097
2164
  )
2098
2165
  ) : 0;
2099
- const LABEL_PADDING = 1.1;
2166
+ const LABEL_PADDING = labelWidth > 0 ? 1.1 : 0;
2100
2167
  schWidth = Math.max(schWidth, labelWidth + LABEL_PADDING);
2101
2168
  let schHeight = params.schHeight;
2102
2169
  if (!schHeight) {
@@ -2389,6 +2456,7 @@ var NormalComponent = class extends PrimitiveComponent {
2389
2456
  _impliedFootprint;
2390
2457
  isPrimitiveContainer = true;
2391
2458
  _asyncSupplierPartNumbers;
2459
+ pcb_missing_footprint_error_id;
2392
2460
  constructor(props) {
2393
2461
  super(props);
2394
2462
  this._addChildrenFromStringFootprint();
@@ -2412,11 +2480,15 @@ var NormalComponent = class extends PrimitiveComponent {
2412
2480
  const { config } = this;
2413
2481
  const portsToCreate = [];
2414
2482
  const schPortArrangement = this._parsedProps.schPortArrangement;
2415
- if (schPortArrangement) {
2483
+ if (schPortArrangement && !this._parsedProps.pinLabels) {
2416
2484
  for (const side in schPortArrangement) {
2417
2485
  const pins = schPortArrangement[side].pins;
2418
2486
  if (Array.isArray(pins)) {
2419
- for (const pinNumber of pins) {
2487
+ for (const pinNumberOrLabel of pins) {
2488
+ const pinNumber = parsePinNumberFromLabelsOrThrow(
2489
+ pinNumberOrLabel,
2490
+ this._parsedProps.pinLabels
2491
+ );
2420
2492
  portsToCreate.push(
2421
2493
  new Port(
2422
2494
  {
@@ -2510,6 +2582,47 @@ var NormalComponent = class extends PrimitiveComponent {
2510
2582
  }
2511
2583
  }
2512
2584
  }
2585
+ for (let pn = 1; pn <= this._getPinCount(); pn++) {
2586
+ if (!this._parsedProps.schPortArrangement) continue;
2587
+ if (portsToCreate.find((p) => p._parsedProps.pinNumber === pn)) continue;
2588
+ let explicitlyListedPinNumbersInSchPortArrangement = [
2589
+ ...this._parsedProps.schPortArrangement?.leftSide?.pins ?? [],
2590
+ ...this._parsedProps.schPortArrangement?.rightSide?.pins ?? [],
2591
+ ...this._parsedProps.schPortArrangement?.topSide?.pins ?? [],
2592
+ ...this._parsedProps.schPortArrangement?.bottomSide?.pins ?? []
2593
+ ].map(
2594
+ (pn2) => parsePinNumberFromLabelsOrThrow(pn2, this._parsedProps.pinLabels)
2595
+ );
2596
+ if ([
2597
+ "leftSize",
2598
+ "rightSize",
2599
+ "topSize",
2600
+ "bottomSize",
2601
+ "leftPinCount",
2602
+ "rightPinCount",
2603
+ "topPinCount",
2604
+ "bottomPinCount"
2605
+ ].some((key) => key in this._parsedProps.schPortArrangement)) {
2606
+ explicitlyListedPinNumbersInSchPortArrangement = Array.from(
2607
+ { length: this._getPinCount() },
2608
+ (_, i) => i + 1
2609
+ );
2610
+ }
2611
+ if (!explicitlyListedPinNumbersInSchPortArrangement.includes(pn)) {
2612
+ continue;
2613
+ }
2614
+ portsToCreate.push(
2615
+ new Port(
2616
+ {
2617
+ pinNumber: pn,
2618
+ aliases: opts.additionalAliases?.[`pin${pn}`] ?? []
2619
+ },
2620
+ {
2621
+ originDescription: `notOtherwiseAddedButDeducedFromPinCount:${pn}`
2622
+ }
2623
+ )
2624
+ );
2625
+ }
2513
2626
  if (portsToCreate.length > 0) {
2514
2627
  this.addAll(portsToCreate);
2515
2628
  }
@@ -2636,6 +2749,14 @@ var NormalComponent = class extends PrimitiveComponent {
2636
2749
  rotation: props.pcbRotation ?? 0,
2637
2750
  source_component_id: this.source_component_id
2638
2751
  });
2752
+ if (!props.footprint) {
2753
+ const footprint_error = db.pcb_missing_footprint_error.insert({
2754
+ message: `No footprint found for component: ${this.componentName}`,
2755
+ source_component_id: `${this.source_component_id}`,
2756
+ error_type: "pcb_missing_footprint_error"
2757
+ });
2758
+ this.pcb_missing_footprint_error_id = footprint_error.pcb_missing_footprint_error_id;
2759
+ }
2639
2760
  this.pcb_component_id = pcb_component.pcb_component_id;
2640
2761
  }
2641
2762
  /**
@@ -2832,7 +2953,17 @@ var NormalComponent = class extends PrimitiveComponent {
2832
2953
  _getPinCount() {
2833
2954
  const schPortArrangement = this._getSchematicPortArrangement();
2834
2955
  if (schPortArrangement) {
2835
- return (schPortArrangement.leftSize ?? 0) + (schPortArrangement.rightSize ?? 0) + (schPortArrangement.topSize ?? 0) + (schPortArrangement.bottomSize ?? 0);
2956
+ const isExplicitPinMapping = isExplicitPinMappingArrangement(schPortArrangement);
2957
+ if (!isExplicitPinMapping) {
2958
+ return (schPortArrangement.leftSize ?? schPortArrangement.leftPinCount ?? 0) + (schPortArrangement.rightSize ?? schPortArrangement.rightPinCount ?? 0) + (schPortArrangement.topSize ?? schPortArrangement.topPinCount ?? 0) + (schPortArrangement.bottomSize ?? schPortArrangement.bottomPinCount ?? 0);
2959
+ }
2960
+ const { leftSide, rightSide, topSide, bottomSide } = schPortArrangement;
2961
+ return Math.max(
2962
+ ...leftSide?.pins ?? [],
2963
+ ...rightSide?.pins ?? [],
2964
+ ...topSide?.pins ?? [],
2965
+ ...bottomSide?.pins ?? []
2966
+ );
2836
2967
  }
2837
2968
  return this.getPortsFromFootprint().length;
2838
2969
  }
@@ -4908,9 +5039,11 @@ var PinHeader = class extends NormalComponent {
4908
5039
  }
4909
5040
  }
4910
5041
  _getSchematicPortArrangement() {
5042
+ const pinCount = this._parsedProps.pinCount ?? 1;
5043
+ const facingDirection = this._parsedProps.facingDirection ?? "right";
4911
5044
  return {
4912
- leftSize: 0,
4913
- rightSize: this._parsedProps.pinCount ?? 1
5045
+ leftSize: facingDirection === "left" ? pinCount : 0,
5046
+ rightSize: facingDirection === "right" ? pinCount : 0
4914
5047
  };
4915
5048
  }
4916
5049
  doInitialSourceRender() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.172",
4
+ "version": "0.0.174",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -40,12 +40,12 @@
40
40
  "@tscircuit/footprinter": "^0.0.77",
41
41
  "@tscircuit/infgrid-ijump-astar": "^0.0.24",
42
42
  "@tscircuit/math-utils": "^0.0.5",
43
- "@tscircuit/props": "^0.0.93",
43
+ "@tscircuit/props": "^0.0.94",
44
44
  "@tscircuit/schematic-autolayout": "^0.0.6",
45
45
  "@tscircuit/soup-util": "^0.0.40",
46
- "circuit-json": "^0.0.99",
46
+ "circuit-json": "^0.0.101",
47
47
  "circuit-json-to-connectivity-map": "^0.0.17",
48
- "circuit-to-svg": "^0.0.71",
48
+ "circuit-to-svg": "^0.0.74",
49
49
  "format-si-unit": "^0.0.2",
50
50
  "nanoid": "^5.0.7",
51
51
  "performance-now": "^2.1.0",