jscad-electronics 0.0.171 → 0.0.173

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vanilla.js CHANGED
@@ -426,115 +426,6 @@ var Dip = ({
426
426
  ] });
427
427
  };
428
428
 
429
- // lib/SmdChipLead.tsx
430
- function calculateSCurve(x, {
431
- height: height10,
432
- padContactLength,
433
- curveLength,
434
- bodyDistance,
435
- steepness = 10
436
- }) {
437
- if (!curveLength) curveLength = bodyDistance * 0.3;
438
- let flatFromBodySectionLength = bodyDistance - padContactLength - curveLength;
439
- if (flatFromBodySectionLength < 0) {
440
- curveLength += flatFromBodySectionLength;
441
- flatFromBodySectionLength = 0;
442
- }
443
- const curveStart = padContactLength * 0.75;
444
- const curveEnd = padContactLength + curveLength + (bodyDistance - padContactLength - curveLength) * 0.25;
445
- if (x <= curveStart) return 0;
446
- if (x >= curveEnd) return height10;
447
- const t = (x - curveStart) / (curveEnd - curveStart);
448
- return height10 / (1 + Math.exp(-steepness * (t - 0.5)));
449
- }
450
- var SmdChipLead = (props) => {
451
- const { thickness, width: width10, padContactLength, bodyDistance, height: height10, rotation } = props;
452
- const N = 15;
453
- const points = Array.from({ length: N }).map((_, i) => i / (N - 1) * bodyDistance).map((x) => [x, calculateSCurve(x, props)]);
454
- const polygon = getExpandedStroke(points, thickness);
455
- return /* @__PURE__ */ jsx(Colorize, { color: "#fff", children: /* @__PURE__ */ jsx(Translate, { offset: { z: 0, y: 0, x: 0, ...props.position }, children: /* @__PURE__ */ jsx(Rotate, { rotation: ["90deg", 0, rotation ?? 0], children: /* @__PURE__ */ jsx(Translate, { offset: { x: 0, y: 0, z: -width10 / 2 }, children: /* @__PURE__ */ jsx(ExtrudeLinear, { height: width10, children: /* @__PURE__ */ jsx(Polygon, { points: polygon.map((p) => [p.x, p.y]) }) }) }) }) }) });
456
- };
457
-
458
- // lib/Tssop.tsx
459
- var Tssop = ({
460
- pinCount,
461
- leadLength,
462
- leadWidth,
463
- pitch,
464
- bodyWidth
465
- }) => {
466
- const sidePinCount = Math.ceil(pinCount / 2);
467
- const isSmallTssop = sidePinCount <= 4;
468
- const pinOffsetToCenter = (sidePinCount - 1) * pitch / 2;
469
- const bodyLength10 = pitch * Math.max(sidePinCount - 1, 0) + (isSmallTssop ? 1.5 : 1.15);
470
- const bodyVisualWidth = bodyWidth - (isSmallTssop ? 0.66 : 0.58);
471
- const leadThickness = 0.15;
472
- const leadHeight = 0.8;
473
- const bodyHeight = 1.22;
474
- const bodyStandoff = 0.24;
475
- const padContactLength = leadLength * 0.5;
476
- const leadReach = padContactLength + Math.max(0.22, Math.min(0.4, leadLength * 0.65));
477
- const leadStartOffset = bodyWidth / 2 + leadLength / 2;
478
- const curveLength = leadReach * 0.1;
479
- const notchInset = Math.min(Math.min(bodyVisualWidth, bodyLength10) * 0.18, 1);
480
- const notchRadius = Math.min(
481
- Math.min(bodyVisualWidth, bodyLength10) * 0.12,
482
- 0.45
483
- );
484
- return /* @__PURE__ */ jsxs(Fragment2, { children: [
485
- Array.from({ length: sidePinCount }).map((_, i) => /* @__PURE__ */ jsx(
486
- SmdChipLead,
487
- {
488
- position: {
489
- x: -leadStartOffset,
490
- y: i * pitch - pinOffsetToCenter,
491
- z: leadThickness / 2
492
- },
493
- width: leadWidth,
494
- thickness: leadThickness,
495
- padContactLength,
496
- bodyDistance: leadReach,
497
- curveLength,
498
- height: leadHeight
499
- },
500
- `left-${i}`
501
- )),
502
- Array.from({ length: sidePinCount }).map((_, i) => /* @__PURE__ */ jsx(
503
- SmdChipLead,
504
- {
505
- rotation: Math.PI,
506
- position: {
507
- x: leadStartOffset,
508
- y: i * pitch - pinOffsetToCenter,
509
- z: leadThickness / 2
510
- },
511
- width: leadWidth,
512
- thickness: leadThickness,
513
- padContactLength,
514
- bodyDistance: leadReach,
515
- curveLength,
516
- height: leadHeight
517
- },
518
- `right-${i}`
519
- )),
520
- /* @__PURE__ */ jsx(
521
- ChipBody,
522
- {
523
- center: { x: 0, y: 0, z: 0 },
524
- width: bodyVisualWidth,
525
- length: bodyLength10,
526
- height: bodyHeight,
527
- notchPosition: {
528
- x: -(bodyVisualWidth / 2 - notchInset - 0.2),
529
- y: bodyLength10 / 2 - notchInset - 0.2,
530
- z: bodyHeight
531
- },
532
- notchRadius
533
- }
534
- )
535
- ] });
536
- };
537
-
538
429
  // lib/utils/DualRowGullWing.tsx
539
430
  function createDualRowGullWing(p) {
540
431
  const {
@@ -666,6 +557,116 @@ function createDualRowGullWing(p) {
666
557
  ] });
667
558
  }
668
559
 
560
+ // lib/SmdChipLead.tsx
561
+ function calculateSCurve(x, {
562
+ height: height10,
563
+ padContactLength,
564
+ curveLength,
565
+ bodyDistance,
566
+ steepness = 10
567
+ }) {
568
+ if (!curveLength) curveLength = bodyDistance * 0.3;
569
+ let flatFromBodySectionLength = bodyDistance - padContactLength - curveLength;
570
+ if (flatFromBodySectionLength < 0) {
571
+ curveLength += flatFromBodySectionLength;
572
+ flatFromBodySectionLength = 0;
573
+ }
574
+ const curveStart = padContactLength * 0.75;
575
+ const curveEnd = padContactLength + curveLength + (bodyDistance - padContactLength - curveLength) * 0.25;
576
+ if (x <= curveStart) return 0;
577
+ if (x >= curveEnd) return height10;
578
+ const t = (x - curveStart) / (curveEnd - curveStart);
579
+ return height10 / (1 + Math.exp(-steepness * (t - 0.5)));
580
+ }
581
+ var SmdChipLead = (props) => {
582
+ const { thickness, width: width10, padContactLength, bodyDistance, height: height10, rotation } = props;
583
+ const N = 15;
584
+ const points = Array.from({ length: N }).map((_, i) => i / (N - 1) * bodyDistance).map((x) => [x, calculateSCurve(x, props)]);
585
+ const polygon = getExpandedStroke(points, thickness);
586
+ return /* @__PURE__ */ jsx(Colorize, { color: "#fff", children: /* @__PURE__ */ jsx(Translate, { offset: { z: 0, y: 0, x: 0, ...props.position }, children: /* @__PURE__ */ jsx(Rotate, { rotation: ["90deg", 0, rotation ?? 0], children: /* @__PURE__ */ jsx(Translate, { offset: { x: 0, y: 0, z: -width10 / 2 }, children: /* @__PURE__ */ jsx(ExtrudeLinear, { height: width10, children: /* @__PURE__ */ jsx(Polygon, { points: polygon.map((p) => [p.x, p.y]) }) }) }) }) }) });
587
+ };
588
+
589
+ // lib/Tssop.tsx
590
+ var LegacyTssop = ({
591
+ pinCount,
592
+ leadLength,
593
+ leadWidth,
594
+ pitch,
595
+ bodyWidth
596
+ }) => {
597
+ const sidePinCount = Math.ceil(pinCount / 2);
598
+ const isSmallTssop = sidePinCount <= 4;
599
+ const pinOffsetToCenter = (sidePinCount - 1) * pitch / 2;
600
+ const bodyLength10 = pitch * Math.max(sidePinCount - 1, 0) + (isSmallTssop ? 1.5 : 1.15);
601
+ const bodyVisualWidth = bodyWidth - (isSmallTssop ? 0.66 : 0.58);
602
+ const leadThickness = 0.15;
603
+ const leadHeight = 0.8;
604
+ const bodyHeight = 1.22;
605
+ const bodyStandoff = 0.24;
606
+ const padContactLength = leadLength * 0.5;
607
+ const leadReach = padContactLength + Math.max(0.22, Math.min(0.4, leadLength * 0.65));
608
+ const leadStartOffset = bodyWidth / 2 + leadLength / 2;
609
+ const curveLength = leadReach * 0.1;
610
+ const notchInset = Math.min(Math.min(bodyVisualWidth, bodyLength10) * 0.18, 1);
611
+ const notchRadius = Math.min(
612
+ Math.min(bodyVisualWidth, bodyLength10) * 0.12,
613
+ 0.45
614
+ );
615
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
616
+ Array.from({ length: sidePinCount }).map((_, i) => /* @__PURE__ */ jsx(
617
+ SmdChipLead,
618
+ {
619
+ position: {
620
+ x: -leadStartOffset,
621
+ y: i * pitch - pinOffsetToCenter,
622
+ z: leadThickness / 2
623
+ },
624
+ width: leadWidth,
625
+ thickness: leadThickness,
626
+ padContactLength,
627
+ bodyDistance: leadReach,
628
+ curveLength,
629
+ height: leadHeight
630
+ },
631
+ `left-${i}`
632
+ )),
633
+ Array.from({ length: sidePinCount }).map((_, i) => /* @__PURE__ */ jsx(
634
+ SmdChipLead,
635
+ {
636
+ rotation: Math.PI,
637
+ position: {
638
+ x: leadStartOffset,
639
+ y: i * pitch - pinOffsetToCenter,
640
+ z: leadThickness / 2
641
+ },
642
+ width: leadWidth,
643
+ thickness: leadThickness,
644
+ padContactLength,
645
+ bodyDistance: leadReach,
646
+ curveLength,
647
+ height: leadHeight
648
+ },
649
+ `right-${i}`
650
+ )),
651
+ /* @__PURE__ */ jsx(
652
+ ChipBody,
653
+ {
654
+ center: { x: 0, y: 0, z: 0 },
655
+ width: bodyVisualWidth,
656
+ length: bodyLength10,
657
+ height: bodyHeight,
658
+ notchPosition: {
659
+ x: -(bodyVisualWidth / 2 - notchInset - 0.2),
660
+ y: bodyLength10 / 2 - notchInset - 0.2,
661
+ z: bodyHeight
662
+ },
663
+ notchRadius
664
+ }
665
+ )
666
+ ] });
667
+ };
668
+ var Tssop = (props) => "leadSpan" in props ? createDualRowGullWing(props) : LegacyTssop(props);
669
+
669
670
  // lib/MSOP.tsx
670
671
  var LegacyMSOP = ({
671
672
  pinCount,
@@ -1117,6 +1118,105 @@ var PinRow = ({
1117
1118
  }) });
1118
1119
  };
1119
1120
 
1121
+ // lib/utils/PhysicalQfn.tsx
1122
+ function createPhysicalQfn(p) {
1123
+ const {
1124
+ num_pins,
1125
+ bodyWidth,
1126
+ bodyLength: bodyLength10,
1127
+ bodyHeight,
1128
+ standoff,
1129
+ terminalSpanX,
1130
+ terminalSpanY,
1131
+ terminalThickness,
1132
+ padWidth,
1133
+ padLength,
1134
+ pitch,
1135
+ exposedPadWidth,
1136
+ exposedPadLength
1137
+ } = p;
1138
+ for (const key of [
1139
+ "bodyWidth",
1140
+ "bodyLength",
1141
+ "bodyHeight",
1142
+ "terminalSpanX",
1143
+ "terminalSpanY",
1144
+ "terminalThickness",
1145
+ "padWidth",
1146
+ "padLength",
1147
+ "pitch",
1148
+ "exposedPadWidth",
1149
+ "exposedPadLength"
1150
+ ])
1151
+ if (!Number.isFinite(p[key]) || p[key] <= 0)
1152
+ throw new Error(`${key} must be finite and positive`);
1153
+ if (!Number.isInteger(num_pins) || num_pins < 8 || num_pins % 4)
1154
+ throw new Error("num_pins must be divisible by four and at least eight");
1155
+ if (!Number.isFinite(standoff) || standoff < 0)
1156
+ throw new Error("standoff must be finite and nonnegative");
1157
+ const rowLength = (num_pins / 4 - 1) * pitch + padWidth;
1158
+ if (terminalThickness <= standoff || terminalThickness >= bodyHeight || padWidth >= pitch || rowLength >= Math.min(bodyWidth, bodyLength10))
1159
+ throw new Error("Invalid mold, terminal thickness or spacing");
1160
+ if (terminalSpanX < bodyWidth || terminalSpanY < bodyLength10 || terminalSpanX / 2 - padLength >= bodyWidth / 2 || terminalSpanY / 2 - padLength >= bodyLength10 / 2 || exposedPadWidth >= Math.min(bodyWidth, terminalSpanX - 2 * padLength) || exposedPadLength >= Math.min(bodyLength10, terminalSpanY - 2 * padLength) || rowLength >= Math.min(terminalSpanX, terminalSpanY) - 2 * padLength)
1161
+ throw new Error(
1162
+ "Terminals must enter the mold and clear the exposed pad and corners"
1163
+ );
1164
+ const body = /* @__PURE__ */ jsx(Translate, { z: (bodyHeight + standoff) / 2, children: /* @__PURE__ */ jsx(Cuboid, { size: [bodyWidth, bodyLength10, bodyHeight - standoff] }) });
1165
+ const radius = Math.min(bodyWidth, bodyLength10) * 0.035;
1166
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
1167
+ /* @__PURE__ */ jsx(Colorize, { color: "#353535", children: /* @__PURE__ */ jsxs(Subtract, { children: [
1168
+ body,
1169
+ /* @__PURE__ */ jsx(
1170
+ Translate,
1171
+ {
1172
+ offset: {
1173
+ x: -bodyWidth / 2 + radius * 2,
1174
+ y: bodyLength10 / 2 - radius * 2,
1175
+ z: bodyHeight
1176
+ },
1177
+ children: /* @__PURE__ */ jsx(
1178
+ Cylinder,
1179
+ {
1180
+ radius,
1181
+ height: Math.min(0.06, (bodyHeight - standoff) / 5)
1182
+ }
1183
+ )
1184
+ }
1185
+ )
1186
+ ] }) }),
1187
+ /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: Array.from({ length: num_pins }, (_, i) => {
1188
+ const side = Math.floor(i / (num_pins / 4));
1189
+ const along = ((num_pins / 4 - 1) / 2 - i % (num_pins / 4)) * pitch;
1190
+ const horizontal = side % 2 === 0;
1191
+ const sign = side < 2 ? -1 : 1;
1192
+ const across = ((horizontal ? terminalSpanX : terminalSpanY) - padLength) / 2 * sign;
1193
+ return /* @__PURE__ */ jsx(
1194
+ Translate,
1195
+ {
1196
+ offset: {
1197
+ x: horizontal ? across : along,
1198
+ y: horizontal ? along : across,
1199
+ z: terminalThickness / 2
1200
+ },
1201
+ children: /* @__PURE__ */ jsx(
1202
+ Cuboid,
1203
+ {
1204
+ size: horizontal ? [padLength, padWidth, terminalThickness] : [padWidth, padLength, terminalThickness]
1205
+ }
1206
+ )
1207
+ },
1208
+ i
1209
+ );
1210
+ }) }),
1211
+ /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: /* @__PURE__ */ jsx(Translate, { z: terminalThickness / 2, children: /* @__PURE__ */ jsx(
1212
+ Cuboid,
1213
+ {
1214
+ size: [exposedPadWidth, exposedPadLength, terminalThickness]
1215
+ }
1216
+ ) }) })
1217
+ ] });
1218
+ }
1219
+
1120
1220
  // lib/utils/getQuadCoords.ts
1121
1221
  var getQuadCoords = (params) => {
1122
1222
  const SIDES_CCW = ["left", "bottom", "right", "top"];
@@ -1205,7 +1305,7 @@ var getQuadPinMap = ({
1205
1305
  };
1206
1306
 
1207
1307
  // lib/qfn.tsx
1208
- var QFN = ({
1308
+ var LegacyQFN = ({
1209
1309
  num_pins = 16,
1210
1310
  bodyWidth = 9,
1211
1311
  bodyLength: bodyLength10 = 9,
@@ -1275,6 +1375,7 @@ var QFN = ({
1275
1375
  )
1276
1376
  ] });
1277
1377
  };
1378
+ var QFN = (props) => "bodyHeight" in props ? createPhysicalQfn(props) : LegacyQFN(props);
1278
1379
  var qfn_default = QFN;
1279
1380
 
1280
1381
  // lib/SOT-235.tsx
@@ -3187,8 +3288,143 @@ var SOT323 = () => {
3187
3288
  ] });
3188
3289
  };
3189
3290
 
3291
+ // lib/utils/PhysicalLqfp.tsx
3292
+ function createPhysicalLqfp(p) {
3293
+ const {
3294
+ pinCount,
3295
+ pitch,
3296
+ bodyWidth,
3297
+ bodyLength: bodyLength10,
3298
+ bodyHeight,
3299
+ standoff,
3300
+ leadSpanX,
3301
+ leadSpanY,
3302
+ leadWidth,
3303
+ leadThickness,
3304
+ contactLength,
3305
+ taperInset
3306
+ } = p;
3307
+ for (const key of [
3308
+ "pitch",
3309
+ "bodyWidth",
3310
+ "bodyLength",
3311
+ "bodyHeight",
3312
+ "leadSpanX",
3313
+ "leadSpanY",
3314
+ "leadWidth",
3315
+ "leadThickness",
3316
+ "contactLength"
3317
+ ])
3318
+ if (!Number.isFinite(p[key]) || p[key] <= 0)
3319
+ throw new Error(`${key} must be finite and positive`);
3320
+ for (const [name, value] of Object.entries({
3321
+ standoff,
3322
+ taperInset
3323
+ }))
3324
+ if (!Number.isFinite(value) || value < 0)
3325
+ throw new Error(`${name} must be finite and nonnegative`);
3326
+ if (!Number.isInteger(pinCount) || pinCount < 8 || pinCount % 4)
3327
+ throw new Error("pinCount must be divisible by four and at least eight");
3328
+ const moldHeight = bodyHeight - standoff;
3329
+ const reach = Math.min(leadSpanX - bodyWidth, leadSpanY - bodyLength10) / 2;
3330
+ const rowLength = (pinCount / 4 - 1) * pitch + leadWidth;
3331
+ if (moldHeight <= leadThickness * 2 || leadWidth >= pitch || rowLength >= Math.min(bodyWidth, bodyLength10) - 2 * taperInset || taperInset * 2 >= Math.min(bodyWidth, bodyLength10) || contactLength >= reach)
3332
+ throw new Error("Invalid mold, lead spacing, or terminal reach");
3333
+ const midZ = standoff + moldHeight / 2;
3334
+ const slice = Math.min(2e-3, moldHeight / 100);
3335
+ const body = /* @__PURE__ */ jsxs(Hull, { children: [
3336
+ /* @__PURE__ */ jsx(Translate, { z: standoff + slice / 2, children: /* @__PURE__ */ jsx(
3337
+ Cuboid,
3338
+ {
3339
+ size: [
3340
+ bodyWidth - 2 * taperInset,
3341
+ bodyLength10 - 2 * taperInset,
3342
+ slice
3343
+ ]
3344
+ }
3345
+ ) }),
3346
+ /* @__PURE__ */ jsx(Translate, { z: midZ, children: /* @__PURE__ */ jsx(Cuboid, { size: [bodyWidth, bodyLength10, slice] }) }),
3347
+ /* @__PURE__ */ jsx(Translate, { z: bodyHeight - slice / 2, children: /* @__PURE__ */ jsx(
3348
+ Cuboid,
3349
+ {
3350
+ size: [
3351
+ bodyWidth - 2 * taperInset,
3352
+ bodyLength10 - 2 * taperInset,
3353
+ slice
3354
+ ]
3355
+ }
3356
+ ) })
3357
+ ] });
3358
+ const dimpleRadius = Math.min(bodyWidth, bodyLength10) * 0.045;
3359
+ const dimpleDepth = Math.min(0.04, moldHeight / 10);
3360
+ const lead = (side, along) => {
3361
+ const horizontal = side % 2 === 0;
3362
+ const sign = side < 2 ? -1 : 1;
3363
+ const width10 = horizontal ? bodyWidth : bodyLength10;
3364
+ const outer = (horizontal ? leadSpanX : leadSpanY) / 2;
3365
+ const root = width10 / 2 - Math.min(width10 / 8, 0.15);
3366
+ const bendStart = outer - contactLength;
3367
+ const bendEnd = width10 / 2 + Math.min(0.08, (reach - contactLength) / 4);
3368
+ const points = [
3369
+ [outer - slice / 2, leadThickness / 2],
3370
+ [bendStart, leadThickness / 2]
3371
+ ];
3372
+ for (let i = 1; i <= 12; i++) {
3373
+ const t = i / 12;
3374
+ points.push([
3375
+ bendStart + (bendEnd - bendStart) * t,
3376
+ leadThickness / 2 + (midZ - leadThickness / 2) * t * t * (3 - 2 * t)
3377
+ ]);
3378
+ }
3379
+ points.push([root, midZ]);
3380
+ const section = ([x, z]) => /* @__PURE__ */ jsx(
3381
+ Translate,
3382
+ {
3383
+ offset: {
3384
+ x: horizontal ? sign * x : along,
3385
+ y: horizontal ? along : sign * x,
3386
+ z
3387
+ },
3388
+ children: /* @__PURE__ */ jsx(
3389
+ Cuboid,
3390
+ {
3391
+ size: horizontal ? [slice, leadWidth, leadThickness] : [leadWidth, slice, leadThickness]
3392
+ }
3393
+ )
3394
+ }
3395
+ );
3396
+ return /* @__PURE__ */ jsx(Union, { children: points.slice(1).map((point, i) => /* @__PURE__ */ jsxs(Hull, { children: [
3397
+ section(points[i]),
3398
+ section(point)
3399
+ ] }, i)) });
3400
+ };
3401
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
3402
+ /* @__PURE__ */ jsx(Colorize, { color: "#353535", children: /* @__PURE__ */ jsxs(Subtract, { children: [
3403
+ body,
3404
+ /* @__PURE__ */ jsx(
3405
+ Translate,
3406
+ {
3407
+ offset: {
3408
+ x: -bodyWidth / 2 + taperInset + dimpleRadius * 2,
3409
+ y: bodyLength10 / 2 - taperInset - dimpleRadius * 2,
3410
+ z: bodyHeight
3411
+ },
3412
+ children: /* @__PURE__ */ jsx(Cylinder, { radius: dimpleRadius, height: dimpleDepth * 2 })
3413
+ }
3414
+ )
3415
+ ] }) }),
3416
+ /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: Array.from(
3417
+ { length: pinCount },
3418
+ (_, i) => lead(
3419
+ Math.floor(i / (pinCount / 4)),
3420
+ ((pinCount / 4 - 1) / 2 - i % (pinCount / 4)) * pitch
3421
+ )
3422
+ ) })
3423
+ ] });
3424
+ }
3425
+
3190
3426
  // lib/lqfp.tsx
3191
- var LQFP = ({
3427
+ var LegacyLQFP = ({
3192
3428
  pinCount,
3193
3429
  pitch,
3194
3430
  leadWidth,
@@ -3298,6 +3534,7 @@ var LQFP = ({
3298
3534
  )
3299
3535
  ] });
3300
3536
  };
3537
+ var LQFP = (props) => "leadSpanX" in props ? createPhysicalLqfp(props) : LegacyLQFP(props);
3301
3538
 
3302
3539
  // lib/SOT-723.tsx
3303
3540
  var SOT723 = () => {