@tscircuit/footprinter 0.0.303 → 0.0.304

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.js CHANGED
@@ -8397,6 +8397,10 @@ var mountedpcbmodule_def = base_def.extend({
8397
8397
  pinrowright: z77.boolean().optional().default(false),
8398
8398
  pinrowtop: z77.boolean().optional().default(false),
8399
8399
  pinrowbottom: z77.boolean().optional().default(false),
8400
+ pinrowleftpins: z77.union([z77.string(), z77.number()]).transform((val) => Number(val)).optional(),
8401
+ pinrowrightpins: z77.union([z77.string(), z77.number()]).transform((val) => Number(val)).optional(),
8402
+ pinrowtoppins: z77.union([z77.string(), z77.number()]).transform((val) => Number(val)).optional(),
8403
+ pinrowbottompins: z77.union([z77.string(), z77.number()]).transform((val) => Number(val)).optional(),
8400
8404
  width: length59.optional(),
8401
8405
  height: length59.optional(),
8402
8406
  pinRowHoleEdgeToEdgeDist: length59.default("2mm"),
@@ -8438,10 +8442,41 @@ var mountedpcbmodule_def = base_def.extend({
8438
8442
  if (data.pinrow !== void 0) {
8439
8443
  data.numPins = Number(data.pinrow);
8440
8444
  }
8445
+ const sidePinCounts = {
8446
+ left: data.pinrowleftpins,
8447
+ right: data.pinrowrightpins,
8448
+ top: data.pinrowtoppins,
8449
+ bottom: data.pinrowbottompins
8450
+ };
8451
+ const hasSidePins = Object.values(sidePinCounts).some(
8452
+ (value) => value !== void 0 && value > 0
8453
+ );
8454
+ const leftRightBoth = (sidePinCounts.left ?? 0) > 0 && (sidePinCounts.right ?? 0) > 0;
8455
+ const topBottomBoth = (sidePinCounts.top ?? 0) > 0 && (sidePinCounts.bottom ?? 0) > 0;
8456
+ if (hasSidePins) {
8457
+ if ((sidePinCounts.left ?? 0) > 0) pinRowSide = "left";
8458
+ else if ((sidePinCounts.right ?? 0) > 0) pinRowSide = "right";
8459
+ else if ((sidePinCounts.top ?? 0) > 0) pinRowSide = "top";
8460
+ else if ((sidePinCounts.bottom ?? 0) > 0) pinRowSide = "bottom";
8461
+ data.numPins = (sidePinCounts.left ?? 0) + (sidePinCounts.right ?? 0) + (sidePinCounts.top ?? 0) + (sidePinCounts.bottom ?? 0);
8462
+ }
8441
8463
  const numPinsPerRow = Math.ceil(data.numPins / data.rows);
8464
+ const verticalPins = Math.max(
8465
+ sidePinCounts.left ?? 0,
8466
+ sidePinCounts.right ?? 0
8467
+ );
8468
+ const horizontalPins = Math.max(
8469
+ sidePinCounts.top ?? 0,
8470
+ sidePinCounts.bottom ?? 0
8471
+ );
8442
8472
  let calculatedWidth;
8443
8473
  let calculatedHeight;
8444
- if (pinRowSide === "left" || pinRowSide === "right") {
8474
+ if (hasSidePins) {
8475
+ const widthGap = leftRightBoth ? data.p : 0;
8476
+ const heightGap = topBottomBoth ? data.p : 0;
8477
+ calculatedWidth = (horizontalPins > 0 ? (horizontalPins - 1) * data.p : 0) + 2 * data.pinRowHoleEdgeToEdgeDist + widthGap;
8478
+ calculatedHeight = (verticalPins > 0 ? (verticalPins - 1) * data.p : 0) + 2 * data.pinRowHoleEdgeToEdgeDist + heightGap;
8479
+ } else if (pinRowSide === "left" || pinRowSide === "right") {
8445
8480
  calculatedWidth = (data.rows - 1) * data.p + 2 * data.pinRowHoleEdgeToEdgeDist;
8446
8481
  calculatedHeight = (numPinsPerRow - 1) * data.p + 2 * data.pinRowHoleEdgeToEdgeDist;
8447
8482
  } else {
@@ -8456,10 +8491,16 @@ var mountedpcbmodule_def = base_def.extend({
8456
8491
  ...data,
8457
8492
  pinlabelAnchorSide,
8458
8493
  pinRowSide,
8494
+ usbposition,
8495
+ usbtype,
8459
8496
  male: data.male ?? !data.female,
8460
8497
  female: data.female ?? false,
8461
8498
  width: data.width ?? calculatedWidth,
8462
- height: data.height ?? calculatedHeight
8499
+ height: data.height ?? calculatedHeight,
8500
+ pinrowleftpins: sidePinCounts.left,
8501
+ pinrowrightpins: sidePinCounts.right,
8502
+ pinrowtoppins: sidePinCounts.top,
8503
+ pinrowbottompins: sidePinCounts.bottom
8463
8504
  };
8464
8505
  }).superRefine((data, ctx) => {
8465
8506
  if (data.male && data.female) {
@@ -8493,95 +8534,195 @@ var mountedpcbmodule = (raw_params) => {
8493
8534
  holes,
8494
8535
  holeXDist,
8495
8536
  holeYDist,
8496
- holeInset
8537
+ holeInset,
8538
+ pinrowleftpins,
8539
+ pinrowrightpins,
8540
+ pinrowtoppins,
8541
+ pinrowbottompins,
8542
+ usbposition,
8543
+ usbtype
8497
8544
  } = parameters;
8498
8545
  let pinlabelTextAlign = "center";
8499
8546
  if (pinlabeltextalignleft) pinlabelTextAlign = "left";
8500
8547
  else if (pinlabeltextalignright) pinlabelTextAlign = "right";
8501
8548
  const elements = [];
8502
- const pinSpacing = p;
8503
- let pinStartX = 0;
8504
- let pinStartY = 0;
8505
- let pinDirectionX = 0;
8506
- let pinDirectionY = 0;
8507
- let rowDirectionX = 0;
8508
- let rowDirectionY = 0;
8509
- const numPinsPerRow = Math.ceil(numPins / rows);
8510
- if (pinRowSide === "left" || pinRowSide === "right") {
8511
- pinStartX = pinRowSide === "left" ? -width / 2 + pinRowHoleEdgeToEdgeDist : width / 2 - pinRowHoleEdgeToEdgeDist;
8512
- pinStartY = (numPinsPerRow - 1) / 2 * pinSpacing;
8513
- pinDirectionX = 0;
8514
- pinDirectionY = -pinSpacing;
8515
- rowDirectionX = pinRowSide === "left" ? pinSpacing : -pinSpacing;
8516
- rowDirectionY = 0;
8517
- } else {
8518
- pinStartX = -(numPinsPerRow - 1) / 2 * pinSpacing;
8519
- pinStartY = pinRowSide === "top" ? height / 2 - pinRowHoleEdgeToEdgeDist : -height / 2 + pinRowHoleEdgeToEdgeDist;
8520
- pinDirectionX = pinSpacing;
8521
- pinDirectionY = 0;
8522
- rowDirectionX = 0;
8523
- rowDirectionY = pinRowSide === "top" ? -pinSpacing : pinSpacing;
8524
- }
8525
- let pinNumber = 1;
8526
- for (let row = 0; row < rows && pinNumber <= numPins; row++) {
8527
- for (let col = 0; col < numPinsPerRow && pinNumber <= numPins; col++) {
8528
- const xoff = pinStartX + col * pinDirectionX + row * rowDirectionX;
8529
- const yoff = pinStartY + col * pinDirectionY + row * rowDirectionY;
8530
- if (parameters.smd) {
8549
+ const sidePinCounts = {
8550
+ left: pinrowleftpins,
8551
+ right: pinrowrightpins,
8552
+ top: pinrowtoppins,
8553
+ bottom: pinrowbottompins
8554
+ };
8555
+ const hasSidePins = Object.values(sidePinCounts).some(
8556
+ (value) => value !== void 0 && value > 0
8557
+ );
8558
+ const addPin = (pinNumber, xoff, yoff, anchorSide) => {
8559
+ if (parameters.smd) {
8560
+ elements.push(
8561
+ rectpad(pinNumber, xoff, yoff, parameters.od, parameters.od)
8562
+ );
8563
+ } else if (pinNumber === 1) {
8564
+ elements.push(
8565
+ platedHoleWithRectPad({
8566
+ pn: pinNumber,
8567
+ x: xoff,
8568
+ y: yoff,
8569
+ holeDiameter: id,
8570
+ rectPadWidth: od,
8571
+ rectPadHeight: od
8572
+ })
8573
+ );
8574
+ } else {
8575
+ elements.push(platedhole(pinNumber, xoff, yoff, id, od));
8576
+ }
8577
+ if (!nopinlabels) {
8578
+ const anchor_x = xoff + (anchorSide === "left" ? -od : anchorSide === "right" ? od : 0);
8579
+ const anchor_y = yoff + (anchorSide === "top" ? od : anchorSide === "bottom" ? -od : 0);
8580
+ if (!bottomsidepinlabel) {
8531
8581
  elements.push(
8532
- rectpad(pinNumber, xoff, yoff, parameters.od, parameters.od)
8582
+ silkscreenPin({
8583
+ fs: od / 5,
8584
+ pn: pinNumber,
8585
+ anchor_x,
8586
+ anchor_y,
8587
+ anchorplacement: anchorSide,
8588
+ textalign: pinlabelTextAlign,
8589
+ orthogonal: pinlabelorthogonal,
8590
+ verticallyinverted: pinlabelverticallyinverted,
8591
+ layer: "top"
8592
+ })
8533
8593
  );
8594
+ }
8595
+ if (doublesidedpinlabel || bottomsidepinlabel) {
8596
+ elements.push(
8597
+ silkscreenPin({
8598
+ fs: od / 5,
8599
+ pn: pinNumber,
8600
+ anchor_x,
8601
+ anchor_y,
8602
+ anchorplacement: anchorSide,
8603
+ textalign: pinlabelTextAlign,
8604
+ orthogonal: pinlabelorthogonal,
8605
+ verticallyinverted: pinlabelverticallyinverted,
8606
+ layer: "bottom"
8607
+ })
8608
+ );
8609
+ }
8610
+ }
8611
+ };
8612
+ if (hasSidePins) {
8613
+ const pinSpacing = p;
8614
+ let pinNumber = 1;
8615
+ const leftCount = sidePinCounts.left ?? 0;
8616
+ const rightCount = sidePinCounts.right ?? 0;
8617
+ const topCount = sidePinCounts.top ?? 0;
8618
+ const bottomCount = sidePinCounts.bottom ?? 0;
8619
+ const addSidePins = (side, count) => {
8620
+ if (count <= 0) return;
8621
+ if (side === "left" || side === "right") {
8622
+ const xoff = side === "left" ? -width / 2 + pinRowHoleEdgeToEdgeDist : width / 2 - pinRowHoleEdgeToEdgeDist;
8623
+ const startY = (count - 1) / 2 * pinSpacing;
8624
+ for (let i = 0; i < count; i++) {
8625
+ addPin(pinNumber, xoff, startY - i * pinSpacing, side);
8626
+ pinNumber++;
8627
+ }
8534
8628
  } else {
8535
- if (pinNumber === 1) {
8536
- elements.push(
8537
- platedHoleWithRectPad({
8538
- pn: pinNumber,
8539
- x: xoff,
8540
- y: yoff,
8541
- holeDiameter: id,
8542
- rectPadWidth: od,
8543
- rectPadHeight: od
8544
- })
8545
- );
8546
- } else {
8547
- elements.push(platedhole(pinNumber, xoff, yoff, id, od));
8629
+ const yoff = side === "top" ? height / 2 - pinRowHoleEdgeToEdgeDist : -height / 2 + pinRowHoleEdgeToEdgeDist;
8630
+ const startX = -((count - 1) / 2) * pinSpacing;
8631
+ for (let i = 0; i < count; i++) {
8632
+ addPin(pinNumber, startX + i * pinSpacing, yoff, side);
8633
+ pinNumber++;
8548
8634
  }
8549
8635
  }
8550
- if (!nopinlabels) {
8551
- const anchor_x = xoff + (pinRowSide === "left" ? -od : pinRowSide === "right" ? od : 0);
8552
- const anchor_y = yoff + (pinRowSide === "top" ? od : pinRowSide === "bottom" ? -od : 0);
8553
- if (!bottomsidepinlabel) {
8636
+ };
8637
+ addSidePins("left", leftCount);
8638
+ addSidePins("right", rightCount);
8639
+ addSidePins("top", topCount);
8640
+ addSidePins("bottom", bottomCount);
8641
+ } else {
8642
+ const pinSpacing = p;
8643
+ let pinStartX = 0;
8644
+ let pinStartY = 0;
8645
+ let pinDirectionX = 0;
8646
+ let pinDirectionY = 0;
8647
+ let rowDirectionX = 0;
8648
+ let rowDirectionY = 0;
8649
+ const numPinsPerRow = Math.ceil(numPins / rows);
8650
+ if (pinRowSide === "left" || pinRowSide === "right") {
8651
+ pinStartX = pinRowSide === "left" ? -width / 2 + pinRowHoleEdgeToEdgeDist : width / 2 - pinRowHoleEdgeToEdgeDist;
8652
+ pinStartY = (numPinsPerRow - 1) / 2 * pinSpacing;
8653
+ pinDirectionX = 0;
8654
+ pinDirectionY = -pinSpacing;
8655
+ rowDirectionX = pinRowSide === "left" ? pinSpacing : -pinSpacing;
8656
+ rowDirectionY = 0;
8657
+ } else {
8658
+ pinStartX = -(numPinsPerRow - 1) / 2 * pinSpacing;
8659
+ pinStartY = pinRowSide === "top" ? height / 2 - pinRowHoleEdgeToEdgeDist : -height / 2 + pinRowHoleEdgeToEdgeDist;
8660
+ pinDirectionX = pinSpacing;
8661
+ pinDirectionY = 0;
8662
+ rowDirectionX = 0;
8663
+ rowDirectionY = pinRowSide === "top" ? -pinSpacing : pinSpacing;
8664
+ }
8665
+ let pinNumber = 1;
8666
+ for (let row = 0; row < rows && pinNumber <= numPins; row++) {
8667
+ for (let col = 0; col < numPinsPerRow && pinNumber <= numPins; col++) {
8668
+ const xoff = pinStartX + col * pinDirectionX + row * rowDirectionX;
8669
+ const yoff = pinStartY + col * pinDirectionY + row * rowDirectionY;
8670
+ if (parameters.smd) {
8554
8671
  elements.push(
8555
- silkscreenPin({
8556
- fs: od / 5,
8557
- pn: pinNumber,
8558
- anchor_x,
8559
- anchor_y,
8560
- anchorplacement: pinlabelAnchorSide,
8561
- textalign: pinlabelTextAlign,
8562
- orthogonal: pinlabelorthogonal,
8563
- verticallyinverted: pinlabelverticallyinverted,
8564
- layer: "top"
8565
- })
8672
+ rectpad(pinNumber, xoff, yoff, parameters.od, parameters.od)
8566
8673
  );
8674
+ } else {
8675
+ if (pinNumber === 1) {
8676
+ elements.push(
8677
+ platedHoleWithRectPad({
8678
+ pn: pinNumber,
8679
+ x: xoff,
8680
+ y: yoff,
8681
+ holeDiameter: id,
8682
+ rectPadWidth: od,
8683
+ rectPadHeight: od
8684
+ })
8685
+ );
8686
+ } else {
8687
+ elements.push(platedhole(pinNumber, xoff, yoff, id, od));
8688
+ }
8567
8689
  }
8568
- if (doublesidedpinlabel || bottomsidepinlabel) {
8569
- elements.push(
8570
- silkscreenPin({
8571
- fs: od / 5,
8572
- pn: pinNumber,
8573
- anchor_x,
8574
- anchor_y,
8575
- anchorplacement: pinlabelAnchorSide,
8576
- textalign: pinlabelTextAlign,
8577
- orthogonal: pinlabelorthogonal,
8578
- verticallyinverted: pinlabelverticallyinverted,
8579
- layer: "bottom"
8580
- })
8581
- );
8690
+ if (!nopinlabels) {
8691
+ const anchor_x = xoff + (pinRowSide === "left" ? -od : pinRowSide === "right" ? od : 0);
8692
+ const anchor_y = yoff + (pinRowSide === "top" ? od : pinRowSide === "bottom" ? -od : 0);
8693
+ if (!bottomsidepinlabel) {
8694
+ elements.push(
8695
+ silkscreenPin({
8696
+ fs: od / 5,
8697
+ pn: pinNumber,
8698
+ anchor_x,
8699
+ anchor_y,
8700
+ anchorplacement: pinlabelAnchorSide,
8701
+ textalign: pinlabelTextAlign,
8702
+ orthogonal: pinlabelorthogonal,
8703
+ verticallyinverted: pinlabelverticallyinverted,
8704
+ layer: "top"
8705
+ })
8706
+ );
8707
+ }
8708
+ if (doublesidedpinlabel || bottomsidepinlabel) {
8709
+ elements.push(
8710
+ silkscreenPin({
8711
+ fs: od / 5,
8712
+ pn: pinNumber,
8713
+ anchor_x,
8714
+ anchor_y,
8715
+ anchorplacement: pinlabelAnchorSide,
8716
+ textalign: pinlabelTextAlign,
8717
+ orthogonal: pinlabelorthogonal,
8718
+ verticallyinverted: pinlabelverticallyinverted,
8719
+ layer: "bottom"
8720
+ })
8721
+ );
8722
+ }
8582
8723
  }
8724
+ pinNumber++;
8583
8725
  }
8584
- pinNumber++;
8585
8726
  }
8586
8727
  }
8587
8728
  if (holes) {
@@ -8623,6 +8764,62 @@ var mountedpcbmodule = (raw_params) => {
8623
8764
  }
8624
8765
  const refText = silkscreenRef(0, height / 2 + 1, 0.5);
8625
8766
  elements.push(refText);
8767
+ if (usbposition && usbtype) {
8768
+ let usbRectWidth;
8769
+ let usbRectHeight;
8770
+ if (usbtype === "c") {
8771
+ usbRectWidth = 8;
8772
+ usbRectHeight = 3;
8773
+ } else if (usbtype === "micro") {
8774
+ usbRectWidth = 6;
8775
+ usbRectHeight = 2;
8776
+ } else {
8777
+ return {
8778
+ circuitJson: elements,
8779
+ parameters
8780
+ };
8781
+ }
8782
+ let usbRect;
8783
+ if (usbposition === "left") {
8784
+ usbRect = [
8785
+ { x: -width / 2, y: -usbRectWidth / 2 },
8786
+ { x: -width / 2 + usbRectHeight, y: -usbRectWidth / 2 },
8787
+ { x: -width / 2 + usbRectHeight, y: usbRectWidth / 2 },
8788
+ { x: -width / 2, y: usbRectWidth / 2 },
8789
+ { x: -width / 2, y: -usbRectWidth / 2 }
8790
+ ];
8791
+ } else if (usbposition === "right") {
8792
+ usbRect = [
8793
+ { x: width / 2 - usbRectHeight, y: -usbRectWidth / 2 },
8794
+ { x: width / 2, y: -usbRectWidth / 2 },
8795
+ { x: width / 2, y: usbRectWidth / 2 },
8796
+ { x: width / 2 - usbRectHeight, y: usbRectWidth / 2 },
8797
+ { x: width / 2 - usbRectHeight, y: -usbRectWidth / 2 }
8798
+ ];
8799
+ } else if (usbposition === "top") {
8800
+ usbRect = [
8801
+ { x: -usbRectWidth / 2, y: height / 2 - usbRectHeight },
8802
+ { x: usbRectWidth / 2, y: height / 2 - usbRectHeight },
8803
+ { x: usbRectWidth / 2, y: height / 2 },
8804
+ { x: -usbRectWidth / 2, y: height / 2 },
8805
+ { x: -usbRectWidth / 2, y: height / 2 - usbRectHeight }
8806
+ ];
8807
+ } else if (usbposition === "bottom") {
8808
+ usbRect = [
8809
+ { x: -usbRectWidth / 2, y: -height / 2 },
8810
+ { x: usbRectWidth / 2, y: -height / 2 },
8811
+ { x: usbRectWidth / 2, y: -height / 2 + usbRectHeight },
8812
+ { x: -usbRectWidth / 2, y: -height / 2 + usbRectHeight },
8813
+ { x: -usbRectWidth / 2, y: -height / 2 }
8814
+ ];
8815
+ } else {
8816
+ return {
8817
+ circuitJson: elements,
8818
+ parameters
8819
+ };
8820
+ }
8821
+ elements.push(silkscreenpath(usbRect, { stroke_width: 0.1, layer: "top" }));
8822
+ }
8626
8823
  return {
8627
8824
  circuitJson: elements,
8628
8825
  parameters