jscad-electronics 0.0.155 → 0.0.157

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