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/index.js CHANGED
@@ -758,7 +758,8 @@ var ExtrudedPads = ({
758
758
 
759
759
  // lib/Footprinter3d.tsx
760
760
  import { fp as fp5 } from "@tscircuit/footprinter";
761
- import { Rotate as Rotate18, Translate as Translate38 } from "jscad-fiber";
761
+ import { mp } from "@tscircuit/modelprinter";
762
+ import { Rotate as Rotate19, Translate as Translate39 } from "jscad-fiber";
762
763
 
763
764
  // lib/DualInlinePackage.tsx
764
765
  import { Polygon as Polygon3, ExtrudeLinear as ExtrudeLinear3, Rotate as Rotate3, Translate as Translate6 } from "jscad-fiber";
@@ -1274,7 +1275,6 @@ var PinHeader = ({
1274
1275
  bodyLength: bodyLength10 = 2.54,
1275
1276
  bodyWidth = 2.54,
1276
1277
  flipZ,
1277
- faceup,
1278
1278
  smd,
1279
1279
  rightangle
1280
1280
  }) => {
@@ -1287,7 +1287,7 @@ var PinHeader = ({
1287
1287
  center: [x, y, flipZ(bodyHeight / 2)]
1288
1288
  }
1289
1289
  ) }),
1290
- !faceup && /* @__PURE__ */ jsx21(Colorize7, { color: PIN_METAL_COLOR, children: smd ? /* @__PURE__ */ jsx21(
1290
+ /* @__PURE__ */ jsx21(Colorize7, { color: PIN_METAL_COLOR, children: smd ? /* @__PURE__ */ jsx21(
1291
1291
  SmdChipLead,
1292
1292
  {
1293
1293
  rotation: -Math.PI / 2,
@@ -1356,7 +1356,6 @@ var PinRow = ({
1356
1356
  pitch = 2.54,
1357
1357
  longSidePinLength = 6,
1358
1358
  invert,
1359
- faceup,
1360
1359
  rows = 1,
1361
1360
  smd,
1362
1361
  rightangle
@@ -1367,8 +1366,9 @@ var PinRow = ({
1367
1366
  const rowSpacing = 2.54;
1368
1367
  const shortSidePinLength = 3;
1369
1368
  const xoff = -((pinsPerRow - 1) / 2) * pitch;
1370
- const zOffset = !smd && !rightangle ? -bodyHeight - 1.6 : 0;
1371
- const flipZ = (z) => (invert || faceup ? -z + bodyHeight : z) + zOffset;
1369
+ const throughHole = !smd && !rightangle;
1370
+ const flipped = throughHole ? !invert : Boolean(invert);
1371
+ const flipZ = (z) => flipped ? -z + bodyHeight : z;
1372
1372
  return /* @__PURE__ */ jsx22(Fragment18, { children: Array.from({ length: numberOfPins }, (_, i) => {
1373
1373
  const row = Math.floor(i / pinsPerRow);
1374
1374
  const col = i % pinsPerRow;
@@ -1384,7 +1384,6 @@ var PinRow = ({
1384
1384
  longSidePinLength,
1385
1385
  bodyHeight,
1386
1386
  flipZ,
1387
- faceup,
1388
1387
  smd,
1389
1388
  rightangle
1390
1389
  },
@@ -6671,1187 +6670,1196 @@ var SOT563 = ({ fullWidth = 1.94, fullLength: fullLength10 = 1.6 }) => {
6671
6670
  ] });
6672
6671
  };
6673
6672
 
6674
- // lib/Footprinter3d.tsx
6675
- import { Fragment as Fragment79, jsx as jsx84 } from "react/jsx-runtime";
6676
- var Footprinter3d = ({ footprint }) => {
6677
- let normalizedFootprint = footprint;
6678
- if (footprint.startsWith("jstzh1_5mm")) {
6679
- const pinMatch = footprint.match(/jstzh1_5mm(\d+)?/);
6680
- const numPins = pinMatch && pinMatch[1] ? pinMatch[1] : "7";
6681
- normalizedFootprint = `zh${numPins}`;
6682
- } else if (footprint.startsWith("jstph2_0mm")) {
6683
- const pinMatch = footprint.match(/jstph2_0mm(\d+)?/);
6684
- const numPins = pinMatch && pinMatch[1] ? pinMatch[1] : "2";
6685
- normalizedFootprint = `jst${numPins}_ph`;
6673
+ // lib/FlexScreen.tsx
6674
+ import { Colorize as Colorize49, Rotate as Rotate18, RoundedCuboid as RoundedCuboid5, Translate as Translate38 } from "jscad-fiber";
6675
+ import { Fragment as Fragment79 } from "react";
6676
+ import { Fragment as Fragment80, jsx as jsx84, jsxs as jsxs80 } from "react/jsx-runtime";
6677
+ var DEFAULT_ASPECT_RATIO = 16 / 9;
6678
+ var DEFAULT_DIAGONAL = 40;
6679
+ var EPSILON = 1e-6;
6680
+ var assertPositive = (name, value) => {
6681
+ if (!Number.isFinite(value) || value <= 0) {
6682
+ throw new Error(`${name} must be a finite number greater than zero`);
6686
6683
  }
6687
- const fpJson = fp5.string(normalizedFootprint).json();
6688
- const colorMatch = footprint.match(/_color\(([^)]+)\)/);
6689
- const color = colorMatch ? colorMatch[1] : void 0;
6690
- const dim = (value, fallback) => {
6691
- if (value === void 0 || value === null) return fallback;
6692
- const parsed = mm(value);
6693
- return Number.isFinite(parsed) ? parsed : fallback;
6684
+ };
6685
+ var resolveAspectRatio = (value) => {
6686
+ if (value === void 0) return DEFAULT_ASPECT_RATIO;
6687
+ if (typeof value === "number") {
6688
+ assertPositive("aspectRatio", value);
6689
+ return value;
6690
+ }
6691
+ if (typeof value !== "string") {
6692
+ const [ratioWidth2, ratioHeight2] = value;
6693
+ assertPositive("aspectRatio width", ratioWidth2);
6694
+ assertPositive("aspectRatio height", ratioHeight2);
6695
+ return ratioWidth2 / ratioHeight2;
6696
+ }
6697
+ const parts = value.split(":");
6698
+ if (parts.length !== 2) {
6699
+ throw new Error('aspectRatio must look like "16:9"');
6700
+ }
6701
+ const ratioWidth = Number(parts[0]);
6702
+ const ratioHeight = Number(parts[1]);
6703
+ assertPositive("aspectRatio width", ratioWidth);
6704
+ assertPositive("aspectRatio height", ratioHeight);
6705
+ return ratioWidth / ratioHeight;
6706
+ };
6707
+ var resolveFlexScreenSize = ({
6708
+ width: width10,
6709
+ height: height10,
6710
+ diagonal,
6711
+ aspectRatio,
6712
+ ratio,
6713
+ defaultDiagonal = DEFAULT_DIAGONAL
6714
+ }) => {
6715
+ const resolvedRatio = resolveAspectRatio(aspectRatio ?? ratio);
6716
+ if (width10 !== void 0) assertPositive("width", width10);
6717
+ if (height10 !== void 0) assertPositive("height", height10);
6718
+ if (diagonal !== void 0) assertPositive("diagonal", diagonal);
6719
+ assertPositive("defaultDiagonal", defaultDiagonal);
6720
+ let resolvedWidth;
6721
+ let resolvedHeight;
6722
+ if (width10 !== void 0 && height10 !== void 0) {
6723
+ resolvedWidth = width10;
6724
+ resolvedHeight = height10;
6725
+ } else if (diagonal !== void 0 && width10 !== void 0) {
6726
+ if (width10 >= diagonal) {
6727
+ throw new Error("width must be smaller than diagonal");
6728
+ }
6729
+ resolvedWidth = width10;
6730
+ resolvedHeight = Math.sqrt(diagonal ** 2 - width10 ** 2);
6731
+ } else if (diagonal !== void 0 && height10 !== void 0) {
6732
+ if (height10 >= diagonal) {
6733
+ throw new Error("height must be smaller than diagonal");
6734
+ }
6735
+ resolvedWidth = Math.sqrt(diagonal ** 2 - height10 ** 2);
6736
+ resolvedHeight = height10;
6737
+ } else if (width10 !== void 0) {
6738
+ resolvedWidth = width10;
6739
+ resolvedHeight = width10 / resolvedRatio;
6740
+ } else if (height10 !== void 0) {
6741
+ resolvedWidth = height10 * resolvedRatio;
6742
+ resolvedHeight = height10;
6743
+ } else {
6744
+ const resolvedDiagonal = diagonal ?? defaultDiagonal;
6745
+ resolvedHeight = resolvedDiagonal / Math.sqrt(resolvedRatio ** 2 + 1);
6746
+ resolvedWidth = resolvedHeight * resolvedRatio;
6747
+ }
6748
+ return {
6749
+ width: resolvedWidth,
6750
+ height: resolvedHeight,
6751
+ diagonal: Math.hypot(resolvedWidth, resolvedHeight),
6752
+ aspectRatio: resolvedWidth / resolvedHeight
6694
6753
  };
6695
- switch (fpJson.fn) {
6696
- case "crystal":
6697
- return /* @__PURE__ */ jsx84(
6698
- Crystal,
6699
- {
6700
- horizontalPadPitch: fpJson.px,
6701
- verticalPadPitch: fpJson.py,
6702
- padWidth: fpJson.pw,
6703
- padHeight: fpJson.ph
6704
- }
6705
- );
6706
- case "dip":
6707
- return /* @__PURE__ */ jsx84(Dip, { numPins: fpJson.num_pins, pitch: fpJson.p, bodyWidth: fpJson.w });
6708
- case "axial":
6709
- return /* @__PURE__ */ jsx84(AxialCapacitor, { pitch: fpJson.p });
6710
- case "tssop":
6711
- return /* @__PURE__ */ jsx84(
6712
- Tssop,
6713
- {
6714
- pinCount: fpJson.num_pins,
6715
- leadLength: fpJson.pl,
6716
- leadWidth: fpJson.pw,
6717
- pitch: fpJson.p,
6718
- bodyWidth: fpJson.w
6719
- }
6720
- );
6721
- case "msop":
6722
- return /* @__PURE__ */ jsx84(
6723
- MSOP,
6724
- {
6725
- pinCount: fpJson.num_pins,
6726
- padContactLength: fpJson.pl,
6727
- leadWidth: fpJson.pw,
6728
- pitch: fpJson.p,
6729
- bodyWidth: fpJson.w
6730
- }
6731
- );
6732
- case "vssop":
6733
- return /* @__PURE__ */ jsx84(
6734
- VSSOP,
6735
- {
6736
- pinCount: fpJson.num_pins,
6737
- leadLength: fpJson.pl,
6738
- leadWidth: fpJson.pw,
6739
- pitch: fpJson.p,
6740
- bodyWidth: fpJson.w,
6741
- bodyLength: fpJson.h
6742
- }
6743
- );
6744
- case "qfp":
6745
- return /* @__PURE__ */ jsx84(
6746
- QFP,
6747
- {
6748
- pinCount: fpJson.num_pins,
6749
- pitch: fpJson.p,
6750
- leadWidth: fpJson.pw,
6751
- padContactLength: fpJson.pl,
6752
- bodyWidth: fpJson.w
6753
- }
6754
- );
6755
- case "tqfp":
6756
- return /* @__PURE__ */ jsx84(tqfp_default, {});
6757
- case "lqfp":
6758
- return /* @__PURE__ */ jsx84(LQFP, { pinCount: fpJson.num_pins });
6759
- case "qfn": {
6760
- const hasThermalPad = typeof fpJson.thermalpad?.x === "number" && typeof fpJson.thermalpad?.y === "number";
6761
- return /* @__PURE__ */ jsx84(
6762
- qfn_default,
6763
- {
6764
- num_pins: fpJson.num_pins,
6765
- bodyWidth: fpJson.w,
6766
- bodyLength: fpJson.h,
6767
- pitch: fpJson.p,
6768
- padLength: fpJson.pl,
6769
- padWidth: fpJson.pw,
6770
- thermalPadSize: hasThermalPad ? {
6771
- width: fpJson.thermalpad.x,
6772
- length: fpJson.thermalpad.y
6773
- } : void 0
6774
- }
6754
+ };
6755
+ var resolveOrientation = (props) => {
6756
+ const shortcuts = [
6757
+ ["sitsFlat", props.sitsFlat],
6758
+ ["sitsFlatBelowBoard", props.sitsFlatBelowBoard],
6759
+ ["foldedToFaceAboveBoard", props.foldedToFaceAboveBoard],
6760
+ ["foldedToFaceBelowBoard", props.foldedToFaceBelowBoard],
6761
+ ["foldedToFaceAboveBoard", props.foldsAboveBoard],
6762
+ ["foldedToFaceBelowBoard", props.foldsBelowBoard],
6763
+ ["foldedToRightAngleAboveBoard", props.foldedToRightAngleAboveBoard],
6764
+ ["foldedToRightAngleBelowBoard", props.foldedToRightAngleBelowBoard]
6765
+ ].filter((entry) => entry[1]);
6766
+ if (shortcuts.length > 1) {
6767
+ throw new Error(
6768
+ "Only one FlexScreen boolean orientation shortcut can be true"
6769
+ );
6770
+ }
6771
+ return shortcuts[0]?.[0] ?? props.orientation ?? "sitsFlat";
6772
+ };
6773
+ var distance = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
6774
+ var interpolate = (a, b, progress) => [
6775
+ a[0] + (b[0] - a[0]) * progress,
6776
+ a[1] + (b[1] - a[1]) * progress,
6777
+ a[2] + (b[2] - a[2]) * progress
6778
+ ];
6779
+ var getPathDistances = (points) => {
6780
+ const distances = [0];
6781
+ for (let index = 1; index < points.length; index += 1) {
6782
+ distances.push(
6783
+ distances[index - 1] + distance(points[index - 1], points[index])
6784
+ );
6785
+ }
6786
+ return distances;
6787
+ };
6788
+ var pointAtDistance = (points, distances, targetDistance) => {
6789
+ if (targetDistance <= 0) return points[0];
6790
+ const totalLength = distances.at(-1);
6791
+ if (targetDistance >= totalLength) return points.at(-1);
6792
+ for (let index = 1; index < points.length; index += 1) {
6793
+ if (distances[index] >= targetDistance) {
6794
+ const segmentStart = distances[index - 1];
6795
+ const segmentLength = distances[index] - segmentStart;
6796
+ return interpolate(
6797
+ points[index - 1],
6798
+ points[index],
6799
+ (targetDistance - segmentStart) / segmentLength
6775
6800
  );
6776
6801
  }
6777
- case "dfn": {
6778
- const hasThermalPad = typeof fpJson.thermalpad?.x === "number" && typeof fpJson.thermalpad?.y === "number";
6779
- return /* @__PURE__ */ jsx84(
6780
- DFN,
6781
- {
6782
- num_pins: fpJson.num_pins,
6783
- bodyWidth: fpJson.w,
6784
- bodyLength: fpJson.h,
6785
- pitch: fpJson.p,
6786
- padLength: fpJson.pl,
6787
- padWidth: fpJson.pw,
6788
- thermalPadSize: hasThermalPad ? {
6789
- width: fpJson.thermalpad.x,
6790
- length: fpJson.thermalpad.y
6791
- } : void 0
6792
- }
6793
- );
6802
+ }
6803
+ return points.at(-1);
6804
+ };
6805
+ var slicePath = (points, startDistance, endDistance) => {
6806
+ const distances = getPathDistances(points);
6807
+ const totalLength = distances.at(-1);
6808
+ const safeStart = Math.max(0, Math.min(startDistance, totalLength));
6809
+ const safeEnd = Math.max(safeStart, Math.min(endDistance, totalLength));
6810
+ const result = [pointAtDistance(points, distances, safeStart)];
6811
+ for (let index = 1; index < points.length - 1; index += 1) {
6812
+ if (distances[index] > safeStart && distances[index] < safeEnd) {
6813
+ result.push(points[index]);
6794
6814
  }
6795
- case "pinrow": {
6796
- const rowsMatch = footprint.match(/_rows(\d+)/);
6797
- const rows = rowsMatch && rowsMatch[1] ? parseInt(rowsMatch[1], 10) : 1;
6798
- if (fpJson.male)
6799
- return /* @__PURE__ */ jsx84(
6800
- PinRow,
6801
- {
6802
- numberOfPins: fpJson.num_pins,
6803
- pitch: fpJson.p,
6804
- invert: fpJson.invert,
6805
- faceup: fpJson.faceup,
6806
- rows,
6807
- smd: fpJson.smd || fpJson.surface_mount,
6808
- rightangle: fpJson.rightangle
6809
- }
6810
- );
6811
- if (fpJson.female)
6812
- return /* @__PURE__ */ jsx84(
6813
- FemaleHeaderRow,
6814
- {
6815
- numberOfPins: fpJson.num_pins,
6816
- pitch: fpJson.p,
6817
- rows
6818
- }
6819
- );
6820
- }
6821
- case "smdpinheader":
6822
- return /* @__PURE__ */ jsx84(
6823
- SmdPinHeader,
6824
- {
6825
- numberOfPins: fpJson.num_pins,
6826
- pitch: fpJson.p,
6827
- bodyWidth: fpJson.bh
6828
- }
6829
- );
6830
- case "led5050":
6831
- return /* @__PURE__ */ jsx84(Led5050, { color });
6832
- case "cap": {
6833
- switch (fpJson.imperial) {
6834
- case "0402":
6835
- return /* @__PURE__ */ jsx84(A0402, { color: "#856c4d" });
6836
- case "0603":
6837
- return /* @__PURE__ */ jsx84(A0603, { color: "#856c4d" });
6838
- case "0805":
6839
- return /* @__PURE__ */ jsx84(A0805, { color: "#856c4d" });
6840
- case "0201":
6841
- return /* @__PURE__ */ jsx84(A0201, { color: "#856c4d" });
6842
- case "01005":
6843
- return /* @__PURE__ */ jsx84(A01005, { color: "#856c4d" });
6844
- case "1206":
6845
- return /* @__PURE__ */ jsx84(A1206, { color: "#856c4d" });
6846
- case "1210":
6847
- return /* @__PURE__ */ jsx84(A1210, { color: "#856c4d" });
6848
- case "2010":
6849
- return /* @__PURE__ */ jsx84(A2010, { color: "#856c4d" });
6850
- case "2512":
6851
- return /* @__PURE__ */ jsx84(A2512, { color: "#856c4d" });
6852
- }
6853
- break;
6854
- }
6855
- case "sot23":
6856
- switch (fpJson.num_pins) {
6857
- case 3:
6858
- return /* @__PURE__ */ jsx84(SOT233P, { color });
6859
- case 5:
6860
- return /* @__PURE__ */ jsx84(SOT_235_default, {});
6861
- }
6862
- break;
6863
- case "sot25":
6864
- return /* @__PURE__ */ jsx84(SOT_235_default, {});
6865
- case "sot":
6866
- case "sot343": {
6867
- const isSc70 = fpJson.fn === "sot343";
6868
- return /* @__PURE__ */ jsx84(
6869
- GullWingBody,
6870
- {
6871
- pads: getSmtPadRects(normalizedFootprint),
6872
- bodyWidth: isSc70 ? 1.25 : 1.6,
6873
- bodyLength: isSc70 ? 2 : 2.9,
6874
- bodyHeight: isSc70 ? 1.1 : 1.3
6875
- }
6876
- );
6877
- }
6878
- case "sot563":
6879
- return /* @__PURE__ */ jsx84(SOT563, {});
6880
- case "sot89": {
6881
- const padSpan = dim(fpJson.w, 4.2);
6882
- return /* @__PURE__ */ jsx84(
6883
- SOT223,
6884
- {
6885
- fullWidth: padSpan,
6886
- bodyWidth: padSpan * 0.6,
6887
- bodyLength: dim(fpJson.h, 4.8) * 0.94,
6888
- bodyHeight: 1.5,
6889
- leadWidth: dim(fpJson.pw, 0.48),
6890
- tabLeadWidth: dim(fpJson.pw, 0.48) * 2,
6891
- padPitch: dim(fpJson.p, 1.5),
6892
- leadHeight: 0.66
6893
- }
6894
- );
6895
- }
6896
- case "sot457":
6897
- return /* @__PURE__ */ jsx84(SOT457, {});
6898
- case "sot223":
6899
- return /* @__PURE__ */ jsx84(SOT223, {});
6900
- case "sot23w":
6901
- return /* @__PURE__ */ jsx84(SOT23W, {});
6902
- case "sot323":
6903
- return /* @__PURE__ */ jsx84(SOT323, {});
6904
- case "sod323f":
6905
- return /* @__PURE__ */ jsx84(SOD323F, {});
6906
- case "sod323fl":
6907
- return /* @__PURE__ */ jsx84(SOD323FL, {});
6908
- case "sot363":
6909
- return /* @__PURE__ */ jsx84(SOT_363_default, {});
6910
- case "sot886":
6911
- return /* @__PURE__ */ jsx84(SOT886, {});
6912
- case "sot963":
6913
- return /* @__PURE__ */ jsx84(SOT963, {});
6914
- case "pushbutton":
6915
- return /* @__PURE__ */ jsx84(
6916
- PushButton,
6917
- {
6918
- width: fpJson.w,
6919
- length: fpJson.h,
6920
- innerDiameter: fpJson.id
6921
- }
6922
- );
6923
- case "jst":
6924
- if (fpJson.zh) {
6925
- return /* @__PURE__ */ jsx84(JSTZH1_5mm, { numPins: fpJson.num_pins });
6926
- }
6927
- if (fpJson.ph) {
6928
- return /* @__PURE__ */ jsx84(JSTPH2_0mm, { numPins: fpJson.num_pins });
6929
- }
6930
- break;
6931
- case "fpc":
6932
- return /* @__PURE__ */ jsx84(
6933
- FPC,
6934
- {
6935
- pinCount: fpJson.num_pins,
6936
- pitch: fpJson.p,
6937
- padWidth: fpJson.pw,
6938
- padLength: fpJson.pl,
6939
- staggered: fpJson.staggered,
6940
- reverse: fpJson.reverse,
6941
- rowPitch: fpJson.py,
6942
- topPadLength: fpJson.toppl,
6943
- bottomPadLength: fpJson.bottompl,
6944
- mountPadPitchX: fpJson.mpx,
6945
- mountPadOffsetY: fpJson.mpy,
6946
- mountTop: fpJson.mounttop,
6947
- mountPadWidth: fpJson.mpw,
6948
- mountPadLength: fpJson.mpl
6949
- }
6950
- );
6951
- case "rj45":
6952
- return /* @__PURE__ */ jsx84(
6953
- RJ45,
6954
- {
6955
- bodyWidth: fpJson.w,
6956
- bodyDepth: fpJson.h,
6957
- bodyCenterY: fpJson.bodyy,
6958
- ledPins: fpJson.ledpins || fpJson.num_pins === 14,
6959
- firstPinLeft: fpJson.firstpinleft,
6960
- firstPinTop: fpJson.firstpintop,
6961
- signalPitch: fpJson.p,
6962
- signalRowPitch: fpJson.py,
6963
- signalHoleDiameter: fpJson.id,
6964
- shieldPinX: fpJson.shieldx,
6965
- shieldPinY: fpJson.shieldy,
6966
- shieldHoleDiameter: fpJson.shieldid,
6967
- locatorHoleX: fpJson.holex,
6968
- locatorHoleY: fpJson.holey,
6969
- locatorHoleDiameter: fpJson.holed,
6970
- ledPinX: fpJson.ledx,
6971
- ledPinPitch: fpJson.ledp,
6972
- ledPinY: fpJson.ledy
6973
- }
6974
- );
6975
- case "soic":
6976
- case "sop8":
6977
- case "ssop":
6978
- return /* @__PURE__ */ jsx84(
6979
- SOIC,
6980
- {
6981
- pinCount: fpJson.num_pins,
6982
- leadLength: fpJson.pl,
6983
- leadWidth: fpJson.pw,
6984
- pitch: fpJson.p,
6985
- bodyWidth: fpJson.w
6986
- }
6987
- );
6988
- case "son":
6989
- case "wson":
6990
- case "vson": {
6991
- const bodyWidth = fpJson.fn === "vson" ? dim(fpJson.grid?.x, 3) : dim(fpJson.w, 3);
6992
- const bodyLength10 = fpJson.fn === "vson" ? dim(fpJson.grid?.y, 3) : dim(fpJson.h, 3);
6993
- const thermalPadWidth = dim(fpJson.epw, 0);
6994
- const thermalPadLength = dim(fpJson.eph, 0);
6995
- const padLength = fpJson.pl !== void 0 ? dim(fpJson.pl, 0) : void 0;
6996
- const padWidth = fpJson.pw !== void 0 ? dim(fpJson.pw, 0) : void 0;
6997
- const signalPads = getSmtPadRects(normalizedFootprint).filter(
6998
- (pad) => Number(pad.pin ?? 0) <= fpJson.num_pins
6999
- );
7000
- const distinct = (values) => new Set(values.map((value) => value.toFixed(3))).size;
7001
- const rowsAlongY = signalPads.length > 2 && distinct(signalPads.map((pad) => pad.y)) === 2 && distinct(signalPads.map((pad) => pad.x)) > 2;
7002
- const dfn = /* @__PURE__ */ jsx84(
7003
- DFN,
7004
- {
7005
- num_pins: fpJson.num_pins,
7006
- bodyWidth: rowsAlongY ? bodyLength10 : bodyWidth,
7007
- bodyLength: rowsAlongY ? bodyWidth : bodyLength10,
7008
- pitch: dim(fpJson.p, 0.5),
7009
- padLength,
7010
- padWidth,
7011
- thermalPadSize: fpJson.ep && thermalPadWidth > 0 && thermalPadLength > 0 ? {
7012
- width: rowsAlongY ? thermalPadLength : thermalPadWidth,
7013
- length: rowsAlongY ? thermalPadWidth : thermalPadLength
7014
- } : void 0
7015
- }
7016
- );
7017
- return rowsAlongY ? /* @__PURE__ */ jsx84(Rotate18, { rotation: [0, 0, "90deg"], children: dfn }) : dfn;
6815
+ }
6816
+ result.push(pointAtDistance(points, distances, safeEnd));
6817
+ return result;
6818
+ };
6819
+ var createFlatPath = (start, flexCableLength) => [
6820
+ start,
6821
+ [start[0], start[1] + flexCableLength, start[2]]
6822
+ ];
6823
+ var createFoldedPath = ({
6824
+ start,
6825
+ endZ,
6826
+ flexCableLength,
6827
+ foldDistanceFromConnector,
6828
+ foldOutset,
6829
+ foldSegments
6830
+ }) => {
6831
+ const points = [start];
6832
+ const foldStart = [
6833
+ start[0],
6834
+ start[1] + foldDistanceFromConnector,
6835
+ start[2]
6836
+ ];
6837
+ if (foldDistanceFromConnector > EPSILON) points.push(foldStart);
6838
+ for (let index = 1; index <= foldSegments; index += 1) {
6839
+ const angle = Math.PI * index / foldSegments;
6840
+ points.push([
6841
+ start[0],
6842
+ foldStart[1] + foldOutset * Math.sin(angle),
6843
+ start[2] + (endZ - start[2]) * (1 - Math.cos(angle)) / 2
6844
+ ]);
6845
+ }
6846
+ const minimumLength = getPathDistances(points).at(-1);
6847
+ if (minimumLength > flexCableLength + EPSILON) {
6848
+ throw new Error(
6849
+ `flexCableLength must be at least ${minimumLength.toFixed(2)} for this 180-degree fold`
6850
+ );
6851
+ }
6852
+ const tailLength = Math.max(0, flexCableLength - minimumLength);
6853
+ if (tailLength > EPSILON) {
6854
+ const foldEnd = points.at(-1);
6855
+ points.push([foldEnd[0], foldEnd[1] - tailLength, foldEnd[2]]);
6856
+ }
6857
+ return points;
6858
+ };
6859
+ var createRightAnglePath = ({
6860
+ start,
6861
+ flexCableLength,
6862
+ bendRadius,
6863
+ bendSegments,
6864
+ verticalLead,
6865
+ direction
6866
+ }) => {
6867
+ const bendLengthPerRadius = 2 * bendSegments * Math.sin(Math.PI / (4 * bendSegments));
6868
+ const resolvedRadius = Math.min(
6869
+ bendRadius,
6870
+ flexCableLength / bendLengthPerRadius
6871
+ );
6872
+ const bendLength = resolvedRadius * bendLengthPerRadius;
6873
+ const remainingLength = Math.max(0, flexCableLength - bendLength);
6874
+ const resolvedVerticalLead = Math.min(verticalLead, remainingLength * 0.45);
6875
+ const horizontalLength = remainingLength - resolvedVerticalLead;
6876
+ const points = [start];
6877
+ if (horizontalLength > EPSILON) {
6878
+ points.push([start[0], start[1] + horizontalLength, start[2]]);
6879
+ }
6880
+ for (let index = 1; index <= bendSegments; index += 1) {
6881
+ const angle = Math.PI / 2 * index / bendSegments;
6882
+ points.push([
6883
+ start[0],
6884
+ start[1] + horizontalLength + resolvedRadius * Math.sin(angle),
6885
+ start[2] + direction * resolvedRadius * (1 - Math.cos(angle))
6886
+ ]);
6887
+ }
6888
+ if (resolvedVerticalLead > EPSILON) {
6889
+ const arcEnd = points.at(-1);
6890
+ points.push([
6891
+ arcEnd[0],
6892
+ arcEnd[1],
6893
+ arcEnd[2] + direction * resolvedVerticalLead
6894
+ ]);
6895
+ }
6896
+ return points;
6897
+ };
6898
+ var CableStrip = ({
6899
+ points,
6900
+ width: width10,
6901
+ thickness,
6902
+ color,
6903
+ acrossOffset = 0,
6904
+ normalOffset = 0,
6905
+ overlap = 0.03
6906
+ }) => /* @__PURE__ */ jsx84(Colorize49, { color, children: points.slice(1).map((point, index) => {
6907
+ const previous = points[index];
6908
+ const dx = point[0] - previous[0];
6909
+ const dy = point[1] - previous[1];
6910
+ const dz = point[2] - previous[2];
6911
+ const segmentLength = Math.hypot(dx, dy, dz);
6912
+ if (segmentLength < EPSILON) return null;
6913
+ const pitch = Math.asin(dz / segmentLength);
6914
+ const yaw = Math.atan2(-dx, dy);
6915
+ const midpoint = [
6916
+ (previous[0] + point[0]) / 2,
6917
+ (previous[1] + point[1]) / 2,
6918
+ (previous[2] + point[2]) / 2
6919
+ ];
6920
+ const roundRadius = Math.max(
6921
+ 1e-3,
6922
+ Math.min(width10, thickness, segmentLength) / 2 - 1e-3
6923
+ );
6924
+ return /* @__PURE__ */ jsx84(Translate38, { offset: midpoint, children: /* @__PURE__ */ jsx84(Rotate18, { rotation: [pitch, 0, yaw], children: /* @__PURE__ */ jsx84(
6925
+ RoundedCuboid5,
6926
+ {
6927
+ size: [width10, segmentLength + overlap, thickness],
6928
+ center: [acrossOffset, 0, normalOffset],
6929
+ roundRadius
7018
6930
  }
7019
- case "mlp":
7020
- case "lga":
7021
- case "quad": {
7022
- if (fpJson.legsoutside) {
7023
- return /* @__PURE__ */ jsx84(
7024
- QFP,
7025
- {
7026
- pinCount: fpJson.num_pins,
7027
- pitch: dim(fpJson.p, 0.5),
7028
- leadWidth: dim(fpJson.pw, 0.25),
7029
- padContactLength: dim(fpJson.pl, 0.25),
7030
- bodyWidth: dim(fpJson.w, 6)
7031
- }
7032
- );
6931
+ ) }) }, `${index}:${midpoint.join(":")}`);
6932
+ }) });
6933
+ var FlexScreen = (props) => {
6934
+ const {
6935
+ width: width10,
6936
+ height: height10,
6937
+ diagonal,
6938
+ aspectRatio,
6939
+ ratio,
6940
+ defaultDiagonal,
6941
+ screenThickness = 1.2,
6942
+ bezelInset = 2,
6943
+ bezelDepth = 0.65,
6944
+ activeAreaWidth,
6945
+ activeAreaHeight,
6946
+ screenColor = "#071b24",
6947
+ bezelColor = "#15181d",
6948
+ showScreen = true,
6949
+ flexCableLength = 28,
6950
+ flexCableThickness = 0.18,
6951
+ flexCableColor = "#d79528",
6952
+ conductorCount = 8,
6953
+ conductorPitch,
6954
+ conductorWidth,
6955
+ conductorThickness = 0.035,
6956
+ conductorColor = "#8c4a18",
6957
+ cableEdgeMargin = 0.6,
6958
+ exposedContactLength = 2.4,
6959
+ showConductors = true,
6960
+ showFlexCable = true,
6961
+ showStiffeners = true,
6962
+ stiffenerLength = 3,
6963
+ stiffenerThickness = 0.16,
6964
+ stiffenerColor = "#416bb3",
6965
+ bendRadius = 3,
6966
+ bendSegments = 10,
6967
+ rightAngleVerticalLead = 3,
6968
+ distanceAboveBoard = 7,
6969
+ distanceBelowBoard = 7,
6970
+ foldDistanceFromConnector = 7,
6971
+ foldOutset = 4,
6972
+ foldSegments = 18,
6973
+ screenGap = 0.08,
6974
+ boardTopZ = 0,
6975
+ boardThickness = 1.6,
6976
+ boardClearance = 0.15,
6977
+ cableStartX = 0,
6978
+ cableStartY = 0,
6979
+ cableStartZ,
6980
+ cableLateralOffset = 0,
6981
+ screenOffset,
6982
+ screenRotation,
6983
+ rotation = [0, 0, 0],
6984
+ offset
6985
+ } = props;
6986
+ const size = resolveFlexScreenSize({
6987
+ width: width10,
6988
+ height: height10,
6989
+ diagonal,
6990
+ aspectRatio,
6991
+ ratio,
6992
+ defaultDiagonal
6993
+ });
6994
+ const orientation = resolveOrientation(props);
6995
+ const belowBoard = orientation === "sitsFlatBelowBoard" || orientation === "foldedToFaceBelowBoard" || orientation === "foldedToRightAngleBelowBoard";
6996
+ const foldedFace = orientation === "foldedToFaceAboveBoard" || orientation === "foldedToFaceBelowBoard";
6997
+ const rightAngle = orientation === "foldedToRightAngleAboveBoard" || orientation === "foldedToRightAngleBelowBoard";
6998
+ assertPositive("screenThickness", screenThickness);
6999
+ assertPositive("flexCableLength", flexCableLength);
7000
+ assertPositive("flexCableThickness", flexCableThickness);
7001
+ assertPositive("conductorThickness", conductorThickness);
7002
+ assertPositive("bendRadius", bendRadius);
7003
+ assertPositive("foldOutset", foldOutset);
7004
+ assertPositive("boardThickness", boardThickness);
7005
+ if (showStiffeners) assertPositive("stiffenerThickness", stiffenerThickness);
7006
+ if (!Number.isInteger(conductorCount) || conductorCount < 1) {
7007
+ throw new Error("conductorCount must be a positive integer");
7008
+ }
7009
+ if (!Number.isInteger(bendSegments) || bendSegments < 2) {
7010
+ throw new Error("bendSegments must be an integer of at least 2");
7011
+ }
7012
+ if (!Number.isInteger(foldSegments) || foldSegments < 4) {
7013
+ throw new Error("foldSegments must be an integer of at least 4");
7014
+ }
7015
+ if (boardClearance < 0 || screenGap < 0 || cableEdgeMargin < 0 || exposedContactLength < 0 || stiffenerLength < 0 || rightAngleVerticalLead < 0 || distanceAboveBoard < 0 || distanceBelowBoard < 0 || foldDistanceFromConnector < 0) {
7016
+ throw new Error(
7017
+ "clearances, margins, contact lengths, and lead lengths cannot be negative"
7018
+ );
7019
+ }
7020
+ const resolvedCableWidth = props.flexCableWidth ?? Math.min(12, Math.max(5, size.width * 0.3));
7021
+ assertPositive("flexCableWidth", resolvedCableWidth);
7022
+ const usableCableWidth = resolvedCableWidth - cableEdgeMargin * 2;
7023
+ if (usableCableWidth <= 0) {
7024
+ throw new Error("cableEdgeMargin leaves no usable flex cable width");
7025
+ }
7026
+ const resolvedConductorPitch = conductorPitch ?? (conductorCount === 1 ? 0 : usableCableWidth / conductorCount);
7027
+ if (conductorCount > 1 && (!Number.isFinite(resolvedConductorPitch) || resolvedConductorPitch <= 0)) {
7028
+ throw new Error("conductorPitch must be greater than zero");
7029
+ }
7030
+ const resolvedConductorWidth = conductorWidth ?? (conductorCount === 1 ? Math.min(usableCableWidth, resolvedCableWidth * 0.45) : resolvedConductorPitch * 0.48);
7031
+ assertPositive("conductorWidth", resolvedConductorWidth);
7032
+ const conductorSpan = (conductorCount - 1) * resolvedConductorPitch + resolvedConductorWidth;
7033
+ if (conductorSpan > usableCableWidth + EPSILON) {
7034
+ throw new Error(
7035
+ "conductorPitch and conductorWidth do not fit inside the flex cable margins"
7036
+ );
7037
+ }
7038
+ const cableStartsBelowBoard = belowBoard && !foldedFace;
7039
+ const defaultCableZ = cableStartsBelowBoard ? boardTopZ - boardThickness - boardClearance - flexCableThickness / 2 : boardTopZ + boardClearance + flexCableThickness / 2;
7040
+ const start = [
7041
+ cableStartX + cableLateralOffset,
7042
+ cableStartY,
7043
+ cableStartZ ?? defaultCableZ
7044
+ ];
7045
+ const direction = belowBoard ? -1 : 1;
7046
+ const foldedScreenBackZ = orientation === "foldedToFaceAboveBoard" ? boardTopZ + distanceAboveBoard : boardTopZ - boardThickness - distanceBelowBoard;
7047
+ const foldedCableEndZ = orientation === "foldedToFaceAboveBoard" ? foldedScreenBackZ - screenGap - flexCableThickness / 2 : foldedScreenBackZ + screenGap + flexCableThickness / 2;
7048
+ const path = foldedFace ? createFoldedPath({
7049
+ start,
7050
+ endZ: foldedCableEndZ,
7051
+ flexCableLength,
7052
+ foldDistanceFromConnector,
7053
+ foldOutset,
7054
+ foldSegments
7055
+ }) : rightAngle ? createRightAnglePath({
7056
+ start,
7057
+ flexCableLength,
7058
+ bendRadius,
7059
+ bendSegments,
7060
+ verticalLead: rightAngleVerticalLead,
7061
+ direction
7062
+ }) : createFlatPath(start, flexCableLength);
7063
+ const totalCableLength = getPathDistances(path).at(-1);
7064
+ const contactLength = Math.min(
7065
+ Math.max(0, exposedContactLength),
7066
+ totalCableLength / 2
7067
+ );
7068
+ const resolvedStiffenerLength = Math.min(
7069
+ Math.max(0, stiffenerLength),
7070
+ totalCableLength / 2
7071
+ );
7072
+ const startContacts = slicePath(path, 0, contactLength);
7073
+ const endContacts = slicePath(
7074
+ path,
7075
+ totalCableLength - contactLength,
7076
+ totalCableLength
7077
+ );
7078
+ const startStiffener = slicePath(path, 0, resolvedStiffenerLength);
7079
+ const endStiffener = slicePath(
7080
+ path,
7081
+ totalCableLength - resolvedStiffenerLength,
7082
+ totalCableLength
7083
+ );
7084
+ const pathEnd = path.at(-1);
7085
+ let presetScreenRotation;
7086
+ let screenCenter;
7087
+ if (orientation === "sitsFlat") {
7088
+ presetScreenRotation = [0, 0, 0];
7089
+ screenCenter = [
7090
+ pathEnd[0],
7091
+ pathEnd[1] + size.height / 2,
7092
+ pathEnd[2] + flexCableThickness / 2 + screenGap
7093
+ ];
7094
+ } else if (orientation === "sitsFlatBelowBoard") {
7095
+ presetScreenRotation = [0, Math.PI, 0];
7096
+ screenCenter = [
7097
+ pathEnd[0],
7098
+ pathEnd[1] + size.height / 2,
7099
+ pathEnd[2] - flexCableThickness / 2 - screenGap
7100
+ ];
7101
+ } else if (orientation === "foldedToFaceAboveBoard") {
7102
+ presetScreenRotation = [0, 0, 0];
7103
+ screenCenter = [pathEnd[0], pathEnd[1] - size.height / 2, foldedScreenBackZ];
7104
+ } else if (orientation === "foldedToFaceBelowBoard") {
7105
+ presetScreenRotation = [0, Math.PI, 0];
7106
+ screenCenter = [pathEnd[0], pathEnd[1] - size.height / 2, foldedScreenBackZ];
7107
+ } else if (orientation === "foldedToRightAngleAboveBoard") {
7108
+ presetScreenRotation = [Math.PI / 2, 0, 0];
7109
+ screenCenter = [
7110
+ pathEnd[0],
7111
+ pathEnd[1] - flexCableThickness / 2 - screenGap,
7112
+ pathEnd[2] + size.height / 2
7113
+ ];
7114
+ } else {
7115
+ presetScreenRotation = [-Math.PI / 2, 0, 0];
7116
+ screenCenter = [
7117
+ pathEnd[0],
7118
+ pathEnd[1] + flexCableThickness / 2 + screenGap,
7119
+ pathEnd[2] - size.height / 2
7120
+ ];
7121
+ }
7122
+ screenCenter = [
7123
+ screenCenter[0] + (screenOffset?.x ?? 0),
7124
+ screenCenter[1] + (screenOffset?.y ?? 0),
7125
+ screenCenter[2] + (screenOffset?.z ?? 0)
7126
+ ];
7127
+ const conductorOffsets = Array.from(
7128
+ { length: conductorCount },
7129
+ (_, index) => conductorCount === 1 ? 0 : (index - (conductorCount - 1) / 2) * resolvedConductorPitch
7130
+ );
7131
+ const conductorNormalOffset = (flexCableThickness + conductorThickness) / 2;
7132
+ const stiffenerNormalOffset = -(flexCableThickness + stiffenerThickness) / 2;
7133
+ const assembly = /* @__PURE__ */ jsxs80(Fragment80, { children: [
7134
+ showFlexCable && /* @__PURE__ */ jsx84(
7135
+ CableStrip,
7136
+ {
7137
+ points: path,
7138
+ width: resolvedCableWidth,
7139
+ thickness: flexCableThickness,
7140
+ color: flexCableColor
7033
7141
  }
7034
- return /* @__PURE__ */ jsx84(
7035
- qfn_default,
7142
+ ),
7143
+ showFlexCable && showStiffeners && resolvedStiffenerLength > EPSILON && /* @__PURE__ */ jsxs80(Fragment80, { children: [
7144
+ /* @__PURE__ */ jsx84(
7145
+ CableStrip,
7036
7146
  {
7037
- num_pins: fpJson.num_pins,
7038
- bodyWidth: dim(fpJson.w, 6),
7039
- bodyLength: dim(fpJson.h, 6),
7040
- pitch: dim(fpJson.p, 0.5),
7041
- padLength: dim(fpJson.pl, 0.25),
7042
- padWidth: dim(fpJson.pw, 0.25)
7147
+ points: startStiffener,
7148
+ width: resolvedCableWidth,
7149
+ thickness: stiffenerThickness,
7150
+ color: stiffenerColor,
7151
+ normalOffset: stiffenerNormalOffset
7043
7152
  }
7044
- );
7045
- }
7046
- case "bga": {
7047
- const pitch = dim(fpJson.p, 0.8);
7048
- const columns = fpJson.grid?.x ?? 8;
7049
- const rows = fpJson.grid?.y ?? 8;
7050
- return /* @__PURE__ */ jsx84(
7051
- BGA,
7153
+ ),
7154
+ /* @__PURE__ */ jsx84(
7155
+ CableStrip,
7052
7156
  {
7053
- ballPitch: pitch,
7054
- ballColumns: columns,
7055
- ballRows: rows,
7056
- ballDiameter: pitch * 0.625,
7057
- packageWidth: columns * pitch,
7058
- packageLength: rows * pitch
7157
+ points: endStiffener,
7158
+ width: resolvedCableWidth,
7159
+ thickness: stiffenerThickness,
7160
+ color: stiffenerColor,
7161
+ normalOffset: stiffenerNormalOffset
7059
7162
  }
7060
- );
7061
- }
7062
- case "sod523":
7063
- return /* @__PURE__ */ jsx84(SOD523, {});
7064
- case "sod723":
7065
- return /* @__PURE__ */ jsx84(SOD723_default, {});
7066
- case "sod882":
7067
- return /* @__PURE__ */ jsx84(SOD882, {});
7068
- case "sma":
7069
- return /* @__PURE__ */ jsx84(SMA, {});
7070
- case "smb":
7071
- return /* @__PURE__ */ jsx84(SMB, {});
7072
- case "smc":
7073
- return /* @__PURE__ */ jsx84(SMC, {});
7074
- case "smf":
7075
- return /* @__PURE__ */ jsx84(SMF, {});
7076
- case "sod123":
7077
- return /* @__PURE__ */ jsx84(SOD123, {});
7078
- case "sod123f":
7079
- return /* @__PURE__ */ jsx84(SOD123F, {});
7080
- case "sod123fl":
7081
- return /* @__PURE__ */ jsx84(SOD123FL, {});
7082
- case "sod123w":
7083
- return /* @__PURE__ */ jsx84(SOD123W, {});
7084
- case "sod110":
7085
- return /* @__PURE__ */ jsx84(SOD123W, { bodyWidth: 2.1, bodyLength: 1.4 });
7086
- case "sod128":
7087
- return /* @__PURE__ */ jsx84(SOD128, {});
7088
- case "sod323":
7089
- return /* @__PURE__ */ jsx84(SOD323, {});
7090
- case "sod323w":
7091
- return /* @__PURE__ */ jsx84(SOD323, {});
7092
- case "sod80":
7093
- return /* @__PURE__ */ jsx84(MINIMELF, {});
7094
- case "sod882d":
7095
- return /* @__PURE__ */ jsx84(SOD882, {});
7096
- case "smbf":
7097
- return /* @__PURE__ */ jsx84(SMB, {});
7098
- case "led2835":
7099
- return /* @__PURE__ */ jsx84(
7100
- Led2835,
7163
+ )
7164
+ ] }),
7165
+ showFlexCable && showConductors && contactLength > EPSILON && conductorOffsets.map((acrossOffset, index) => /* @__PURE__ */ jsxs80(Fragment79, { children: [
7166
+ /* @__PURE__ */ jsx84(
7167
+ CableStrip,
7101
7168
  {
7102
- color,
7103
- bodyWidth: dim(fpJson.w, 3.5),
7104
- bodyLength: dim(fpJson.h, 2.8),
7105
- pad1X: dim(fpJson.p1x, -0.9),
7106
- pad1Width: dim(fpJson.p1w, 2.2),
7107
- pad2X: dim(fpJson.p2x, 1.375),
7108
- pad2Width: dim(fpJson.p2w, 1.25),
7109
- padLength: dim(fpJson.ph, 2.2)
7169
+ points: startContacts,
7170
+ width: resolvedConductorWidth,
7171
+ thickness: conductorThickness,
7172
+ color: conductorColor,
7173
+ acrossOffset,
7174
+ normalOffset: conductorNormalOffset
7110
7175
  }
7111
- );
7112
- case "electrolytic":
7113
- case "radial": {
7114
- const pitch = dim(fpJson.p, 2.5);
7115
- const namedDiameter = footprint.match(/_d([\d.]+)/);
7116
- const diameter = fpJson.d !== void 0 ? dim(fpJson.d, pitch * 2) : namedDiameter ? Number(namedDiameter[1]) : pitch * 2;
7117
- return /* @__PURE__ */ jsx84(ElectrolyticCapacitor, { diameter, leadPitch: pitch });
7118
- }
7119
- case "potentiometer":
7120
- return /* @__PURE__ */ jsx84(
7121
- Potentiometer,
7176
+ ),
7177
+ /* @__PURE__ */ jsx84(
7178
+ CableStrip,
7122
7179
  {
7123
- bodyWidth: dim(fpJson.w, 5.35),
7124
- bodyLength: dim(fpJson.ca, 14),
7125
- bodyHeight: dim(fpJson.h, 4),
7126
- leads: getPlatedHoleCenters(normalizedFootprint)
7180
+ points: endContacts,
7181
+ width: resolvedConductorWidth,
7182
+ thickness: conductorThickness,
7183
+ color: conductorColor,
7184
+ acrossOffset,
7185
+ normalOffset: conductorNormalOffset
7127
7186
  }
7128
- );
7129
- case "smdpushbutton":
7130
- return /* @__PURE__ */ jsx84(
7131
- SmdPushButton,
7187
+ )
7188
+ ] }, `conductor:${index}`)),
7189
+ showScreen && /* @__PURE__ */ jsx84(Translate38, { offset: screenCenter, children: /* @__PURE__ */ jsx84(Rotate18, { rotation: screenRotation ?? presetScreenRotation, children: /* @__PURE__ */ jsx84(
7190
+ Screen,
7191
+ {
7192
+ width: size.width,
7193
+ height: size.height,
7194
+ thickness: screenThickness,
7195
+ bezelInset,
7196
+ bezelDepth,
7197
+ screenWidth: activeAreaWidth,
7198
+ screenHeight: activeAreaHeight,
7199
+ screenColor,
7200
+ bezelColor
7201
+ }
7202
+ ) }) })
7203
+ ] });
7204
+ return /* @__PURE__ */ jsx84(
7205
+ Translate38,
7206
+ {
7207
+ offset: {
7208
+ x: offset?.x ?? 0,
7209
+ y: offset?.y ?? 0,
7210
+ z: offset?.z ?? 0
7211
+ },
7212
+ children: /* @__PURE__ */ jsx84(Translate38, { offset: start, children: /* @__PURE__ */ jsx84(Rotate18, { rotation, children: /* @__PURE__ */ jsx84(Translate38, { offset: [-start[0], -start[1], -start[2]], children: assembly }) }) })
7213
+ }
7214
+ );
7215
+ };
7216
+
7217
+ // lib/Footprinter3d.tsx
7218
+ import { Fragment as Fragment81, jsx as jsx85 } from "react/jsx-runtime";
7219
+ var Footprinter3d = ({ footprint }) => {
7220
+ const modelFn = mp.string(footprint.split("_", 1)[0]).params().fn;
7221
+ if (mp.getModelNames().includes(modelFn)) {
7222
+ const model = mp.string(footprint).json();
7223
+ switch (model.fn) {
7224
+ case "flexscreen": {
7225
+ const { fn: _, ...flexScreenProps } = model;
7226
+ return /* @__PURE__ */ jsx85(FlexScreen, { ...flexScreenProps });
7227
+ }
7228
+ }
7229
+ }
7230
+ let normalizedFootprint = footprint;
7231
+ if (footprint.startsWith("jstzh1_5mm")) {
7232
+ const pinMatch = footprint.match(/jstzh1_5mm(\d+)?/);
7233
+ const numPins = pinMatch && pinMatch[1] ? pinMatch[1] : "7";
7234
+ normalizedFootprint = `zh${numPins}`;
7235
+ } else if (footprint.startsWith("jstph2_0mm")) {
7236
+ const pinMatch = footprint.match(/jstph2_0mm(\d+)?/);
7237
+ const numPins = pinMatch && pinMatch[1] ? pinMatch[1] : "2";
7238
+ normalizedFootprint = `jst${numPins}_ph`;
7239
+ }
7240
+ const fpJson = fp5.string(normalizedFootprint).json();
7241
+ const colorMatch = footprint.match(/_color\(([^)]+)\)/);
7242
+ const color = colorMatch ? colorMatch[1] : void 0;
7243
+ const dim = (value, fallback) => {
7244
+ if (value === void 0 || value === null) return fallback;
7245
+ const parsed = mm(value);
7246
+ return Number.isFinite(parsed) ? parsed : fallback;
7247
+ };
7248
+ switch (fpJson.fn) {
7249
+ case "crystal":
7250
+ return /* @__PURE__ */ jsx85(
7251
+ Crystal,
7132
7252
  {
7133
- padSpanX: dim(fpJson.px, 4.2),
7134
- padSpanY: dim(fpJson.py, 2.15),
7135
- padWidth: dim(fpJson.pw, 1.05),
7136
- padLength: dim(fpJson.ph, 0.7)
7253
+ horizontalPadPitch: fpJson.px,
7254
+ verticalPadPitch: fpJson.py,
7255
+ padWidth: fpJson.pw,
7256
+ padHeight: fpJson.ph
7137
7257
  }
7138
7258
  );
7139
- case "breakoutheaders": {
7140
- const pitch = dim(fpJson.p, 2.54);
7141
- const halfWidth = dim(fpJson.w, 10) / 2;
7142
- const sides = [
7143
- { x: -halfWidth, pins: fpJson.left ?? 0, key: "left" },
7144
- { x: halfWidth, pins: fpJson.right ?? 0, key: "right" }
7145
- ];
7146
- return /* @__PURE__ */ jsx84(Fragment79, { children: sides.filter(({ pins }) => pins > 0).map(({ x, pins, key }) => /* @__PURE__ */ jsx84(Translate38, { center: [x, 0, 0], children: /* @__PURE__ */ jsx84(Rotate18, { rotation: [0, 0, "90deg"], children: /* @__PURE__ */ jsx84(PinRow, { numberOfPins: pins, pitch }) }) }, key)) });
7147
- }
7148
- case "sod923":
7149
- return /* @__PURE__ */ jsx84(SOD923, {});
7150
- case "hc49":
7151
- return /* @__PURE__ */ jsx84(HC49, {});
7152
- case "micromelf":
7153
- return /* @__PURE__ */ jsx84(MicroMELF, {});
7154
- case "minimelf":
7155
- return /* @__PURE__ */ jsx84(MINIMELF, {});
7156
- case "melf":
7157
- return /* @__PURE__ */ jsx84(MELF, {});
7158
- case "ms012":
7159
- return /* @__PURE__ */ jsx84(
7160
- MS012,
7259
+ case "dip":
7260
+ return /* @__PURE__ */ jsx85(Dip, { numPins: fpJson.num_pins, pitch: fpJson.p, bodyWidth: fpJson.w });
7261
+ case "axial":
7262
+ return /* @__PURE__ */ jsx85(AxialCapacitor, { pitch: fpJson.p });
7263
+ case "tssop":
7264
+ return /* @__PURE__ */ jsx85(
7265
+ Tssop,
7161
7266
  {
7162
7267
  pinCount: fpJson.num_pins,
7163
- padContactLength: fpJson.pl,
7268
+ leadLength: fpJson.pl,
7164
7269
  leadWidth: fpJson.pw,
7165
- pitch: fpJson.p
7270
+ pitch: fpJson.p,
7271
+ bodyWidth: fpJson.w
7166
7272
  }
7167
7273
  );
7168
- case "ms013":
7169
- return /* @__PURE__ */ jsx84(
7170
- MS013,
7274
+ case "msop":
7275
+ return /* @__PURE__ */ jsx85(
7276
+ MSOP,
7171
7277
  {
7172
7278
  pinCount: fpJson.num_pins,
7173
7279
  padContactLength: fpJson.pl,
7174
7280
  leadWidth: fpJson.pw,
7175
- pitch: fpJson.p
7176
- }
7177
- );
7178
- case "sot723":
7179
- return /* @__PURE__ */ jsx84(SOT723, {});
7180
- case "to220":
7181
- return /* @__PURE__ */ jsx84(TO220, { leads: getPlatedHoleCenters(normalizedFootprint) });
7182
- case "to220f":
7183
- return /* @__PURE__ */ jsx84(TO220, { mouldedTab: true, leads: getPlatedHoleCenters(normalizedFootprint) });
7184
- case "to92":
7185
- return /* @__PURE__ */ jsx84(TO92, { leads: getPlatedHoleCenters(normalizedFootprint) });
7186
- case "to92l":
7187
- case "to92s": {
7188
- const across = dim(fpJson.w, 4.8);
7189
- const along = dim(fpJson.h, 4);
7190
- const diameter = Math.max(across, along);
7191
- return /* @__PURE__ */ jsx84(
7192
- TO92,
7193
- {
7194
- bodyDiameter: diameter,
7195
- flatCut: Math.max(diameter - Math.min(across, along), 0.4),
7196
- leads: getPlatedHoleCenters(normalizedFootprint)
7281
+ pitch: fpJson.p,
7282
+ bodyWidth: fpJson.w
7197
7283
  }
7198
7284
  );
7199
- }
7200
- case "to252":
7201
- case "dpak":
7202
- case "to263":
7203
- case "d2pak": {
7204
- const isD2Pak = fpJson.fn === "to263" || fpJson.fn === "d2pak";
7205
- const tabWidth = dim(fpJson.tabw, isD2Pak ? 8.38 : 6.2);
7206
- const tabLength = Math.min(
7207
- dim(fpJson.tabh, isD2Pak ? 10 : 5.8),
7208
- isD2Pak ? 10 : 6.5
7209
- );
7210
- return /* @__PURE__ */ jsx84(
7211
- DPAK,
7285
+ case "vssop":
7286
+ return /* @__PURE__ */ jsx85(
7287
+ VSSOP,
7212
7288
  {
7213
- bodyWidth: tabWidth,
7214
- bodyLength: dim(fpJson.w, isD2Pak ? 10.1 : 6.6),
7215
- bodyHeight: isD2Pak ? 4.4 : 2.3,
7216
- tabWidth,
7217
- tabLength,
7218
- span: dim(fpJson.span, isD2Pak ? 10.21 : 6.85),
7219
- pitch: dim(fpJson.p, isD2Pak ? 2.54 : 2.29),
7220
- leadWidth: dim(fpJson.pw, 1.5),
7221
- leadContactLength: dim(fpJson.pl, 3)
7289
+ pinCount: fpJson.num_pins,
7290
+ leadLength: fpJson.pl,
7291
+ leadWidth: fpJson.pw,
7292
+ pitch: fpJson.p,
7293
+ bodyWidth: fpJson.w,
7294
+ bodyLength: fpJson.h
7222
7295
  }
7223
7296
  );
7224
- }
7225
- case "stampboard":
7226
- case "stampreceiver":
7227
- return /* @__PURE__ */ jsx84(
7228
- StampBoard,
7297
+ case "qfp":
7298
+ return /* @__PURE__ */ jsx85(
7299
+ QFP,
7229
7300
  {
7230
- bodyWidth: fpJson.w,
7231
- leadsLeft: fpJson.left,
7232
- leadsRight: fpJson.right,
7233
- leadsTop: fpJson.top,
7234
- leadsBottom: fpJson.bottom,
7235
- leadsPitch: fpJson.p,
7301
+ pinCount: fpJson.num_pins,
7302
+ pitch: fpJson.p,
7236
7303
  leadWidth: fpJson.pw,
7237
- leadLength: fpJson.pl,
7238
- innerHoles: fpJson.innerhole,
7239
- innerHoleEdgeDistance: fpJson.innerholeedgedistance
7304
+ padContactLength: fpJson.pl,
7305
+ bodyWidth: fpJson.w
7240
7306
  }
7241
7307
  );
7242
- case "mountedpcbmodule": {
7243
- const rows = fpJson.rows ?? 1;
7244
- const pinRowSide = fpJson.pinRowSide ?? "left";
7245
- const holeInset = fpJson.holeInset;
7246
- const width10 = fpJson.width;
7247
- const height10 = fpJson.height;
7248
- const pinRow = fpJson.pinrow;
7249
- const pinRowHoleEdgeToEdgeDist = fpJson.pinRowHoleEdgeToEdgeDist;
7250
- const holes = Array.isArray(fpJson.holes) ? fpJson.holes : [];
7251
- return /* @__PURE__ */ jsx84(
7252
- MountedPcbModule,
7308
+ case "tqfp":
7309
+ return /* @__PURE__ */ jsx85(tqfp_default, {});
7310
+ case "lqfp":
7311
+ return /* @__PURE__ */ jsx85(LQFP, { pinCount: fpJson.num_pins });
7312
+ case "qfn": {
7313
+ const hasThermalPad = typeof fpJson.thermalpad?.x === "number" && typeof fpJson.thermalpad?.y === "number";
7314
+ return /* @__PURE__ */ jsx85(
7315
+ qfn_default,
7253
7316
  {
7254
- numPins: pinRow,
7255
- rows,
7256
- p: fpJson.p,
7257
- id: fpJson.id,
7258
- od: fpJson.od,
7259
- width: width10,
7260
- height: height10,
7261
- pinRowSide,
7262
- holes,
7263
- holeInset,
7264
- pinRowHoleEdgeToEdgeDist,
7265
- nopin: fpJson.nopin,
7266
- female: fpJson.female,
7267
- screen: fpJson.screen,
7268
- screenWidth: fpJson.screenwidth,
7269
- screenHeight: fpJson.screenheight,
7270
- screenCenterOffsetX: fpJson.screencenteroffsetx,
7271
- screenCenterOffsetY: fpJson.screencenteroffsety
7317
+ num_pins: fpJson.num_pins,
7318
+ bodyWidth: fpJson.w,
7319
+ bodyLength: fpJson.h,
7320
+ pitch: fpJson.p,
7321
+ padLength: fpJson.pl,
7322
+ padWidth: fpJson.pw,
7323
+ thermalPadSize: hasThermalPad ? {
7324
+ width: fpJson.thermalpad.x,
7325
+ length: fpJson.thermalpad.y
7326
+ } : void 0
7272
7327
  }
7273
7328
  );
7274
7329
  }
7275
- }
7276
- switch (fpJson.imperial) {
7277
- case "0402":
7278
- return /* @__PURE__ */ jsx84(A0402, { color });
7279
- case "0603":
7280
- return /* @__PURE__ */ jsx84(A0603, { color });
7281
- case "0805":
7282
- return /* @__PURE__ */ jsx84(A0805, { color });
7283
- case "0201":
7284
- return /* @__PURE__ */ jsx84(A0201, { color });
7285
- case "01005":
7286
- return /* @__PURE__ */ jsx84(A01005, { color });
7287
- case "1206":
7288
- return /* @__PURE__ */ jsx84(A1206, { color });
7289
- case "1210":
7290
- return /* @__PURE__ */ jsx84(A1210, { color });
7291
- case "2010":
7292
- return /* @__PURE__ */ jsx84(A2010, { color });
7293
- case "2512":
7294
- return /* @__PURE__ */ jsx84(A2512, { color });
7295
- }
7296
- if ((fpJson.fn === "res" || fpJson.fn === "cap") && fpJson.p !== void 0 && fpJson.ph !== void 0) {
7297
- const padPitch = mm(fpJson.p);
7298
- const padHeight = mm(fpJson.ph);
7299
- if (Number.isFinite(padPitch) && Number.isFinite(padHeight)) {
7300
- return /* @__PURE__ */ jsx84(
7301
- ParametricChip,
7330
+ case "dfn": {
7331
+ const hasThermalPad = typeof fpJson.thermalpad?.x === "number" && typeof fpJson.thermalpad?.y === "number";
7332
+ return /* @__PURE__ */ jsx85(
7333
+ DFN,
7302
7334
  {
7303
- padPitch,
7304
- padHeight,
7305
- color: color ?? (fpJson.fn === "cap" ? "#856c4d" : void 0)
7335
+ num_pins: fpJson.num_pins,
7336
+ bodyWidth: fpJson.w,
7337
+ bodyLength: fpJson.h,
7338
+ pitch: fpJson.p,
7339
+ padLength: fpJson.pl,
7340
+ padWidth: fpJson.pw,
7341
+ thermalPadSize: hasThermalPad ? {
7342
+ width: fpJson.thermalpad.x,
7343
+ length: fpJson.thermalpad.y
7344
+ } : void 0
7306
7345
  }
7307
7346
  );
7308
7347
  }
7309
- }
7310
- return null;
7311
- };
7312
-
7313
- // lib/FlexScreen.tsx
7314
- import { Colorize as Colorize49, Rotate as Rotate19, RoundedCuboid as RoundedCuboid5, Translate as Translate39 } from "jscad-fiber";
7315
- import { Fragment as Fragment80 } from "react";
7316
- import { Fragment as Fragment81, jsx as jsx85, jsxs as jsxs80 } from "react/jsx-runtime";
7317
- var DEFAULT_ASPECT_RATIO = 16 / 9;
7318
- var DEFAULT_DIAGONAL = 40;
7319
- var EPSILON = 1e-6;
7320
- var assertPositive = (name, value) => {
7321
- if (!Number.isFinite(value) || value <= 0) {
7322
- throw new Error(`${name} must be a finite number greater than zero`);
7323
- }
7324
- };
7325
- var resolveAspectRatio = (value) => {
7326
- if (value === void 0) return DEFAULT_ASPECT_RATIO;
7327
- if (typeof value === "number") {
7328
- assertPositive("aspectRatio", value);
7329
- return value;
7330
- }
7331
- if (typeof value !== "string") {
7332
- const [ratioWidth2, ratioHeight2] = value;
7333
- assertPositive("aspectRatio width", ratioWidth2);
7334
- assertPositive("aspectRatio height", ratioHeight2);
7335
- return ratioWidth2 / ratioHeight2;
7336
- }
7337
- const parts = value.split(":");
7338
- if (parts.length !== 2) {
7339
- throw new Error('aspectRatio must look like "16:9"');
7340
- }
7341
- const ratioWidth = Number(parts[0]);
7342
- const ratioHeight = Number(parts[1]);
7343
- assertPositive("aspectRatio width", ratioWidth);
7344
- assertPositive("aspectRatio height", ratioHeight);
7345
- return ratioWidth / ratioHeight;
7346
- };
7347
- var resolveFlexScreenSize = ({
7348
- width: width10,
7349
- height: height10,
7350
- diagonal,
7351
- aspectRatio,
7352
- ratio,
7353
- defaultDiagonal = DEFAULT_DIAGONAL
7354
- }) => {
7355
- const resolvedRatio = resolveAspectRatio(aspectRatio ?? ratio);
7356
- if (width10 !== void 0) assertPositive("width", width10);
7357
- if (height10 !== void 0) assertPositive("height", height10);
7358
- if (diagonal !== void 0) assertPositive("diagonal", diagonal);
7359
- assertPositive("defaultDiagonal", defaultDiagonal);
7360
- let resolvedWidth;
7361
- let resolvedHeight;
7362
- if (width10 !== void 0 && height10 !== void 0) {
7363
- resolvedWidth = width10;
7364
- resolvedHeight = height10;
7365
- } else if (diagonal !== void 0 && width10 !== void 0) {
7366
- if (width10 >= diagonal) {
7367
- throw new Error("width must be smaller than diagonal");
7368
- }
7369
- resolvedWidth = width10;
7370
- resolvedHeight = Math.sqrt(diagonal ** 2 - width10 ** 2);
7371
- } else if (diagonal !== void 0 && height10 !== void 0) {
7372
- if (height10 >= diagonal) {
7373
- throw new Error("height must be smaller than diagonal");
7348
+ case "pinrow": {
7349
+ const rowsMatch = footprint.match(/_rows(\d+)/);
7350
+ const rows = rowsMatch && rowsMatch[1] ? parseInt(rowsMatch[1], 10) : 1;
7351
+ if (fpJson.male)
7352
+ return /* @__PURE__ */ jsx85(
7353
+ PinRow,
7354
+ {
7355
+ numberOfPins: fpJson.num_pins,
7356
+ pitch: fpJson.p,
7357
+ invert: fpJson.invert,
7358
+ rows,
7359
+ smd: fpJson.smd || fpJson.surface_mount,
7360
+ rightangle: fpJson.rightangle
7361
+ }
7362
+ );
7363
+ if (fpJson.female)
7364
+ return /* @__PURE__ */ jsx85(
7365
+ FemaleHeaderRow,
7366
+ {
7367
+ numberOfPins: fpJson.num_pins,
7368
+ pitch: fpJson.p,
7369
+ rows
7370
+ }
7371
+ );
7374
7372
  }
7375
- resolvedWidth = Math.sqrt(diagonal ** 2 - height10 ** 2);
7376
- resolvedHeight = height10;
7377
- } else if (width10 !== void 0) {
7378
- resolvedWidth = width10;
7379
- resolvedHeight = width10 / resolvedRatio;
7380
- } else if (height10 !== void 0) {
7381
- resolvedWidth = height10 * resolvedRatio;
7382
- resolvedHeight = height10;
7383
- } else {
7384
- const resolvedDiagonal = diagonal ?? defaultDiagonal;
7385
- resolvedHeight = resolvedDiagonal / Math.sqrt(resolvedRatio ** 2 + 1);
7386
- resolvedWidth = resolvedHeight * resolvedRatio;
7387
- }
7388
- return {
7389
- width: resolvedWidth,
7390
- height: resolvedHeight,
7391
- diagonal: Math.hypot(resolvedWidth, resolvedHeight),
7392
- aspectRatio: resolvedWidth / resolvedHeight
7393
- };
7394
- };
7395
- var resolveOrientation = (props) => {
7396
- const shortcuts = [
7397
- ["sitsFlat", props.sitsFlat],
7398
- ["sitsFlatBelowBoard", props.sitsFlatBelowBoard],
7399
- ["foldedToFaceAboveBoard", props.foldedToFaceAboveBoard],
7400
- ["foldedToFaceBelowBoard", props.foldedToFaceBelowBoard],
7401
- ["foldedToFaceAboveBoard", props.foldsAboveBoard],
7402
- ["foldedToFaceBelowBoard", props.foldsBelowBoard],
7403
- ["foldedToRightAngleAboveBoard", props.foldedToRightAngleAboveBoard],
7404
- ["foldedToRightAngleBelowBoard", props.foldedToRightAngleBelowBoard]
7405
- ].filter((entry) => entry[1]);
7406
- if (shortcuts.length > 1) {
7407
- throw new Error(
7408
- "Only one FlexScreen boolean orientation shortcut can be true"
7409
- );
7410
- }
7411
- return shortcuts[0]?.[0] ?? props.orientation ?? "sitsFlat";
7412
- };
7413
- var distance = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
7414
- var interpolate = (a, b, progress) => [
7415
- a[0] + (b[0] - a[0]) * progress,
7416
- a[1] + (b[1] - a[1]) * progress,
7417
- a[2] + (b[2] - a[2]) * progress
7418
- ];
7419
- var getPathDistances = (points) => {
7420
- const distances = [0];
7421
- for (let index = 1; index < points.length; index += 1) {
7422
- distances.push(
7423
- distances[index - 1] + distance(points[index - 1], points[index])
7424
- );
7425
- }
7426
- return distances;
7427
- };
7428
- var pointAtDistance = (points, distances, targetDistance) => {
7429
- if (targetDistance <= 0) return points[0];
7430
- const totalLength = distances.at(-1);
7431
- if (targetDistance >= totalLength) return points.at(-1);
7432
- for (let index = 1; index < points.length; index += 1) {
7433
- if (distances[index] >= targetDistance) {
7434
- const segmentStart = distances[index - 1];
7435
- const segmentLength = distances[index] - segmentStart;
7436
- return interpolate(
7437
- points[index - 1],
7438
- points[index],
7439
- (targetDistance - segmentStart) / segmentLength
7373
+ case "smdpinheader":
7374
+ return /* @__PURE__ */ jsx85(
7375
+ SmdPinHeader,
7376
+ {
7377
+ numberOfPins: fpJson.num_pins,
7378
+ pitch: fpJson.p,
7379
+ bodyWidth: fpJson.bh
7380
+ }
7381
+ );
7382
+ case "led5050":
7383
+ return /* @__PURE__ */ jsx85(Led5050, { color });
7384
+ case "cap": {
7385
+ switch (fpJson.imperial) {
7386
+ case "0402":
7387
+ return /* @__PURE__ */ jsx85(A0402, { color: "#856c4d" });
7388
+ case "0603":
7389
+ return /* @__PURE__ */ jsx85(A0603, { color: "#856c4d" });
7390
+ case "0805":
7391
+ return /* @__PURE__ */ jsx85(A0805, { color: "#856c4d" });
7392
+ case "0201":
7393
+ return /* @__PURE__ */ jsx85(A0201, { color: "#856c4d" });
7394
+ case "01005":
7395
+ return /* @__PURE__ */ jsx85(A01005, { color: "#856c4d" });
7396
+ case "1206":
7397
+ return /* @__PURE__ */ jsx85(A1206, { color: "#856c4d" });
7398
+ case "1210":
7399
+ return /* @__PURE__ */ jsx85(A1210, { color: "#856c4d" });
7400
+ case "2010":
7401
+ return /* @__PURE__ */ jsx85(A2010, { color: "#856c4d" });
7402
+ case "2512":
7403
+ return /* @__PURE__ */ jsx85(A2512, { color: "#856c4d" });
7404
+ }
7405
+ break;
7406
+ }
7407
+ case "sot23":
7408
+ switch (fpJson.num_pins) {
7409
+ case 3:
7410
+ return /* @__PURE__ */ jsx85(SOT233P, { color });
7411
+ case 5:
7412
+ return /* @__PURE__ */ jsx85(SOT_235_default, {});
7413
+ }
7414
+ break;
7415
+ case "sot25":
7416
+ return /* @__PURE__ */ jsx85(SOT_235_default, {});
7417
+ case "sot":
7418
+ case "sot343": {
7419
+ const isSc70 = fpJson.fn === "sot343";
7420
+ return /* @__PURE__ */ jsx85(
7421
+ GullWingBody,
7422
+ {
7423
+ pads: getSmtPadRects(normalizedFootprint),
7424
+ bodyWidth: isSc70 ? 1.25 : 1.6,
7425
+ bodyLength: isSc70 ? 2 : 2.9,
7426
+ bodyHeight: isSc70 ? 1.1 : 1.3
7427
+ }
7440
7428
  );
7441
7429
  }
7442
- }
7443
- return points.at(-1);
7444
- };
7445
- var slicePath = (points, startDistance, endDistance) => {
7446
- const distances = getPathDistances(points);
7447
- const totalLength = distances.at(-1);
7448
- const safeStart = Math.max(0, Math.min(startDistance, totalLength));
7449
- const safeEnd = Math.max(safeStart, Math.min(endDistance, totalLength));
7450
- const result = [pointAtDistance(points, distances, safeStart)];
7451
- for (let index = 1; index < points.length - 1; index += 1) {
7452
- if (distances[index] > safeStart && distances[index] < safeEnd) {
7453
- result.push(points[index]);
7430
+ case "sot563":
7431
+ return /* @__PURE__ */ jsx85(SOT563, {});
7432
+ case "sot89": {
7433
+ const padSpan = dim(fpJson.w, 4.2);
7434
+ return /* @__PURE__ */ jsx85(
7435
+ SOT223,
7436
+ {
7437
+ fullWidth: padSpan,
7438
+ bodyWidth: padSpan * 0.6,
7439
+ bodyLength: dim(fpJson.h, 4.8) * 0.94,
7440
+ bodyHeight: 1.5,
7441
+ leadWidth: dim(fpJson.pw, 0.48),
7442
+ tabLeadWidth: dim(fpJson.pw, 0.48) * 2,
7443
+ padPitch: dim(fpJson.p, 1.5),
7444
+ leadHeight: 0.66
7445
+ }
7446
+ );
7454
7447
  }
7455
- }
7456
- result.push(pointAtDistance(points, distances, safeEnd));
7457
- return result;
7458
- };
7459
- var createFlatPath = (start, flexCableLength) => [
7460
- start,
7461
- [start[0], start[1] + flexCableLength, start[2]]
7462
- ];
7463
- var createFoldedPath = ({
7464
- start,
7465
- endZ,
7466
- flexCableLength,
7467
- foldDistanceFromConnector,
7468
- foldOutset,
7469
- foldSegments
7470
- }) => {
7471
- const points = [start];
7472
- const foldStart = [
7473
- start[0],
7474
- start[1] + foldDistanceFromConnector,
7475
- start[2]
7476
- ];
7477
- if (foldDistanceFromConnector > EPSILON) points.push(foldStart);
7478
- for (let index = 1; index <= foldSegments; index += 1) {
7479
- const angle = Math.PI * index / foldSegments;
7480
- points.push([
7481
- start[0],
7482
- foldStart[1] + foldOutset * Math.sin(angle),
7483
- start[2] + (endZ - start[2]) * (1 - Math.cos(angle)) / 2
7484
- ]);
7485
- }
7486
- const minimumLength = getPathDistances(points).at(-1);
7487
- if (minimumLength > flexCableLength + EPSILON) {
7488
- throw new Error(
7489
- `flexCableLength must be at least ${minimumLength.toFixed(2)} for this 180-degree fold`
7490
- );
7491
- }
7492
- const tailLength = Math.max(0, flexCableLength - minimumLength);
7493
- if (tailLength > EPSILON) {
7494
- const foldEnd = points.at(-1);
7495
- points.push([foldEnd[0], foldEnd[1] - tailLength, foldEnd[2]]);
7496
- }
7497
- return points;
7498
- };
7499
- var createRightAnglePath = ({
7500
- start,
7501
- flexCableLength,
7502
- bendRadius,
7503
- bendSegments,
7504
- verticalLead,
7505
- direction
7506
- }) => {
7507
- const bendLengthPerRadius = 2 * bendSegments * Math.sin(Math.PI / (4 * bendSegments));
7508
- const resolvedRadius = Math.min(
7509
- bendRadius,
7510
- flexCableLength / bendLengthPerRadius
7511
- );
7512
- const bendLength = resolvedRadius * bendLengthPerRadius;
7513
- const remainingLength = Math.max(0, flexCableLength - bendLength);
7514
- const resolvedVerticalLead = Math.min(verticalLead, remainingLength * 0.45);
7515
- const horizontalLength = remainingLength - resolvedVerticalLead;
7516
- const points = [start];
7517
- if (horizontalLength > EPSILON) {
7518
- points.push([start[0], start[1] + horizontalLength, start[2]]);
7519
- }
7520
- for (let index = 1; index <= bendSegments; index += 1) {
7521
- const angle = Math.PI / 2 * index / bendSegments;
7522
- points.push([
7523
- start[0],
7524
- start[1] + horizontalLength + resolvedRadius * Math.sin(angle),
7525
- start[2] + direction * resolvedRadius * (1 - Math.cos(angle))
7526
- ]);
7527
- }
7528
- if (resolvedVerticalLead > EPSILON) {
7529
- const arcEnd = points.at(-1);
7530
- points.push([
7531
- arcEnd[0],
7532
- arcEnd[1],
7533
- arcEnd[2] + direction * resolvedVerticalLead
7534
- ]);
7535
- }
7536
- return points;
7537
- };
7538
- var CableStrip = ({
7539
- points,
7540
- width: width10,
7541
- thickness,
7542
- color,
7543
- acrossOffset = 0,
7544
- normalOffset = 0,
7545
- overlap = 0.03
7546
- }) => /* @__PURE__ */ jsx85(Colorize49, { color, children: points.slice(1).map((point, index) => {
7547
- const previous = points[index];
7548
- const dx = point[0] - previous[0];
7549
- const dy = point[1] - previous[1];
7550
- const dz = point[2] - previous[2];
7551
- const segmentLength = Math.hypot(dx, dy, dz);
7552
- if (segmentLength < EPSILON) return null;
7553
- const pitch = Math.asin(dz / segmentLength);
7554
- const yaw = Math.atan2(-dx, dy);
7555
- const midpoint = [
7556
- (previous[0] + point[0]) / 2,
7557
- (previous[1] + point[1]) / 2,
7558
- (previous[2] + point[2]) / 2
7559
- ];
7560
- const roundRadius = Math.max(
7561
- 1e-3,
7562
- Math.min(width10, thickness, segmentLength) / 2 - 1e-3
7563
- );
7564
- return /* @__PURE__ */ jsx85(Translate39, { offset: midpoint, children: /* @__PURE__ */ jsx85(Rotate19, { rotation: [pitch, 0, yaw], children: /* @__PURE__ */ jsx85(
7565
- RoundedCuboid5,
7566
- {
7567
- size: [width10, segmentLength + overlap, thickness],
7568
- center: [acrossOffset, 0, normalOffset],
7569
- roundRadius
7448
+ case "sot457":
7449
+ return /* @__PURE__ */ jsx85(SOT457, {});
7450
+ case "sot223":
7451
+ return /* @__PURE__ */ jsx85(SOT223, {});
7452
+ case "sot23w":
7453
+ return /* @__PURE__ */ jsx85(SOT23W, {});
7454
+ case "sot323":
7455
+ return /* @__PURE__ */ jsx85(SOT323, {});
7456
+ case "sod323f":
7457
+ return /* @__PURE__ */ jsx85(SOD323F, {});
7458
+ case "sod323fl":
7459
+ return /* @__PURE__ */ jsx85(SOD323FL, {});
7460
+ case "sot363":
7461
+ return /* @__PURE__ */ jsx85(SOT_363_default, {});
7462
+ case "sot886":
7463
+ return /* @__PURE__ */ jsx85(SOT886, {});
7464
+ case "sot963":
7465
+ return /* @__PURE__ */ jsx85(SOT963, {});
7466
+ case "pushbutton":
7467
+ return /* @__PURE__ */ jsx85(
7468
+ PushButton,
7469
+ {
7470
+ width: fpJson.w,
7471
+ length: fpJson.h,
7472
+ innerDiameter: fpJson.id
7473
+ }
7474
+ );
7475
+ case "jst":
7476
+ if (fpJson.zh) {
7477
+ return /* @__PURE__ */ jsx85(JSTZH1_5mm, { numPins: fpJson.num_pins });
7478
+ }
7479
+ if (fpJson.ph) {
7480
+ return /* @__PURE__ */ jsx85(JSTPH2_0mm, { numPins: fpJson.num_pins });
7481
+ }
7482
+ break;
7483
+ case "fpc":
7484
+ return /* @__PURE__ */ jsx85(
7485
+ FPC,
7486
+ {
7487
+ pinCount: fpJson.num_pins,
7488
+ pitch: fpJson.p,
7489
+ padWidth: fpJson.pw,
7490
+ padLength: fpJson.pl,
7491
+ staggered: fpJson.staggered,
7492
+ reverse: fpJson.reverse,
7493
+ rowPitch: fpJson.py,
7494
+ topPadLength: fpJson.toppl,
7495
+ bottomPadLength: fpJson.bottompl,
7496
+ mountPadPitchX: fpJson.mpx,
7497
+ mountPadOffsetY: fpJson.mpy,
7498
+ mountTop: fpJson.mounttop,
7499
+ mountPadWidth: fpJson.mpw,
7500
+ mountPadLength: fpJson.mpl
7501
+ }
7502
+ );
7503
+ case "rj45":
7504
+ return /* @__PURE__ */ jsx85(
7505
+ RJ45,
7506
+ {
7507
+ bodyWidth: fpJson.w,
7508
+ bodyDepth: fpJson.h,
7509
+ bodyCenterY: fpJson.bodyy,
7510
+ ledPins: fpJson.ledpins || fpJson.num_pins === 14,
7511
+ firstPinLeft: fpJson.firstpinleft,
7512
+ firstPinTop: fpJson.firstpintop,
7513
+ signalPitch: fpJson.p,
7514
+ signalRowPitch: fpJson.py,
7515
+ signalHoleDiameter: fpJson.id,
7516
+ shieldPinX: fpJson.shieldx,
7517
+ shieldPinY: fpJson.shieldy,
7518
+ shieldHoleDiameter: fpJson.shieldid,
7519
+ locatorHoleX: fpJson.holex,
7520
+ locatorHoleY: fpJson.holey,
7521
+ locatorHoleDiameter: fpJson.holed,
7522
+ ledPinX: fpJson.ledx,
7523
+ ledPinPitch: fpJson.ledp,
7524
+ ledPinY: fpJson.ledy
7525
+ }
7526
+ );
7527
+ case "soic":
7528
+ case "sop8":
7529
+ case "ssop":
7530
+ return /* @__PURE__ */ jsx85(
7531
+ SOIC,
7532
+ {
7533
+ pinCount: fpJson.num_pins,
7534
+ leadLength: fpJson.pl,
7535
+ leadWidth: fpJson.pw,
7536
+ pitch: fpJson.p,
7537
+ bodyWidth: fpJson.w
7538
+ }
7539
+ );
7540
+ case "son":
7541
+ case "wson":
7542
+ case "vson": {
7543
+ const bodyWidth = fpJson.fn === "vson" ? dim(fpJson.grid?.x, 3) : dim(fpJson.w, 3);
7544
+ const bodyLength10 = fpJson.fn === "vson" ? dim(fpJson.grid?.y, 3) : dim(fpJson.h, 3);
7545
+ const thermalPadWidth = dim(fpJson.epw, 0);
7546
+ const thermalPadLength = dim(fpJson.eph, 0);
7547
+ const padLength = fpJson.pl !== void 0 ? dim(fpJson.pl, 0) : void 0;
7548
+ const padWidth = fpJson.pw !== void 0 ? dim(fpJson.pw, 0) : void 0;
7549
+ const signalPads = getSmtPadRects(normalizedFootprint).filter(
7550
+ (pad) => Number(pad.pin ?? 0) <= fpJson.num_pins
7551
+ );
7552
+ const distinct = (values) => new Set(values.map((value) => value.toFixed(3))).size;
7553
+ const rowsAlongY = signalPads.length > 2 && distinct(signalPads.map((pad) => pad.y)) === 2 && distinct(signalPads.map((pad) => pad.x)) > 2;
7554
+ const dfn = /* @__PURE__ */ jsx85(
7555
+ DFN,
7556
+ {
7557
+ num_pins: fpJson.num_pins,
7558
+ bodyWidth: rowsAlongY ? bodyLength10 : bodyWidth,
7559
+ bodyLength: rowsAlongY ? bodyWidth : bodyLength10,
7560
+ pitch: dim(fpJson.p, 0.5),
7561
+ padLength,
7562
+ padWidth,
7563
+ thermalPadSize: fpJson.ep && thermalPadWidth > 0 && thermalPadLength > 0 ? {
7564
+ width: rowsAlongY ? thermalPadLength : thermalPadWidth,
7565
+ length: rowsAlongY ? thermalPadWidth : thermalPadLength
7566
+ } : void 0
7567
+ }
7568
+ );
7569
+ return rowsAlongY ? /* @__PURE__ */ jsx85(Rotate19, { rotation: [0, 0, "90deg"], children: dfn }) : dfn;
7570
7570
  }
7571
- ) }) }, `${index}:${midpoint.join(":")}`);
7572
- }) });
7573
- var FlexScreen = (props) => {
7574
- const {
7575
- width: width10,
7576
- height: height10,
7577
- diagonal,
7578
- aspectRatio,
7579
- ratio,
7580
- defaultDiagonal,
7581
- screenThickness = 1.2,
7582
- bezelInset = 2,
7583
- bezelDepth = 0.65,
7584
- activeAreaWidth,
7585
- activeAreaHeight,
7586
- screenColor = "#071b24",
7587
- bezelColor = "#15181d",
7588
- showScreen = true,
7589
- flexCableLength = 28,
7590
- flexCableThickness = 0.18,
7591
- flexCableColor = "#d79528",
7592
- conductorCount = 8,
7593
- conductorPitch,
7594
- conductorWidth,
7595
- conductorThickness = 0.035,
7596
- conductorColor = "#8c4a18",
7597
- cableEdgeMargin = 0.6,
7598
- exposedContactLength = 2.4,
7599
- showConductors = true,
7600
- showFlexCable = true,
7601
- showStiffeners = true,
7602
- stiffenerLength = 3,
7603
- stiffenerThickness = 0.16,
7604
- stiffenerColor = "#416bb3",
7605
- bendRadius = 3,
7606
- bendSegments = 10,
7607
- rightAngleVerticalLead = 3,
7608
- distanceAboveBoard = 7,
7609
- distanceBelowBoard = 7,
7610
- foldDistanceFromConnector = 7,
7611
- foldOutset = 4,
7612
- foldSegments = 18,
7613
- screenGap = 0.08,
7614
- boardTopZ = 0,
7615
- boardThickness = 1.6,
7616
- boardClearance = 0.15,
7617
- cableStartX = 0,
7618
- cableStartY = 0,
7619
- cableStartZ,
7620
- cableLateralOffset = 0,
7621
- screenOffset,
7622
- screenRotation,
7623
- rotation = [0, 0, 0],
7624
- offset
7625
- } = props;
7626
- const size = resolveFlexScreenSize({
7627
- width: width10,
7628
- height: height10,
7629
- diagonal,
7630
- aspectRatio,
7631
- ratio,
7632
- defaultDiagonal
7633
- });
7634
- const orientation = resolveOrientation(props);
7635
- const belowBoard = orientation === "sitsFlatBelowBoard" || orientation === "foldedToFaceBelowBoard" || orientation === "foldedToRightAngleBelowBoard";
7636
- const foldedFace = orientation === "foldedToFaceAboveBoard" || orientation === "foldedToFaceBelowBoard";
7637
- const rightAngle = orientation === "foldedToRightAngleAboveBoard" || orientation === "foldedToRightAngleBelowBoard";
7638
- assertPositive("screenThickness", screenThickness);
7639
- assertPositive("flexCableLength", flexCableLength);
7640
- assertPositive("flexCableThickness", flexCableThickness);
7641
- assertPositive("conductorThickness", conductorThickness);
7642
- assertPositive("bendRadius", bendRadius);
7643
- assertPositive("foldOutset", foldOutset);
7644
- assertPositive("boardThickness", boardThickness);
7645
- if (showStiffeners) assertPositive("stiffenerThickness", stiffenerThickness);
7646
- if (!Number.isInteger(conductorCount) || conductorCount < 1) {
7647
- throw new Error("conductorCount must be a positive integer");
7648
- }
7649
- if (!Number.isInteger(bendSegments) || bendSegments < 2) {
7650
- throw new Error("bendSegments must be an integer of at least 2");
7651
- }
7652
- if (!Number.isInteger(foldSegments) || foldSegments < 4) {
7653
- throw new Error("foldSegments must be an integer of at least 4");
7654
- }
7655
- if (boardClearance < 0 || screenGap < 0 || cableEdgeMargin < 0 || exposedContactLength < 0 || stiffenerLength < 0 || rightAngleVerticalLead < 0 || distanceAboveBoard < 0 || distanceBelowBoard < 0 || foldDistanceFromConnector < 0) {
7656
- throw new Error(
7657
- "clearances, margins, contact lengths, and lead lengths cannot be negative"
7658
- );
7659
- }
7660
- const resolvedCableWidth = props.flexCableWidth ?? Math.min(12, Math.max(5, size.width * 0.3));
7661
- assertPositive("flexCableWidth", resolvedCableWidth);
7662
- const usableCableWidth = resolvedCableWidth - cableEdgeMargin * 2;
7663
- if (usableCableWidth <= 0) {
7664
- throw new Error("cableEdgeMargin leaves no usable flex cable width");
7665
- }
7666
- const resolvedConductorPitch = conductorPitch ?? (conductorCount === 1 ? 0 : usableCableWidth / conductorCount);
7667
- if (conductorCount > 1 && (!Number.isFinite(resolvedConductorPitch) || resolvedConductorPitch <= 0)) {
7668
- throw new Error("conductorPitch must be greater than zero");
7669
- }
7670
- const resolvedConductorWidth = conductorWidth ?? (conductorCount === 1 ? Math.min(usableCableWidth, resolvedCableWidth * 0.45) : resolvedConductorPitch * 0.48);
7671
- assertPositive("conductorWidth", resolvedConductorWidth);
7672
- const conductorSpan = (conductorCount - 1) * resolvedConductorPitch + resolvedConductorWidth;
7673
- if (conductorSpan > usableCableWidth + EPSILON) {
7674
- throw new Error(
7675
- "conductorPitch and conductorWidth do not fit inside the flex cable margins"
7676
- );
7677
- }
7678
- const cableStartsBelowBoard = belowBoard && !foldedFace;
7679
- const defaultCableZ = cableStartsBelowBoard ? boardTopZ - boardThickness - boardClearance - flexCableThickness / 2 : boardTopZ + boardClearance + flexCableThickness / 2;
7680
- const start = [
7681
- cableStartX + cableLateralOffset,
7682
- cableStartY,
7683
- cableStartZ ?? defaultCableZ
7684
- ];
7685
- const direction = belowBoard ? -1 : 1;
7686
- const foldedScreenBackZ = orientation === "foldedToFaceAboveBoard" ? boardTopZ + distanceAboveBoard : boardTopZ - boardThickness - distanceBelowBoard;
7687
- const foldedCableEndZ = orientation === "foldedToFaceAboveBoard" ? foldedScreenBackZ - screenGap - flexCableThickness / 2 : foldedScreenBackZ + screenGap + flexCableThickness / 2;
7688
- const path = foldedFace ? createFoldedPath({
7689
- start,
7690
- endZ: foldedCableEndZ,
7691
- flexCableLength,
7692
- foldDistanceFromConnector,
7693
- foldOutset,
7694
- foldSegments
7695
- }) : rightAngle ? createRightAnglePath({
7696
- start,
7697
- flexCableLength,
7698
- bendRadius,
7699
- bendSegments,
7700
- verticalLead: rightAngleVerticalLead,
7701
- direction
7702
- }) : createFlatPath(start, flexCableLength);
7703
- const totalCableLength = getPathDistances(path).at(-1);
7704
- const contactLength = Math.min(
7705
- Math.max(0, exposedContactLength),
7706
- totalCableLength / 2
7707
- );
7708
- const resolvedStiffenerLength = Math.min(
7709
- Math.max(0, stiffenerLength),
7710
- totalCableLength / 2
7711
- );
7712
- const startContacts = slicePath(path, 0, contactLength);
7713
- const endContacts = slicePath(
7714
- path,
7715
- totalCableLength - contactLength,
7716
- totalCableLength
7717
- );
7718
- const startStiffener = slicePath(path, 0, resolvedStiffenerLength);
7719
- const endStiffener = slicePath(
7720
- path,
7721
- totalCableLength - resolvedStiffenerLength,
7722
- totalCableLength
7723
- );
7724
- const pathEnd = path.at(-1);
7725
- let presetScreenRotation;
7726
- let screenCenter;
7727
- if (orientation === "sitsFlat") {
7728
- presetScreenRotation = [0, 0, 0];
7729
- screenCenter = [
7730
- pathEnd[0],
7731
- pathEnd[1] + size.height / 2,
7732
- pathEnd[2] + flexCableThickness / 2 + screenGap
7733
- ];
7734
- } else if (orientation === "sitsFlatBelowBoard") {
7735
- presetScreenRotation = [0, Math.PI, 0];
7736
- screenCenter = [
7737
- pathEnd[0],
7738
- pathEnd[1] + size.height / 2,
7739
- pathEnd[2] - flexCableThickness / 2 - screenGap
7740
- ];
7741
- } else if (orientation === "foldedToFaceAboveBoard") {
7742
- presetScreenRotation = [0, 0, 0];
7743
- screenCenter = [pathEnd[0], pathEnd[1] - size.height / 2, foldedScreenBackZ];
7744
- } else if (orientation === "foldedToFaceBelowBoard") {
7745
- presetScreenRotation = [0, Math.PI, 0];
7746
- screenCenter = [pathEnd[0], pathEnd[1] - size.height / 2, foldedScreenBackZ];
7747
- } else if (orientation === "foldedToRightAngleAboveBoard") {
7748
- presetScreenRotation = [Math.PI / 2, 0, 0];
7749
- screenCenter = [
7750
- pathEnd[0],
7751
- pathEnd[1] - flexCableThickness / 2 - screenGap,
7752
- pathEnd[2] + size.height / 2
7753
- ];
7754
- } else {
7755
- presetScreenRotation = [-Math.PI / 2, 0, 0];
7756
- screenCenter = [
7757
- pathEnd[0],
7758
- pathEnd[1] + flexCableThickness / 2 + screenGap,
7759
- pathEnd[2] - size.height / 2
7760
- ];
7761
- }
7762
- screenCenter = [
7763
- screenCenter[0] + (screenOffset?.x ?? 0),
7764
- screenCenter[1] + (screenOffset?.y ?? 0),
7765
- screenCenter[2] + (screenOffset?.z ?? 0)
7766
- ];
7767
- const conductorOffsets = Array.from(
7768
- { length: conductorCount },
7769
- (_, index) => conductorCount === 1 ? 0 : (index - (conductorCount - 1) / 2) * resolvedConductorPitch
7770
- );
7771
- const conductorNormalOffset = (flexCableThickness + conductorThickness) / 2;
7772
- const stiffenerNormalOffset = -(flexCableThickness + stiffenerThickness) / 2;
7773
- const assembly = /* @__PURE__ */ jsxs80(Fragment81, { children: [
7774
- showFlexCable && /* @__PURE__ */ jsx85(
7775
- CableStrip,
7776
- {
7777
- points: path,
7778
- width: resolvedCableWidth,
7779
- thickness: flexCableThickness,
7780
- color: flexCableColor
7571
+ case "mlp":
7572
+ case "lga":
7573
+ case "quad": {
7574
+ if (fpJson.legsoutside) {
7575
+ return /* @__PURE__ */ jsx85(
7576
+ QFP,
7577
+ {
7578
+ pinCount: fpJson.num_pins,
7579
+ pitch: dim(fpJson.p, 0.5),
7580
+ leadWidth: dim(fpJson.pw, 0.25),
7581
+ padContactLength: dim(fpJson.pl, 0.25),
7582
+ bodyWidth: dim(fpJson.w, 6)
7583
+ }
7584
+ );
7781
7585
  }
7782
- ),
7783
- showFlexCable && showStiffeners && resolvedStiffenerLength > EPSILON && /* @__PURE__ */ jsxs80(Fragment81, { children: [
7784
- /* @__PURE__ */ jsx85(
7785
- CableStrip,
7586
+ return /* @__PURE__ */ jsx85(
7587
+ qfn_default,
7588
+ {
7589
+ num_pins: fpJson.num_pins,
7590
+ bodyWidth: dim(fpJson.w, 6),
7591
+ bodyLength: dim(fpJson.h, 6),
7592
+ pitch: dim(fpJson.p, 0.5),
7593
+ padLength: dim(fpJson.pl, 0.25),
7594
+ padWidth: dim(fpJson.pw, 0.25)
7595
+ }
7596
+ );
7597
+ }
7598
+ case "bga": {
7599
+ const pitch = dim(fpJson.p, 0.8);
7600
+ const columns = fpJson.grid?.x ?? 8;
7601
+ const rows = fpJson.grid?.y ?? 8;
7602
+ return /* @__PURE__ */ jsx85(
7603
+ BGA,
7786
7604
  {
7787
- points: startStiffener,
7788
- width: resolvedCableWidth,
7789
- thickness: stiffenerThickness,
7790
- color: stiffenerColor,
7791
- normalOffset: stiffenerNormalOffset
7605
+ ballPitch: pitch,
7606
+ ballColumns: columns,
7607
+ ballRows: rows,
7608
+ ballDiameter: pitch * 0.625,
7609
+ packageWidth: columns * pitch,
7610
+ packageLength: rows * pitch
7792
7611
  }
7793
- ),
7794
- /* @__PURE__ */ jsx85(
7795
- CableStrip,
7612
+ );
7613
+ }
7614
+ case "sod523":
7615
+ return /* @__PURE__ */ jsx85(SOD523, {});
7616
+ case "sod723":
7617
+ return /* @__PURE__ */ jsx85(SOD723_default, {});
7618
+ case "sod882":
7619
+ return /* @__PURE__ */ jsx85(SOD882, {});
7620
+ case "sma":
7621
+ return /* @__PURE__ */ jsx85(SMA, {});
7622
+ case "smb":
7623
+ return /* @__PURE__ */ jsx85(SMB, {});
7624
+ case "smc":
7625
+ return /* @__PURE__ */ jsx85(SMC, {});
7626
+ case "smf":
7627
+ return /* @__PURE__ */ jsx85(SMF, {});
7628
+ case "sod123":
7629
+ return /* @__PURE__ */ jsx85(SOD123, {});
7630
+ case "sod123f":
7631
+ return /* @__PURE__ */ jsx85(SOD123F, {});
7632
+ case "sod123fl":
7633
+ return /* @__PURE__ */ jsx85(SOD123FL, {});
7634
+ case "sod123w":
7635
+ return /* @__PURE__ */ jsx85(SOD123W, {});
7636
+ case "sod110":
7637
+ return /* @__PURE__ */ jsx85(SOD123W, { bodyWidth: 2.1, bodyLength: 1.4 });
7638
+ case "sod128":
7639
+ return /* @__PURE__ */ jsx85(SOD128, {});
7640
+ case "sod323":
7641
+ return /* @__PURE__ */ jsx85(SOD323, {});
7642
+ case "sod323w":
7643
+ return /* @__PURE__ */ jsx85(SOD323, {});
7644
+ case "sod80":
7645
+ return /* @__PURE__ */ jsx85(MINIMELF, {});
7646
+ case "sod882d":
7647
+ return /* @__PURE__ */ jsx85(SOD882, {});
7648
+ case "smbf":
7649
+ return /* @__PURE__ */ jsx85(SMB, {});
7650
+ case "led2835":
7651
+ return /* @__PURE__ */ jsx85(
7652
+ Led2835,
7796
7653
  {
7797
- points: endStiffener,
7798
- width: resolvedCableWidth,
7799
- thickness: stiffenerThickness,
7800
- color: stiffenerColor,
7801
- normalOffset: stiffenerNormalOffset
7654
+ color,
7655
+ bodyWidth: dim(fpJson.w, 3.5),
7656
+ bodyLength: dim(fpJson.h, 2.8),
7657
+ pad1X: dim(fpJson.p1x, -0.9),
7658
+ pad1Width: dim(fpJson.p1w, 2.2),
7659
+ pad2X: dim(fpJson.p2x, 1.375),
7660
+ pad2Width: dim(fpJson.p2w, 1.25),
7661
+ padLength: dim(fpJson.ph, 2.2)
7802
7662
  }
7803
- )
7804
- ] }),
7805
- showFlexCable && showConductors && contactLength > EPSILON && conductorOffsets.map((acrossOffset, index) => /* @__PURE__ */ jsxs80(Fragment80, { children: [
7806
- /* @__PURE__ */ jsx85(
7807
- CableStrip,
7663
+ );
7664
+ case "electrolytic":
7665
+ case "radial": {
7666
+ const pitch = dim(fpJson.p, 2.5);
7667
+ const namedDiameter = footprint.match(/_d([\d.]+)/);
7668
+ const diameter = fpJson.d !== void 0 ? dim(fpJson.d, pitch * 2) : namedDiameter ? Number(namedDiameter[1]) : pitch * 2;
7669
+ return /* @__PURE__ */ jsx85(ElectrolyticCapacitor, { diameter, leadPitch: pitch });
7670
+ }
7671
+ case "potentiometer":
7672
+ return /* @__PURE__ */ jsx85(
7673
+ Potentiometer,
7808
7674
  {
7809
- points: startContacts,
7810
- width: resolvedConductorWidth,
7811
- thickness: conductorThickness,
7812
- color: conductorColor,
7813
- acrossOffset,
7814
- normalOffset: conductorNormalOffset
7675
+ bodyWidth: dim(fpJson.w, 5.35),
7676
+ bodyLength: dim(fpJson.ca, 14),
7677
+ bodyHeight: dim(fpJson.h, 4),
7678
+ leads: getPlatedHoleCenters(normalizedFootprint)
7815
7679
  }
7816
- ),
7817
- /* @__PURE__ */ jsx85(
7818
- CableStrip,
7680
+ );
7681
+ case "smdpushbutton":
7682
+ return /* @__PURE__ */ jsx85(
7683
+ SmdPushButton,
7819
7684
  {
7820
- points: endContacts,
7821
- width: resolvedConductorWidth,
7822
- thickness: conductorThickness,
7823
- color: conductorColor,
7824
- acrossOffset,
7825
- normalOffset: conductorNormalOffset
7685
+ padSpanX: dim(fpJson.px, 4.2),
7686
+ padSpanY: dim(fpJson.py, 2.15),
7687
+ padWidth: dim(fpJson.pw, 1.05),
7688
+ padLength: dim(fpJson.ph, 0.7)
7826
7689
  }
7827
- )
7828
- ] }, `conductor:${index}`)),
7829
- showScreen && /* @__PURE__ */ jsx85(Translate39, { offset: screenCenter, children: /* @__PURE__ */ jsx85(Rotate19, { rotation: screenRotation ?? presetScreenRotation, children: /* @__PURE__ */ jsx85(
7830
- Screen,
7831
- {
7832
- width: size.width,
7833
- height: size.height,
7834
- thickness: screenThickness,
7835
- bezelInset,
7836
- bezelDepth,
7837
- screenWidth: activeAreaWidth,
7838
- screenHeight: activeAreaHeight,
7839
- screenColor,
7840
- bezelColor
7841
- }
7842
- ) }) })
7843
- ] });
7844
- return /* @__PURE__ */ jsx85(
7845
- Translate39,
7846
- {
7847
- offset: {
7848
- x: offset?.x ?? 0,
7849
- y: offset?.y ?? 0,
7850
- z: offset?.z ?? 0
7851
- },
7852
- children: /* @__PURE__ */ jsx85(Translate39, { offset: start, children: /* @__PURE__ */ jsx85(Rotate19, { rotation, children: /* @__PURE__ */ jsx85(Translate39, { offset: [-start[0], -start[1], -start[2]], children: assembly }) }) })
7690
+ );
7691
+ case "breakoutheaders": {
7692
+ const pitch = dim(fpJson.p, 2.54);
7693
+ const halfWidth = dim(fpJson.w, 10) / 2;
7694
+ const sides = [
7695
+ { x: -halfWidth, pins: fpJson.left ?? 0, key: "left" },
7696
+ { x: halfWidth, pins: fpJson.right ?? 0, key: "right" }
7697
+ ];
7698
+ return /* @__PURE__ */ jsx85(Fragment81, { children: sides.filter(({ pins }) => pins > 0).map(({ x, pins, key }) => /* @__PURE__ */ jsx85(Translate39, { center: [x, 0, 0], children: /* @__PURE__ */ jsx85(Rotate19, { rotation: [0, 0, "90deg"], children: /* @__PURE__ */ jsx85(PinRow, { numberOfPins: pins, pitch }) }) }, key)) });
7853
7699
  }
7854
- );
7700
+ case "sod923":
7701
+ return /* @__PURE__ */ jsx85(SOD923, {});
7702
+ case "hc49":
7703
+ return /* @__PURE__ */ jsx85(HC49, {});
7704
+ case "micromelf":
7705
+ return /* @__PURE__ */ jsx85(MicroMELF, {});
7706
+ case "minimelf":
7707
+ return /* @__PURE__ */ jsx85(MINIMELF, {});
7708
+ case "melf":
7709
+ return /* @__PURE__ */ jsx85(MELF, {});
7710
+ case "ms012":
7711
+ return /* @__PURE__ */ jsx85(
7712
+ MS012,
7713
+ {
7714
+ pinCount: fpJson.num_pins,
7715
+ padContactLength: fpJson.pl,
7716
+ leadWidth: fpJson.pw,
7717
+ pitch: fpJson.p
7718
+ }
7719
+ );
7720
+ case "ms013":
7721
+ return /* @__PURE__ */ jsx85(
7722
+ MS013,
7723
+ {
7724
+ pinCount: fpJson.num_pins,
7725
+ padContactLength: fpJson.pl,
7726
+ leadWidth: fpJson.pw,
7727
+ pitch: fpJson.p
7728
+ }
7729
+ );
7730
+ case "sot723":
7731
+ return /* @__PURE__ */ jsx85(SOT723, {});
7732
+ case "to220":
7733
+ return /* @__PURE__ */ jsx85(TO220, { leads: getPlatedHoleCenters(normalizedFootprint) });
7734
+ case "to220f":
7735
+ return /* @__PURE__ */ jsx85(TO220, { mouldedTab: true, leads: getPlatedHoleCenters(normalizedFootprint) });
7736
+ case "to92":
7737
+ return /* @__PURE__ */ jsx85(TO92, { leads: getPlatedHoleCenters(normalizedFootprint) });
7738
+ case "to92l":
7739
+ case "to92s": {
7740
+ const across = dim(fpJson.w, 4.8);
7741
+ const along = dim(fpJson.h, 4);
7742
+ const diameter = Math.max(across, along);
7743
+ return /* @__PURE__ */ jsx85(
7744
+ TO92,
7745
+ {
7746
+ bodyDiameter: diameter,
7747
+ flatCut: Math.max(diameter - Math.min(across, along), 0.4),
7748
+ leads: getPlatedHoleCenters(normalizedFootprint)
7749
+ }
7750
+ );
7751
+ }
7752
+ case "to252":
7753
+ case "dpak":
7754
+ case "to263":
7755
+ case "d2pak": {
7756
+ const isD2Pak = fpJson.fn === "to263" || fpJson.fn === "d2pak";
7757
+ const tabWidth = dim(fpJson.tabw, isD2Pak ? 8.38 : 6.2);
7758
+ const tabLength = Math.min(
7759
+ dim(fpJson.tabh, isD2Pak ? 10 : 5.8),
7760
+ isD2Pak ? 10 : 6.5
7761
+ );
7762
+ return /* @__PURE__ */ jsx85(
7763
+ DPAK,
7764
+ {
7765
+ bodyWidth: tabWidth,
7766
+ bodyLength: dim(fpJson.w, isD2Pak ? 10.1 : 6.6),
7767
+ bodyHeight: isD2Pak ? 4.4 : 2.3,
7768
+ tabWidth,
7769
+ tabLength,
7770
+ span: dim(fpJson.span, isD2Pak ? 10.21 : 6.85),
7771
+ pitch: dim(fpJson.p, isD2Pak ? 2.54 : 2.29),
7772
+ leadWidth: dim(fpJson.pw, 1.5),
7773
+ leadContactLength: dim(fpJson.pl, 3)
7774
+ }
7775
+ );
7776
+ }
7777
+ case "stampboard":
7778
+ case "stampreceiver":
7779
+ return /* @__PURE__ */ jsx85(
7780
+ StampBoard,
7781
+ {
7782
+ bodyWidth: fpJson.w,
7783
+ leadsLeft: fpJson.left,
7784
+ leadsRight: fpJson.right,
7785
+ leadsTop: fpJson.top,
7786
+ leadsBottom: fpJson.bottom,
7787
+ leadsPitch: fpJson.p,
7788
+ leadWidth: fpJson.pw,
7789
+ leadLength: fpJson.pl,
7790
+ innerHoles: fpJson.innerhole,
7791
+ innerHoleEdgeDistance: fpJson.innerholeedgedistance
7792
+ }
7793
+ );
7794
+ case "mountedpcbmodule": {
7795
+ const rows = fpJson.rows ?? 1;
7796
+ const pinRowSide = fpJson.pinRowSide ?? "left";
7797
+ const holeInset = fpJson.holeInset;
7798
+ const width10 = fpJson.width;
7799
+ const height10 = fpJson.height;
7800
+ const pinRow = fpJson.pinrow;
7801
+ const pinRowHoleEdgeToEdgeDist = fpJson.pinRowHoleEdgeToEdgeDist;
7802
+ const holes = Array.isArray(fpJson.holes) ? fpJson.holes : [];
7803
+ return /* @__PURE__ */ jsx85(
7804
+ MountedPcbModule,
7805
+ {
7806
+ numPins: pinRow,
7807
+ rows,
7808
+ p: fpJson.p,
7809
+ id: fpJson.id,
7810
+ od: fpJson.od,
7811
+ width: width10,
7812
+ height: height10,
7813
+ pinRowSide,
7814
+ holes,
7815
+ holeInset,
7816
+ pinRowHoleEdgeToEdgeDist,
7817
+ nopin: fpJson.nopin,
7818
+ female: fpJson.female,
7819
+ screen: fpJson.screen,
7820
+ screenWidth: fpJson.screenwidth,
7821
+ screenHeight: fpJson.screenheight,
7822
+ screenCenterOffsetX: fpJson.screencenteroffsetx,
7823
+ screenCenterOffsetY: fpJson.screencenteroffsety
7824
+ }
7825
+ );
7826
+ }
7827
+ }
7828
+ switch (fpJson.imperial) {
7829
+ case "0402":
7830
+ return /* @__PURE__ */ jsx85(A0402, { color });
7831
+ case "0603":
7832
+ return /* @__PURE__ */ jsx85(A0603, { color });
7833
+ case "0805":
7834
+ return /* @__PURE__ */ jsx85(A0805, { color });
7835
+ case "0201":
7836
+ return /* @__PURE__ */ jsx85(A0201, { color });
7837
+ case "01005":
7838
+ return /* @__PURE__ */ jsx85(A01005, { color });
7839
+ case "1206":
7840
+ return /* @__PURE__ */ jsx85(A1206, { color });
7841
+ case "1210":
7842
+ return /* @__PURE__ */ jsx85(A1210, { color });
7843
+ case "2010":
7844
+ return /* @__PURE__ */ jsx85(A2010, { color });
7845
+ case "2512":
7846
+ return /* @__PURE__ */ jsx85(A2512, { color });
7847
+ }
7848
+ if ((fpJson.fn === "res" || fpJson.fn === "cap") && fpJson.p !== void 0 && fpJson.ph !== void 0) {
7849
+ const padPitch = mm(fpJson.p);
7850
+ const padHeight = mm(fpJson.ph);
7851
+ if (Number.isFinite(padPitch) && Number.isFinite(padHeight)) {
7852
+ return /* @__PURE__ */ jsx85(
7853
+ ParametricChip,
7854
+ {
7855
+ padPitch,
7856
+ padHeight,
7857
+ color: color ?? (fpJson.fn === "cap" ? "#856c4d" : void 0)
7858
+ }
7859
+ );
7860
+ }
7861
+ }
7862
+ return null;
7855
7863
  };
7856
7864
  export {
7857
7865
  A01005,