jscad-electronics 0.0.154 → 0.0.156

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/vanilla.js CHANGED
@@ -181,6 +181,7 @@ var ExtrudedPads = ({
181
181
 
182
182
  // lib/Footprinter3d.tsx
183
183
  import { fp as fp5 } from "@tscircuit/footprinter";
184
+ import { mp } from "@tscircuit/modelprinter";
184
185
 
185
186
  // lib/ChipBody.tsx
186
187
  var ChipBody = ({
@@ -854,7 +855,6 @@ var PinHeader = ({
854
855
  bodyLength: bodyLength10 = 2.54,
855
856
  bodyWidth = 2.54,
856
857
  flipZ,
857
- faceup,
858
858
  smd,
859
859
  rightangle
860
860
  }) => {
@@ -867,7 +867,7 @@ var PinHeader = ({
867
867
  center: [x, y, flipZ(bodyHeight / 2)]
868
868
  }
869
869
  ) }),
870
- !faceup && /* @__PURE__ */ jsx(Colorize, { color: PIN_METAL_COLOR, children: smd ? /* @__PURE__ */ jsx(
870
+ /* @__PURE__ */ jsx(Colorize, { color: PIN_METAL_COLOR, children: smd ? /* @__PURE__ */ jsx(
871
871
  SmdChipLead,
872
872
  {
873
873
  rotation: -Math.PI / 2,
@@ -935,7 +935,6 @@ var PinRow = ({
935
935
  pitch = 2.54,
936
936
  longSidePinLength = 6,
937
937
  invert,
938
- faceup,
939
938
  rows = 1,
940
939
  smd,
941
940
  rightangle
@@ -946,8 +945,9 @@ var PinRow = ({
946
945
  const rowSpacing = 2.54;
947
946
  const shortSidePinLength = 3;
948
947
  const xoff = -((pinsPerRow - 1) / 2) * pitch;
949
- const zOffset = !smd && !rightangle ? -bodyHeight - 1.6 : 0;
950
- const flipZ = (z) => (invert || faceup ? -z + bodyHeight : z) + zOffset;
948
+ const throughHole = !smd && !rightangle;
949
+ const flipped = throughHole ? !invert : Boolean(invert);
950
+ const flipZ = (z) => flipped ? -z + bodyHeight : z;
951
951
  return /* @__PURE__ */ jsx(Fragment2, { children: Array.from({ length: numberOfPins }, (_, i) => {
952
952
  const row = Math.floor(i / pinsPerRow);
953
953
  const col = i % pinsPerRow;
@@ -963,7 +963,6 @@ var PinRow = ({
963
963
  longSidePinLength,
964
964
  bodyHeight,
965
965
  flipZ,
966
- faceup,
967
966
  smd,
968
967
  rightangle
969
968
  },
@@ -6459,8 +6458,559 @@ var BGA = ({
6459
6458
  ] });
6460
6459
  };
6461
6460
 
6461
+ // lib/FlexScreen.tsx
6462
+ var DEFAULT_ASPECT_RATIO = 16 / 9;
6463
+ var DEFAULT_DIAGONAL = 40;
6464
+ var EPSILON = 1e-6;
6465
+ var assertPositive = (name, value) => {
6466
+ if (!Number.isFinite(value) || value <= 0) {
6467
+ throw new Error(`${name} must be a finite number greater than zero`);
6468
+ }
6469
+ };
6470
+ var resolveAspectRatio = (value) => {
6471
+ if (value === void 0) return DEFAULT_ASPECT_RATIO;
6472
+ if (typeof value === "number") {
6473
+ assertPositive("aspectRatio", value);
6474
+ return value;
6475
+ }
6476
+ if (typeof value !== "string") {
6477
+ const [ratioWidth2, ratioHeight2] = value;
6478
+ assertPositive("aspectRatio width", ratioWidth2);
6479
+ assertPositive("aspectRatio height", ratioHeight2);
6480
+ return ratioWidth2 / ratioHeight2;
6481
+ }
6482
+ const parts = value.split(":");
6483
+ if (parts.length !== 2) {
6484
+ throw new Error('aspectRatio must look like "16:9"');
6485
+ }
6486
+ const ratioWidth = Number(parts[0]);
6487
+ const ratioHeight = Number(parts[1]);
6488
+ assertPositive("aspectRatio width", ratioWidth);
6489
+ assertPositive("aspectRatio height", ratioHeight);
6490
+ return ratioWidth / ratioHeight;
6491
+ };
6492
+ var resolveFlexScreenSize = ({
6493
+ width: width10,
6494
+ height: height10,
6495
+ diagonal,
6496
+ aspectRatio,
6497
+ ratio,
6498
+ defaultDiagonal = DEFAULT_DIAGONAL
6499
+ }) => {
6500
+ const resolvedRatio = resolveAspectRatio(aspectRatio ?? ratio);
6501
+ if (width10 !== void 0) assertPositive("width", width10);
6502
+ if (height10 !== void 0) assertPositive("height", height10);
6503
+ if (diagonal !== void 0) assertPositive("diagonal", diagonal);
6504
+ assertPositive("defaultDiagonal", defaultDiagonal);
6505
+ let resolvedWidth;
6506
+ let resolvedHeight;
6507
+ if (width10 !== void 0 && height10 !== void 0) {
6508
+ resolvedWidth = width10;
6509
+ resolvedHeight = height10;
6510
+ } else if (diagonal !== void 0 && width10 !== void 0) {
6511
+ if (width10 >= diagonal) {
6512
+ throw new Error("width must be smaller than diagonal");
6513
+ }
6514
+ resolvedWidth = width10;
6515
+ resolvedHeight = Math.sqrt(diagonal ** 2 - width10 ** 2);
6516
+ } else if (diagonal !== void 0 && height10 !== void 0) {
6517
+ if (height10 >= diagonal) {
6518
+ throw new Error("height must be smaller than diagonal");
6519
+ }
6520
+ resolvedWidth = Math.sqrt(diagonal ** 2 - height10 ** 2);
6521
+ resolvedHeight = height10;
6522
+ } else if (width10 !== void 0) {
6523
+ resolvedWidth = width10;
6524
+ resolvedHeight = width10 / resolvedRatio;
6525
+ } else if (height10 !== void 0) {
6526
+ resolvedWidth = height10 * resolvedRatio;
6527
+ resolvedHeight = height10;
6528
+ } else {
6529
+ const resolvedDiagonal = diagonal ?? defaultDiagonal;
6530
+ resolvedHeight = resolvedDiagonal / Math.sqrt(resolvedRatio ** 2 + 1);
6531
+ resolvedWidth = resolvedHeight * resolvedRatio;
6532
+ }
6533
+ return {
6534
+ width: resolvedWidth,
6535
+ height: resolvedHeight,
6536
+ diagonal: Math.hypot(resolvedWidth, resolvedHeight),
6537
+ aspectRatio: resolvedWidth / resolvedHeight
6538
+ };
6539
+ };
6540
+ var resolveOrientation = (props) => {
6541
+ const shortcuts = [
6542
+ ["sitsFlat", props.sitsFlat],
6543
+ ["sitsFlatBelowBoard", props.sitsFlatBelowBoard],
6544
+ ["foldedToFaceAboveBoard", props.foldedToFaceAboveBoard],
6545
+ ["foldedToFaceBelowBoard", props.foldedToFaceBelowBoard],
6546
+ ["foldedToFaceAboveBoard", props.foldsAboveBoard],
6547
+ ["foldedToFaceBelowBoard", props.foldsBelowBoard],
6548
+ ["foldedToRightAngleAboveBoard", props.foldedToRightAngleAboveBoard],
6549
+ ["foldedToRightAngleBelowBoard", props.foldedToRightAngleBelowBoard]
6550
+ ].filter((entry) => entry[1]);
6551
+ if (shortcuts.length > 1) {
6552
+ throw new Error(
6553
+ "Only one FlexScreen boolean orientation shortcut can be true"
6554
+ );
6555
+ }
6556
+ return shortcuts[0]?.[0] ?? props.orientation ?? "sitsFlat";
6557
+ };
6558
+ var distance = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
6559
+ var interpolate = (a, b, progress) => [
6560
+ a[0] + (b[0] - a[0]) * progress,
6561
+ a[1] + (b[1] - a[1]) * progress,
6562
+ a[2] + (b[2] - a[2]) * progress
6563
+ ];
6564
+ var getPathDistances = (points) => {
6565
+ const distances = [0];
6566
+ for (let index = 1; index < points.length; index += 1) {
6567
+ distances.push(
6568
+ distances[index - 1] + distance(points[index - 1], points[index])
6569
+ );
6570
+ }
6571
+ return distances;
6572
+ };
6573
+ var pointAtDistance = (points, distances, targetDistance) => {
6574
+ if (targetDistance <= 0) return points[0];
6575
+ const totalLength = distances.at(-1);
6576
+ if (targetDistance >= totalLength) return points.at(-1);
6577
+ for (let index = 1; index < points.length; index += 1) {
6578
+ if (distances[index] >= targetDistance) {
6579
+ const segmentStart = distances[index - 1];
6580
+ const segmentLength = distances[index] - segmentStart;
6581
+ return interpolate(
6582
+ points[index - 1],
6583
+ points[index],
6584
+ (targetDistance - segmentStart) / segmentLength
6585
+ );
6586
+ }
6587
+ }
6588
+ return points.at(-1);
6589
+ };
6590
+ var slicePath = (points, startDistance, endDistance) => {
6591
+ const distances = getPathDistances(points);
6592
+ const totalLength = distances.at(-1);
6593
+ const safeStart = Math.max(0, Math.min(startDistance, totalLength));
6594
+ const safeEnd = Math.max(safeStart, Math.min(endDistance, totalLength));
6595
+ const result = [pointAtDistance(points, distances, safeStart)];
6596
+ for (let index = 1; index < points.length - 1; index += 1) {
6597
+ if (distances[index] > safeStart && distances[index] < safeEnd) {
6598
+ result.push(points[index]);
6599
+ }
6600
+ }
6601
+ result.push(pointAtDistance(points, distances, safeEnd));
6602
+ return result;
6603
+ };
6604
+ var createFlatPath = (start, flexCableLength) => [
6605
+ start,
6606
+ [start[0], start[1] + flexCableLength, start[2]]
6607
+ ];
6608
+ var createFoldedPath = ({
6609
+ start,
6610
+ endZ,
6611
+ flexCableLength,
6612
+ foldDistanceFromConnector,
6613
+ foldOutset,
6614
+ foldSegments
6615
+ }) => {
6616
+ const points = [start];
6617
+ const foldStart = [
6618
+ start[0],
6619
+ start[1] + foldDistanceFromConnector,
6620
+ start[2]
6621
+ ];
6622
+ if (foldDistanceFromConnector > EPSILON) points.push(foldStart);
6623
+ for (let index = 1; index <= foldSegments; index += 1) {
6624
+ const angle = Math.PI * index / foldSegments;
6625
+ points.push([
6626
+ start[0],
6627
+ foldStart[1] + foldOutset * Math.sin(angle),
6628
+ start[2] + (endZ - start[2]) * (1 - Math.cos(angle)) / 2
6629
+ ]);
6630
+ }
6631
+ const minimumLength = getPathDistances(points).at(-1);
6632
+ if (minimumLength > flexCableLength + EPSILON) {
6633
+ throw new Error(
6634
+ `flexCableLength must be at least ${minimumLength.toFixed(2)} for this 180-degree fold`
6635
+ );
6636
+ }
6637
+ const tailLength = Math.max(0, flexCableLength - minimumLength);
6638
+ if (tailLength > EPSILON) {
6639
+ const foldEnd = points.at(-1);
6640
+ points.push([foldEnd[0], foldEnd[1] - tailLength, foldEnd[2]]);
6641
+ }
6642
+ return points;
6643
+ };
6644
+ var createRightAnglePath = ({
6645
+ start,
6646
+ flexCableLength,
6647
+ bendRadius,
6648
+ bendSegments,
6649
+ verticalLead,
6650
+ direction
6651
+ }) => {
6652
+ const bendLengthPerRadius = 2 * bendSegments * Math.sin(Math.PI / (4 * bendSegments));
6653
+ const resolvedRadius = Math.min(
6654
+ bendRadius,
6655
+ flexCableLength / bendLengthPerRadius
6656
+ );
6657
+ const bendLength = resolvedRadius * bendLengthPerRadius;
6658
+ const remainingLength = Math.max(0, flexCableLength - bendLength);
6659
+ const resolvedVerticalLead = Math.min(verticalLead, remainingLength * 0.45);
6660
+ const horizontalLength = remainingLength - resolvedVerticalLead;
6661
+ const points = [start];
6662
+ if (horizontalLength > EPSILON) {
6663
+ points.push([start[0], start[1] + horizontalLength, start[2]]);
6664
+ }
6665
+ for (let index = 1; index <= bendSegments; index += 1) {
6666
+ const angle = Math.PI / 2 * index / bendSegments;
6667
+ points.push([
6668
+ start[0],
6669
+ start[1] + horizontalLength + resolvedRadius * Math.sin(angle),
6670
+ start[2] + direction * resolvedRadius * (1 - Math.cos(angle))
6671
+ ]);
6672
+ }
6673
+ if (resolvedVerticalLead > EPSILON) {
6674
+ const arcEnd = points.at(-1);
6675
+ points.push([
6676
+ arcEnd[0],
6677
+ arcEnd[1],
6678
+ arcEnd[2] + direction * resolvedVerticalLead
6679
+ ]);
6680
+ }
6681
+ return points;
6682
+ };
6683
+ var CableStrip = ({
6684
+ points,
6685
+ width: width10,
6686
+ thickness,
6687
+ color,
6688
+ acrossOffset = 0,
6689
+ normalOffset = 0,
6690
+ overlap = 0.03
6691
+ }) => /* @__PURE__ */ jsx(Colorize, { color, children: points.slice(1).map((point, index) => {
6692
+ const previous = points[index];
6693
+ const dx = point[0] - previous[0];
6694
+ const dy = point[1] - previous[1];
6695
+ const dz = point[2] - previous[2];
6696
+ const segmentLength = Math.hypot(dx, dy, dz);
6697
+ if (segmentLength < EPSILON) return null;
6698
+ const pitch = Math.asin(dz / segmentLength);
6699
+ const yaw = Math.atan2(-dx, dy);
6700
+ const midpoint = [
6701
+ (previous[0] + point[0]) / 2,
6702
+ (previous[1] + point[1]) / 2,
6703
+ (previous[2] + point[2]) / 2
6704
+ ];
6705
+ const roundRadius = Math.max(
6706
+ 1e-3,
6707
+ Math.min(width10, thickness, segmentLength) / 2 - 1e-3
6708
+ );
6709
+ return /* @__PURE__ */ jsx(Translate, { offset: midpoint, children: /* @__PURE__ */ jsx(Rotate, { rotation: [pitch, 0, yaw], children: /* @__PURE__ */ jsx(
6710
+ RoundedCuboid,
6711
+ {
6712
+ size: [width10, segmentLength + overlap, thickness],
6713
+ center: [acrossOffset, 0, normalOffset],
6714
+ roundRadius
6715
+ }
6716
+ ) }) }, `${index}:${midpoint.join(":")}`);
6717
+ }) });
6718
+ var FlexScreen = (props) => {
6719
+ const {
6720
+ width: width10,
6721
+ height: height10,
6722
+ diagonal,
6723
+ aspectRatio,
6724
+ ratio,
6725
+ defaultDiagonal,
6726
+ screenThickness = 1.2,
6727
+ bezelInset = 2,
6728
+ bezelDepth = 0.65,
6729
+ activeAreaWidth,
6730
+ activeAreaHeight,
6731
+ screenColor = "#071b24",
6732
+ bezelColor = "#15181d",
6733
+ showScreen = true,
6734
+ flexCableLength = 28,
6735
+ flexCableThickness = 0.18,
6736
+ flexCableColor = "#d79528",
6737
+ conductorCount = 8,
6738
+ conductorPitch,
6739
+ conductorWidth,
6740
+ conductorThickness = 0.035,
6741
+ conductorColor = "#8c4a18",
6742
+ cableEdgeMargin = 0.6,
6743
+ exposedContactLength = 2.4,
6744
+ showConductors = true,
6745
+ showFlexCable = true,
6746
+ showStiffeners = true,
6747
+ stiffenerLength = 3,
6748
+ stiffenerThickness = 0.16,
6749
+ stiffenerColor = "#416bb3",
6750
+ bendRadius = 3,
6751
+ bendSegments = 10,
6752
+ rightAngleVerticalLead = 3,
6753
+ distanceAboveBoard = 7,
6754
+ distanceBelowBoard = 7,
6755
+ foldDistanceFromConnector = 7,
6756
+ foldOutset = 4,
6757
+ foldSegments = 18,
6758
+ screenGap = 0.08,
6759
+ boardTopZ = 0,
6760
+ boardThickness = 1.6,
6761
+ boardClearance = 0.15,
6762
+ cableStartX = 0,
6763
+ cableStartY = 0,
6764
+ cableStartZ,
6765
+ cableLateralOffset = 0,
6766
+ screenOffset,
6767
+ screenRotation,
6768
+ rotation = [0, 0, 0],
6769
+ offset
6770
+ } = props;
6771
+ const size = resolveFlexScreenSize({
6772
+ width: width10,
6773
+ height: height10,
6774
+ diagonal,
6775
+ aspectRatio,
6776
+ ratio,
6777
+ defaultDiagonal
6778
+ });
6779
+ const orientation = resolveOrientation(props);
6780
+ const belowBoard = orientation === "sitsFlatBelowBoard" || orientation === "foldedToFaceBelowBoard" || orientation === "foldedToRightAngleBelowBoard";
6781
+ const foldedFace = orientation === "foldedToFaceAboveBoard" || orientation === "foldedToFaceBelowBoard";
6782
+ const rightAngle = orientation === "foldedToRightAngleAboveBoard" || orientation === "foldedToRightAngleBelowBoard";
6783
+ assertPositive("screenThickness", screenThickness);
6784
+ assertPositive("flexCableLength", flexCableLength);
6785
+ assertPositive("flexCableThickness", flexCableThickness);
6786
+ assertPositive("conductorThickness", conductorThickness);
6787
+ assertPositive("bendRadius", bendRadius);
6788
+ assertPositive("foldOutset", foldOutset);
6789
+ assertPositive("boardThickness", boardThickness);
6790
+ if (showStiffeners) assertPositive("stiffenerThickness", stiffenerThickness);
6791
+ if (!Number.isInteger(conductorCount) || conductorCount < 1) {
6792
+ throw new Error("conductorCount must be a positive integer");
6793
+ }
6794
+ if (!Number.isInteger(bendSegments) || bendSegments < 2) {
6795
+ throw new Error("bendSegments must be an integer of at least 2");
6796
+ }
6797
+ if (!Number.isInteger(foldSegments) || foldSegments < 4) {
6798
+ throw new Error("foldSegments must be an integer of at least 4");
6799
+ }
6800
+ if (boardClearance < 0 || screenGap < 0 || cableEdgeMargin < 0 || exposedContactLength < 0 || stiffenerLength < 0 || rightAngleVerticalLead < 0 || distanceAboveBoard < 0 || distanceBelowBoard < 0 || foldDistanceFromConnector < 0) {
6801
+ throw new Error(
6802
+ "clearances, margins, contact lengths, and lead lengths cannot be negative"
6803
+ );
6804
+ }
6805
+ const resolvedCableWidth = props.flexCableWidth ?? Math.min(12, Math.max(5, size.width * 0.3));
6806
+ assertPositive("flexCableWidth", resolvedCableWidth);
6807
+ const usableCableWidth = resolvedCableWidth - cableEdgeMargin * 2;
6808
+ if (usableCableWidth <= 0) {
6809
+ throw new Error("cableEdgeMargin leaves no usable flex cable width");
6810
+ }
6811
+ const resolvedConductorPitch = conductorPitch ?? (conductorCount === 1 ? 0 : usableCableWidth / conductorCount);
6812
+ if (conductorCount > 1 && (!Number.isFinite(resolvedConductorPitch) || resolvedConductorPitch <= 0)) {
6813
+ throw new Error("conductorPitch must be greater than zero");
6814
+ }
6815
+ const resolvedConductorWidth = conductorWidth ?? (conductorCount === 1 ? Math.min(usableCableWidth, resolvedCableWidth * 0.45) : resolvedConductorPitch * 0.48);
6816
+ assertPositive("conductorWidth", resolvedConductorWidth);
6817
+ const conductorSpan = (conductorCount - 1) * resolvedConductorPitch + resolvedConductorWidth;
6818
+ if (conductorSpan > usableCableWidth + EPSILON) {
6819
+ throw new Error(
6820
+ "conductorPitch and conductorWidth do not fit inside the flex cable margins"
6821
+ );
6822
+ }
6823
+ const cableStartsBelowBoard = belowBoard && !foldedFace;
6824
+ const defaultCableZ = cableStartsBelowBoard ? boardTopZ - boardThickness - boardClearance - flexCableThickness / 2 : boardTopZ + boardClearance + flexCableThickness / 2;
6825
+ const start = [
6826
+ cableStartX + cableLateralOffset,
6827
+ cableStartY,
6828
+ cableStartZ ?? defaultCableZ
6829
+ ];
6830
+ const direction = belowBoard ? -1 : 1;
6831
+ const foldedScreenBackZ = orientation === "foldedToFaceAboveBoard" ? boardTopZ + distanceAboveBoard : boardTopZ - boardThickness - distanceBelowBoard;
6832
+ const foldedCableEndZ = orientation === "foldedToFaceAboveBoard" ? foldedScreenBackZ - screenGap - flexCableThickness / 2 : foldedScreenBackZ + screenGap + flexCableThickness / 2;
6833
+ const path = foldedFace ? createFoldedPath({
6834
+ start,
6835
+ endZ: foldedCableEndZ,
6836
+ flexCableLength,
6837
+ foldDistanceFromConnector,
6838
+ foldOutset,
6839
+ foldSegments
6840
+ }) : rightAngle ? createRightAnglePath({
6841
+ start,
6842
+ flexCableLength,
6843
+ bendRadius,
6844
+ bendSegments,
6845
+ verticalLead: rightAngleVerticalLead,
6846
+ direction
6847
+ }) : createFlatPath(start, flexCableLength);
6848
+ const totalCableLength = getPathDistances(path).at(-1);
6849
+ const contactLength = Math.min(
6850
+ Math.max(0, exposedContactLength),
6851
+ totalCableLength / 2
6852
+ );
6853
+ const resolvedStiffenerLength = Math.min(
6854
+ Math.max(0, stiffenerLength),
6855
+ totalCableLength / 2
6856
+ );
6857
+ const startContacts = slicePath(path, 0, contactLength);
6858
+ const endContacts = slicePath(
6859
+ path,
6860
+ totalCableLength - contactLength,
6861
+ totalCableLength
6862
+ );
6863
+ const startStiffener = slicePath(path, 0, resolvedStiffenerLength);
6864
+ const endStiffener = slicePath(
6865
+ path,
6866
+ totalCableLength - resolvedStiffenerLength,
6867
+ totalCableLength
6868
+ );
6869
+ const pathEnd = path.at(-1);
6870
+ let presetScreenRotation;
6871
+ let screenCenter;
6872
+ if (orientation === "sitsFlat") {
6873
+ presetScreenRotation = [0, 0, 0];
6874
+ screenCenter = [
6875
+ pathEnd[0],
6876
+ pathEnd[1] + size.height / 2,
6877
+ pathEnd[2] + flexCableThickness / 2 + screenGap
6878
+ ];
6879
+ } else if (orientation === "sitsFlatBelowBoard") {
6880
+ presetScreenRotation = [0, Math.PI, 0];
6881
+ screenCenter = [
6882
+ pathEnd[0],
6883
+ pathEnd[1] + size.height / 2,
6884
+ pathEnd[2] - flexCableThickness / 2 - screenGap
6885
+ ];
6886
+ } else if (orientation === "foldedToFaceAboveBoard") {
6887
+ presetScreenRotation = [0, 0, 0];
6888
+ screenCenter = [pathEnd[0], pathEnd[1] - size.height / 2, foldedScreenBackZ];
6889
+ } else if (orientation === "foldedToFaceBelowBoard") {
6890
+ presetScreenRotation = [0, Math.PI, 0];
6891
+ screenCenter = [pathEnd[0], pathEnd[1] - size.height / 2, foldedScreenBackZ];
6892
+ } else if (orientation === "foldedToRightAngleAboveBoard") {
6893
+ presetScreenRotation = [Math.PI / 2, 0, 0];
6894
+ screenCenter = [
6895
+ pathEnd[0],
6896
+ pathEnd[1] - flexCableThickness / 2 - screenGap,
6897
+ pathEnd[2] + size.height / 2
6898
+ ];
6899
+ } else {
6900
+ presetScreenRotation = [-Math.PI / 2, 0, 0];
6901
+ screenCenter = [
6902
+ pathEnd[0],
6903
+ pathEnd[1] + flexCableThickness / 2 + screenGap,
6904
+ pathEnd[2] - size.height / 2
6905
+ ];
6906
+ }
6907
+ screenCenter = [
6908
+ screenCenter[0] + (screenOffset?.x ?? 0),
6909
+ screenCenter[1] + (screenOffset?.y ?? 0),
6910
+ screenCenter[2] + (screenOffset?.z ?? 0)
6911
+ ];
6912
+ const conductorOffsets = Array.from(
6913
+ { length: conductorCount },
6914
+ (_, index) => conductorCount === 1 ? 0 : (index - (conductorCount - 1) / 2) * resolvedConductorPitch
6915
+ );
6916
+ const conductorNormalOffset = (flexCableThickness + conductorThickness) / 2;
6917
+ const stiffenerNormalOffset = -(flexCableThickness + stiffenerThickness) / 2;
6918
+ const assembly = /* @__PURE__ */ jsxs(Fragment2, { children: [
6919
+ showFlexCable && /* @__PURE__ */ jsx(
6920
+ CableStrip,
6921
+ {
6922
+ points: path,
6923
+ width: resolvedCableWidth,
6924
+ thickness: flexCableThickness,
6925
+ color: flexCableColor
6926
+ }
6927
+ ),
6928
+ showFlexCable && showStiffeners && resolvedStiffenerLength > EPSILON && /* @__PURE__ */ jsxs(Fragment2, { children: [
6929
+ /* @__PURE__ */ jsx(
6930
+ CableStrip,
6931
+ {
6932
+ points: startStiffener,
6933
+ width: resolvedCableWidth,
6934
+ thickness: stiffenerThickness,
6935
+ color: stiffenerColor,
6936
+ normalOffset: stiffenerNormalOffset
6937
+ }
6938
+ ),
6939
+ /* @__PURE__ */ jsx(
6940
+ CableStrip,
6941
+ {
6942
+ points: endStiffener,
6943
+ width: resolvedCableWidth,
6944
+ thickness: stiffenerThickness,
6945
+ color: stiffenerColor,
6946
+ normalOffset: stiffenerNormalOffset
6947
+ }
6948
+ )
6949
+ ] }),
6950
+ showFlexCable && showConductors && contactLength > EPSILON && conductorOffsets.map((acrossOffset, index) => /* @__PURE__ */ jsxs(Fragment2, { children: [
6951
+ /* @__PURE__ */ jsx(
6952
+ CableStrip,
6953
+ {
6954
+ points: startContacts,
6955
+ width: resolvedConductorWidth,
6956
+ thickness: conductorThickness,
6957
+ color: conductorColor,
6958
+ acrossOffset,
6959
+ normalOffset: conductorNormalOffset
6960
+ }
6961
+ ),
6962
+ /* @__PURE__ */ jsx(
6963
+ CableStrip,
6964
+ {
6965
+ points: endContacts,
6966
+ width: resolvedConductorWidth,
6967
+ thickness: conductorThickness,
6968
+ color: conductorColor,
6969
+ acrossOffset,
6970
+ normalOffset: conductorNormalOffset
6971
+ }
6972
+ )
6973
+ ] }, `conductor:${index}`)),
6974
+ showScreen && /* @__PURE__ */ jsx(Translate, { offset: screenCenter, children: /* @__PURE__ */ jsx(Rotate, { rotation: screenRotation ?? presetScreenRotation, children: /* @__PURE__ */ jsx(
6975
+ Screen,
6976
+ {
6977
+ width: size.width,
6978
+ height: size.height,
6979
+ thickness: screenThickness,
6980
+ bezelInset,
6981
+ bezelDepth,
6982
+ screenWidth: activeAreaWidth,
6983
+ screenHeight: activeAreaHeight,
6984
+ screenColor,
6985
+ bezelColor
6986
+ }
6987
+ ) }) })
6988
+ ] });
6989
+ return /* @__PURE__ */ jsx(
6990
+ Translate,
6991
+ {
6992
+ offset: {
6993
+ x: offset?.x ?? 0,
6994
+ y: offset?.y ?? 0,
6995
+ z: offset?.z ?? 0
6996
+ },
6997
+ children: /* @__PURE__ */ jsx(Translate, { offset: start, children: /* @__PURE__ */ jsx(Rotate, { rotation, children: /* @__PURE__ */ jsx(Translate, { offset: [-start[0], -start[1], -start[2]], children: assembly }) }) })
6998
+ }
6999
+ );
7000
+ };
7001
+
6462
7002
  // lib/Footprinter3d.tsx
6463
7003
  var Footprinter3d = ({ footprint }) => {
7004
+ const modelFn = mp.string(footprint.split("_", 1)[0]).params().fn;
7005
+ if (mp.getModelNames().includes(modelFn)) {
7006
+ const model = mp.string(footprint).json();
7007
+ switch (model.fn) {
7008
+ case "flexscreen": {
7009
+ const { fn: _, ...flexScreenProps } = model;
7010
+ return /* @__PURE__ */ jsx(FlexScreen, { ...flexScreenProps });
7011
+ }
7012
+ }
7013
+ }
6464
7014
  let normalizedFootprint = footprint;
6465
7015
  if (footprint.startsWith("jstzh1_5mm")) {
6466
7016
  const pinMatch = footprint.match(/jstzh1_5mm(\d+)?/);
@@ -6589,7 +7139,6 @@ var Footprinter3d = ({ footprint }) => {
6589
7139
  numberOfPins: fpJson.num_pins,
6590
7140
  pitch: fpJson.p,
6591
7141
  invert: fpJson.invert,
6592
- faceup: fpJson.faceup,
6593
7142
  rows,
6594
7143
  smd: fpJson.smd || fpJson.surface_mount,
6595
7144
  rightangle: fpJson.rightangle