@tscircuit/core 0.0.171 → 0.0.173

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
@@ -1947,6 +1947,31 @@ var getSizeOfSidesFromPortArrangement = (pa) => {
1947
1947
  return { leftSize, rightSize, topSize, bottomSize };
1948
1948
  };
1949
1949
 
1950
+ // lib/utils/schematic/parsePinNumberFromLabelsOrThrow.ts
1951
+ var parsePinNumberFromLabelsOrThrow = (pinNumberOrLabel, pinLabels) => {
1952
+ if (typeof pinNumberOrLabel === "number") {
1953
+ return pinNumberOrLabel;
1954
+ }
1955
+ if (pinNumberOrLabel.startsWith("pin")) {
1956
+ const pinNumber = Number(pinNumberOrLabel.slice(3));
1957
+ return pinNumber;
1958
+ }
1959
+ if (!pinLabels) {
1960
+ throw new Error(
1961
+ `No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`
1962
+ );
1963
+ }
1964
+ for (const pinNumberKey in pinLabels) {
1965
+ const aliases = Array.isArray(pinLabels[pinNumberKey]) ? pinLabels[pinNumberKey] : [pinLabels[pinNumberKey]];
1966
+ if (aliases.includes(pinNumberOrLabel)) {
1967
+ return Number(pinNumberKey.replace("pin", ""));
1968
+ }
1969
+ }
1970
+ throw new Error(
1971
+ `No pin labels provided and pin number or label is not a number: "${pinNumberOrLabel}"`
1972
+ );
1973
+ };
1974
+
1950
1975
  // lib/utils/schematic/getAllDimensionsForSchematicBox.ts
1951
1976
  function isExplicitPinMappingArrangement(arrangement) {
1952
1977
  return arrangement.leftSide !== void 0;
@@ -1985,11 +2010,40 @@ var getAllDimensionsForSchematicBox = (params) => {
1985
2010
  bottomSize: 0
1986
2011
  };
1987
2012
  }
2013
+ const getPinNumberUsingSideIndex = ({
2014
+ side,
2015
+ sideIndex,
2016
+ truePinIndex: truePinIndex2
2017
+ }) => {
2018
+ if (!params.schPortArrangement) return truePinIndex2 + 1;
2019
+ if (!isExplicitPinMappingArrangement(params.schPortArrangement))
2020
+ return truePinIndex2 + 1;
2021
+ const normalCcwDirection = {
2022
+ left: "top-to-bottom",
2023
+ bottom: "left-to-right",
2024
+ right: "bottom-to-top",
2025
+ top: "right-to-left"
2026
+ }[side];
2027
+ const directionAlongSide = params.schPortArrangement?.[`${side}Side`]?.direction ?? normalCcwDirection;
2028
+ const pinsDefinitionForSide = params.schPortArrangement?.[`${side}Side`]?.pins;
2029
+ let sideIndexWithDirectionCorrection = sideIndex;
2030
+ if (directionAlongSide !== normalCcwDirection) {
2031
+ sideIndexWithDirectionCorrection = pinsDefinitionForSide.length - sideIndex - 1;
2032
+ }
2033
+ return parsePinNumberFromLabelsOrThrow(
2034
+ pinsDefinitionForSide[sideIndexWithDirectionCorrection],
2035
+ params.pinLabels
2036
+ );
2037
+ };
1988
2038
  const orderedTruePorts = [];
1989
2039
  let currentDistanceFromEdge = 0;
1990
2040
  let truePinIndex = 0;
1991
2041
  for (let sideIndex = 0; sideIndex < sidePinCounts.leftSize; sideIndex++) {
1992
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement?.leftSide?.pins[sideIndex] : truePinIndex + 1;
2042
+ const pinNumber = getPinNumberUsingSideIndex({
2043
+ side: "left",
2044
+ sideIndex,
2045
+ truePinIndex
2046
+ });
1993
2047
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
1994
2048
  if (pinStyle?.topMargin) {
1995
2049
  currentDistanceFromEdge += pinStyle.topMargin;
@@ -2013,7 +2067,11 @@ var getAllDimensionsForSchematicBox = (params) => {
2013
2067
  }
2014
2068
  currentDistanceFromEdge = 0;
2015
2069
  for (let sideIndex = 0; sideIndex < sidePinCounts.bottomSize; sideIndex++) {
2016
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.bottomSide?.pins[sideIndex] : truePinIndex + 1;
2070
+ const pinNumber = getPinNumberUsingSideIndex({
2071
+ side: "bottom",
2072
+ sideIndex,
2073
+ truePinIndex
2074
+ });
2017
2075
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
2018
2076
  if (pinStyle?.leftMargin) {
2019
2077
  currentDistanceFromEdge += pinStyle.leftMargin;
@@ -2037,7 +2095,11 @@ var getAllDimensionsForSchematicBox = (params) => {
2037
2095
  }
2038
2096
  currentDistanceFromEdge = 0;
2039
2097
  for (let sideIndex = 0; sideIndex < sidePinCounts.rightSize; sideIndex++) {
2040
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.rightSide?.pins[sideIndex] : truePinIndex + 1;
2098
+ const pinNumber = getPinNumberUsingSideIndex({
2099
+ side: "right",
2100
+ sideIndex,
2101
+ truePinIndex
2102
+ });
2041
2103
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
2042
2104
  if (pinStyle?.bottomMargin) {
2043
2105
  currentDistanceFromEdge += pinStyle.bottomMargin;
@@ -2061,7 +2123,11 @@ var getAllDimensionsForSchematicBox = (params) => {
2061
2123
  }
2062
2124
  currentDistanceFromEdge = 0;
2063
2125
  for (let sideIndex = 0; sideIndex < sidePinCounts.topSize; sideIndex++) {
2064
- const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.topSide?.pins[sideIndex] : truePinIndex + 1;
2126
+ const pinNumber = getPinNumberUsingSideIndex({
2127
+ side: "top",
2128
+ sideIndex,
2129
+ truePinIndex
2130
+ });
2065
2131
  const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
2066
2132
  if (pinStyle?.rightMargin) {
2067
2133
  currentDistanceFromEdge += pinStyle.rightMargin;
@@ -2096,7 +2162,7 @@ var getAllDimensionsForSchematicBox = (params) => {
2096
2162
  // Estimated text width
2097
2163
  )
2098
2164
  ) : 0;
2099
- const LABEL_PADDING = 1.1;
2165
+ const LABEL_PADDING = labelWidth > 0 ? 1.1 : 0;
2100
2166
  schWidth = Math.max(schWidth, labelWidth + LABEL_PADDING);
2101
2167
  let schHeight = params.schHeight;
2102
2168
  if (!schHeight) {
@@ -2389,6 +2455,7 @@ var NormalComponent = class extends PrimitiveComponent {
2389
2455
  _impliedFootprint;
2390
2456
  isPrimitiveContainer = true;
2391
2457
  _asyncSupplierPartNumbers;
2458
+ pcb_missing_footprint_error_id;
2392
2459
  constructor(props) {
2393
2460
  super(props);
2394
2461
  this._addChildrenFromStringFootprint();
@@ -2412,11 +2479,15 @@ var NormalComponent = class extends PrimitiveComponent {
2412
2479
  const { config } = this;
2413
2480
  const portsToCreate = [];
2414
2481
  const schPortArrangement = this._parsedProps.schPortArrangement;
2415
- if (schPortArrangement) {
2482
+ if (schPortArrangement && !this._parsedProps.pinLabels) {
2416
2483
  for (const side in schPortArrangement) {
2417
2484
  const pins = schPortArrangement[side].pins;
2418
2485
  if (Array.isArray(pins)) {
2419
- for (const pinNumber of pins) {
2486
+ for (const pinNumberOrLabel of pins) {
2487
+ const pinNumber = parsePinNumberFromLabelsOrThrow(
2488
+ pinNumberOrLabel,
2489
+ this._parsedProps.pinLabels
2490
+ );
2420
2491
  portsToCreate.push(
2421
2492
  new Port(
2422
2493
  {
@@ -2510,6 +2581,47 @@ var NormalComponent = class extends PrimitiveComponent {
2510
2581
  }
2511
2582
  }
2512
2583
  }
2584
+ for (let pn = 1; pn <= this._getPinCount(); pn++) {
2585
+ if (!this._parsedProps.schPortArrangement) continue;
2586
+ if (portsToCreate.find((p) => p._parsedProps.pinNumber === pn)) continue;
2587
+ let explicitlyListedPinNumbersInSchPortArrangement = [
2588
+ ...this._parsedProps.schPortArrangement?.leftSide?.pins ?? [],
2589
+ ...this._parsedProps.schPortArrangement?.rightSide?.pins ?? [],
2590
+ ...this._parsedProps.schPortArrangement?.topSide?.pins ?? [],
2591
+ ...this._parsedProps.schPortArrangement?.bottomSide?.pins ?? []
2592
+ ].map(
2593
+ (pn2) => parsePinNumberFromLabelsOrThrow(pn2, this._parsedProps.pinLabels)
2594
+ );
2595
+ if ([
2596
+ "leftSize",
2597
+ "rightSize",
2598
+ "topSize",
2599
+ "bottomSize",
2600
+ "leftPinCount",
2601
+ "rightPinCount",
2602
+ "topPinCount",
2603
+ "bottomPinCount"
2604
+ ].some((key) => key in this._parsedProps.schPortArrangement)) {
2605
+ explicitlyListedPinNumbersInSchPortArrangement = Array.from(
2606
+ { length: this._getPinCount() },
2607
+ (_, i) => i + 1
2608
+ );
2609
+ }
2610
+ if (!explicitlyListedPinNumbersInSchPortArrangement.includes(pn)) {
2611
+ continue;
2612
+ }
2613
+ portsToCreate.push(
2614
+ new Port(
2615
+ {
2616
+ pinNumber: pn,
2617
+ aliases: opts.additionalAliases?.[`pin${pn}`] ?? []
2618
+ },
2619
+ {
2620
+ originDescription: `notOtherwiseAddedButDeducedFromPinCount:${pn}`
2621
+ }
2622
+ )
2623
+ );
2624
+ }
2513
2625
  if (portsToCreate.length > 0) {
2514
2626
  this.addAll(portsToCreate);
2515
2627
  }
@@ -2636,6 +2748,14 @@ var NormalComponent = class extends PrimitiveComponent {
2636
2748
  rotation: props.pcbRotation ?? 0,
2637
2749
  source_component_id: this.source_component_id
2638
2750
  });
2751
+ if (!props.footprint) {
2752
+ const footprint_error = db.pcb_missing_footprint_error.insert({
2753
+ message: `No footprint found for component: ${this.componentName}`,
2754
+ source_component_id: `${this.source_component_id}`,
2755
+ error_type: "pcb_missing_footprint_error"
2756
+ });
2757
+ this.pcb_missing_footprint_error_id = footprint_error.pcb_missing_footprint_error_id;
2758
+ }
2639
2759
  this.pcb_component_id = pcb_component.pcb_component_id;
2640
2760
  }
2641
2761
  /**
@@ -2832,7 +2952,17 @@ var NormalComponent = class extends PrimitiveComponent {
2832
2952
  _getPinCount() {
2833
2953
  const schPortArrangement = this._getSchematicPortArrangement();
2834
2954
  if (schPortArrangement) {
2835
- return (schPortArrangement.leftSize ?? 0) + (schPortArrangement.rightSize ?? 0) + (schPortArrangement.topSize ?? 0) + (schPortArrangement.bottomSize ?? 0);
2955
+ const isExplicitPinMapping = isExplicitPinMappingArrangement(schPortArrangement);
2956
+ if (!isExplicitPinMapping) {
2957
+ return (schPortArrangement.leftSize ?? schPortArrangement.leftPinCount ?? 0) + (schPortArrangement.rightSize ?? schPortArrangement.rightPinCount ?? 0) + (schPortArrangement.topSize ?? schPortArrangement.topPinCount ?? 0) + (schPortArrangement.bottomSize ?? schPortArrangement.bottomPinCount ?? 0);
2958
+ }
2959
+ const { leftSide, rightSide, topSide, bottomSide } = schPortArrangement;
2960
+ return Math.max(
2961
+ ...leftSide?.pins ?? [],
2962
+ ...rightSide?.pins ?? [],
2963
+ ...topSide?.pins ?? [],
2964
+ ...bottomSide?.pins ?? []
2965
+ );
2836
2966
  }
2837
2967
  return this.getPortsFromFootprint().length;
2838
2968
  }
@@ -4908,9 +5038,11 @@ var PinHeader = class extends NormalComponent {
4908
5038
  }
4909
5039
  }
4910
5040
  _getSchematicPortArrangement() {
5041
+ const pinCount = this._parsedProps.pinCount ?? 1;
5042
+ const facingDirection = this._parsedProps.facingDirection ?? "right";
4911
5043
  return {
4912
- leftSize: 0,
4913
- rightSize: this._parsedProps.pinCount ?? 1
5044
+ leftSize: facingDirection === "left" ? pinCount : 0,
5045
+ rightSize: facingDirection === "right" ? pinCount : 0
4914
5046
  };
4915
5047
  }
4916
5048
  doInitialSourceRender() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.171",
4
+ "version": "0.0.173",
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",