jscad-electronics 0.0.200 → 0.0.202

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
@@ -183,24 +183,24 @@ var FootprintPlatedHole = ({
183
183
  import { buttonScrewModelDefinitionSchema } from "@tscircuit/modelprinter";
184
184
 
185
185
  // lib/model-registry.ts
186
- function defineModelRenderer(model15) {
187
- return model15;
186
+ function defineModelRenderer(model17) {
187
+ return model17;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model15) {
192
- if (typeof model15.name !== "string" || !/^[a-z]+$/.test(model15.name)) {
191
+ register(model17) {
192
+ if (typeof model17.name !== "string" || !/^[a-z]+$/.test(model17.name)) {
193
193
  throw new Error(
194
194
  "Model renderer names must contain only lowercase letters"
195
195
  );
196
196
  }
197
- if (this.models.has(model15.name)) {
198
- throw new Error(`Model renderer "${model15.name}" is already registered`);
197
+ if (this.models.has(model17.name)) {
198
+ throw new Error(`Model renderer "${model17.name}" is already registered`);
199
199
  }
200
- if (model15.pads !== "none" && model15.pads !== "footprinter") {
200
+ if (model17.pads !== "none" && model17.pads !== "footprinter") {
201
201
  throw new Error('Model renderer pads must be "none" or "footprinter"');
202
202
  }
203
- const { name, schema, render: render2, pads } = model15;
203
+ const { name, schema, render: render2, pads } = model17;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -372,6 +372,301 @@ function register(registry) {
372
372
  registry.register(model);
373
373
  }
374
374
 
375
+ // lib/models/cablegrommet/register.tsx
376
+ import { cableGrommetModelDefinitionSchema } from "@tscircuit/modelprinter";
377
+
378
+ // lib/models/cablegrommet/mesh.ts
379
+ import {
380
+ cableGrommetModelPropsSchema,
381
+ getCableGrommetDimensions
382
+ } from "@tscircuit/modelprinter";
383
+ function createCableGrommetMesh(input, options = {}) {
384
+ const props = cableGrommetModelPropsSchema.parse(input);
385
+ const dimensions = getCableGrommetDimensions(props);
386
+ const inner = props.innerDiameter / 2;
387
+ const root = dimensions.grooveRootDiameter / 2;
388
+ const outer = props.outerDiameter / 2;
389
+ const requested = options.radialSegments ?? 96;
390
+ if (!Number.isInteger(requested) || requested < 12 || requested > 4096 || requested % 4 !== 0)
391
+ throw new Error(
392
+ "Grommet radial segments must be a multiple of four in [12,4096]"
393
+ );
394
+ const wallAngle = Math.acos((inner + root) / (2 * root));
395
+ const segments = Math.max(requested, 4 * Math.ceil(Math.PI / wallAngle / 4));
396
+ if (!Number.isFinite(segments) || segments > 4096)
397
+ throw new Error(
398
+ "Grommet wall exceeds mesh resolution limit (4096 segments)"
399
+ );
400
+ const section = [
401
+ [inner, -props.height / 2],
402
+ [outer, -props.height / 2],
403
+ [outer, dimensions.grooveStartZ],
404
+ [root, dimensions.grooveStartZ],
405
+ [root, dimensions.grooveEndZ],
406
+ [outer, dimensions.grooveEndZ],
407
+ [outer, props.height / 2],
408
+ [inner, props.height / 2]
409
+ ];
410
+ const positions = [];
411
+ const indices = [];
412
+ for (const [radius, z] of section)
413
+ for (let sample = 0; sample < segments; sample++) {
414
+ const angle = sample * 2 * Math.PI / segments;
415
+ positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
416
+ }
417
+ for (let ring = 0; ring < section.length; ring++) {
418
+ const a = ring * segments;
419
+ const b = (ring + 1) % section.length * segments;
420
+ for (let sample = 0; sample < segments; sample++) {
421
+ const next = (sample + 1) % segments;
422
+ indices.push(
423
+ a + sample,
424
+ a + next,
425
+ b + next,
426
+ a + sample,
427
+ b + next,
428
+ b + sample
429
+ );
430
+ }
431
+ }
432
+ return { positions, indices };
433
+ }
434
+
435
+ // lib/models/cablegrommet/CableGrommet.tsx
436
+ function createCableGrommetGeom(input) {
437
+ return indexedMeshToGeom3(createCableGrommetMesh(input));
438
+ }
439
+ function CableGrommet({
440
+ color = "#343943",
441
+ ...props
442
+ }) {
443
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createCableGrommetGeom(props) }) });
444
+ }
445
+
446
+ // lib/models/cablegrommet/register.tsx
447
+ var model2 = defineModelRenderer({
448
+ name: "cablegrommet",
449
+ schema: cableGrommetModelDefinitionSchema,
450
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(CableGrommet, { ...props }),
451
+ pads: "none"
452
+ });
453
+ function register2(registry) {
454
+ registry.register(model2);
455
+ }
456
+
457
+ // lib/models/compressionspring/register.tsx
458
+ import { compressionSpringModelDefinitionSchema } from "@tscircuit/modelprinter";
459
+
460
+ // lib/models/compressionspring/mesh.ts
461
+ import {
462
+ compressionSpringModelPropsSchema,
463
+ getCompressionSpringCenterlinePoint,
464
+ getCompressionSpringDimensions
465
+ } from "@tscircuit/modelprinter";
466
+
467
+ // lib/mechanical/clip-mesh-to-z-range.ts
468
+ import earcut from "earcut";
469
+ function clipMeshToZRange(mesh, lower, upper) {
470
+ const originals = [];
471
+ const tolerance = 32 * Number.EPSILON * (upper - lower);
472
+ for (let index = 0; index < mesh.positions.length / 3; index++)
473
+ originals.push({
474
+ key: `v${index}`,
475
+ coordinates: [
476
+ mesh.positions[index * 3],
477
+ mesh.positions[index * 3 + 1],
478
+ Math.abs(mesh.positions[index * 3 + 2] - lower) <= tolerance ? lower : Math.abs(mesh.positions[index * 3 + 2] - upper) <= tolerance ? upper : mesh.positions[index * 3 + 2]
479
+ ]
480
+ });
481
+ const intersections = /* @__PURE__ */ new Map();
482
+ const crossing = (a, b, plane) => {
483
+ if (a.coordinates[2] === plane) return a;
484
+ if (b.coordinates[2] === plane) return b;
485
+ const [first, second] = a.key < b.key ? [a, b] : [b, a];
486
+ const key = `${plane}:${first.key}:${second.key}`;
487
+ let point = intersections.get(key);
488
+ if (!point) {
489
+ const fraction = (plane - first.coordinates[2]) / (second.coordinates[2] - first.coordinates[2]);
490
+ point = {
491
+ key,
492
+ coordinates: [
493
+ first.coordinates[0] + fraction * (second.coordinates[0] - first.coordinates[0]),
494
+ first.coordinates[1] + fraction * (second.coordinates[1] - first.coordinates[1]),
495
+ plane
496
+ ]
497
+ };
498
+ intersections.set(key, point);
499
+ }
500
+ return point;
501
+ };
502
+ const clip = (polygon, plane, keepAbove) => {
503
+ const result = [];
504
+ const inside = (point) => keepAbove ? point.coordinates[2] >= plane : point.coordinates[2] <= plane;
505
+ for (let index = 0; index < polygon.length; index++) {
506
+ const a = polygon[index];
507
+ const b = polygon[(index + 1) % polygon.length];
508
+ if (inside(a)) result.push(a);
509
+ if (inside(a) !== inside(b)) result.push(crossing(a, b, plane));
510
+ }
511
+ return result.filter(
512
+ (point, index) => point.key !== result[(index + result.length - 1) % result.length]?.key
513
+ );
514
+ };
515
+ const positions = [];
516
+ const indices = [];
517
+ const pointIndices = /* @__PURE__ */ new Map();
518
+ const vertex = (point) => {
519
+ let index = pointIndices.get(point.key);
520
+ if (index === void 0) {
521
+ index = positions.length / 3;
522
+ positions.push(...point.coordinates);
523
+ pointIndices.set(point.key, index);
524
+ }
525
+ return index;
526
+ };
527
+ for (let index = 0; index < mesh.indices.length; index += 3) {
528
+ const triangle = mesh.indices.slice(index, index + 3).map((i) => originals[i]);
529
+ const polygon = clip(clip(triangle, lower, true), upper, false);
530
+ for (let corner = 1; corner + 1 < polygon.length; corner++) {
531
+ const points = [polygon[0], polygon[corner], polygon[corner + 1]];
532
+ if (new Set(points.map((point) => point.key)).size === 3)
533
+ indices.push(...points.map(vertex));
534
+ }
535
+ }
536
+ const edges = /* @__PURE__ */ new Map();
537
+ for (let index = 0; index < indices.length; index += 3)
538
+ for (let side = 0; side < 3; side++) {
539
+ const from = indices[index + side];
540
+ const to = indices[index + (side + 1) % 3];
541
+ const key = `${Math.min(from, to)},${Math.max(from, to)}`;
542
+ const prior = edges.get(key);
543
+ if (prior) prior.count++;
544
+ else edges.set(key, { from, to, count: 1 });
545
+ }
546
+ const boundary = [...edges.values()].filter((edge) => edge.count === 1);
547
+ const outgoing = new Map(boundary.map(({ from, to }) => [from, to]));
548
+ if (outgoing.size !== boundary.length)
549
+ throw new Error("Ground clipping produced an ambiguous boundary");
550
+ while (outgoing.size > 0) {
551
+ const start = outgoing.keys().next().value;
552
+ const loop = [];
553
+ let current = start;
554
+ do {
555
+ loop.push(current);
556
+ const next = outgoing.get(current);
557
+ if (next === void 0)
558
+ throw new Error("Ground clipping produced an open boundary");
559
+ outgoing.delete(current);
560
+ current = next;
561
+ } while (current !== start);
562
+ const plane = positions[3 * start + 2];
563
+ if (plane !== lower && plane !== upper || loop.some((i) => positions[3 * i + 2] !== plane))
564
+ throw new Error("Ground clipping boundary must lie on an end plane");
565
+ const coordinates = loop.flatMap((i) => [
566
+ positions[3 * i],
567
+ positions[3 * i + 1]
568
+ ]);
569
+ const cap = earcut(coordinates);
570
+ for (let index = 0; index < cap.length; index += 3) {
571
+ const a = loop[cap[index]];
572
+ let b = loop[cap[index + 1]];
573
+ let c = loop[cap[index + 2]];
574
+ const cross = (positions[b * 3] - positions[a * 3]) * (positions[c * 3 + 1] - positions[a * 3 + 1]) - (positions[b * 3 + 1] - positions[a * 3 + 1]) * (positions[c * 3] - positions[a * 3]);
575
+ if (plane === lower && cross > 0 || plane === upper && cross < 0)
576
+ [b, c] = [c, b];
577
+ indices.push(a, b, c);
578
+ }
579
+ }
580
+ return { positions, indices };
581
+ }
582
+
583
+ // lib/models/compressionspring/mesh.ts
584
+ function createCompressionSpringMesh(input, options = {}) {
585
+ const props = compressionSpringModelPropsSchema.parse(input);
586
+ const dimensions = getCompressionSpringDimensions(props);
587
+ const segmentsPerTurn = options.segmentsPerTurn ?? 64;
588
+ const wireSegments = options.wireSegments ?? 24;
589
+ for (const [name, value, minimum, maximum] of [
590
+ ["segmentsPerTurn", segmentsPerTurn, 16, 256],
591
+ ["wireSegments", wireSegments, 8, 64]
592
+ ])
593
+ if (!Number.isInteger(value) || value < minimum || value > maximum || value % 4 !== 0)
594
+ throw new Error(
595
+ `${name} must be a multiple of four in [${minimum},${maximum}]`
596
+ );
597
+ const steps = props.totalTurns * segmentsPerTurn;
598
+ if (!Number.isSafeInteger(steps) || (steps + 1) * wireSegments > 25e4)
599
+ throw new Error("Spring exceeds mesh resolution limit (250000 vertices)");
600
+ const scale = Math.max(props.outerDiameter, props.freeLength);
601
+ if (dimensions.activePitch - props.wireDiameter <= scale * 1e-10 || props.wireDiameter <= scale * 1e-10 || dimensions.insideDiameter <= scale * 1e-10)
602
+ throw new Error("Spring clearance exceeds mesh resolution limit");
603
+ const positions = [];
604
+ const indices = [];
605
+ const wireRadius = props.wireDiameter / 2;
606
+ for (let step = 0; step <= steps; step++) {
607
+ const center = getCompressionSpringCenterlinePoint(
608
+ props,
609
+ step / segmentsPerTurn
610
+ );
611
+ const meanRadius = Math.hypot(center.x, center.y);
612
+ for (let sample = 0; sample < wireSegments; sample++) {
613
+ const angle = sample * 2 * Math.PI / wireSegments;
614
+ const cosine = sample === wireSegments / 4 || sample === 3 * wireSegments / 4 ? 0 : Math.cos(angle);
615
+ const sine = sample === 0 || sample === wireSegments / 2 ? 0 : Math.sin(angle);
616
+ const radialOffset = wireRadius * cosine;
617
+ positions.push(
618
+ center.x + radialOffset * center.x / meanRadius,
619
+ center.y + radialOffset * center.y / meanRadius,
620
+ center.z + wireRadius * sine
621
+ );
622
+ }
623
+ }
624
+ const triangle = (a, b, c) => {
625
+ if (props.hand === "left") indices.push(a, c, b);
626
+ else indices.push(a, b, c);
627
+ };
628
+ for (let step = 0; step < steps; step++)
629
+ for (let sample = 0; sample < wireSegments; sample++) {
630
+ const next = (sample + 1) % wireSegments;
631
+ const a = step * wireSegments;
632
+ const b = (step + 1) * wireSegments;
633
+ triangle(a + sample, b + sample, b + next);
634
+ triangle(a + sample, b + next, a + next);
635
+ }
636
+ for (let corner = 1; corner + 1 < wireSegments; corner++) {
637
+ triangle(0, corner, corner + 1);
638
+ const end = steps * wireSegments;
639
+ triangle(end, end + corner + 1, end + corner);
640
+ }
641
+ return clipMeshToZRange(
642
+ { positions, indices },
643
+ dimensions.lowerBearingZ,
644
+ dimensions.upperBearingZ
645
+ );
646
+ }
647
+
648
+ // lib/models/compressionspring/CompressionSpring.tsx
649
+ function createCompressionSpringGeom(input) {
650
+ return indexedMeshToGeom3(createCompressionSpringMesh(input));
651
+ }
652
+ function CompressionSpring({
653
+ color = "#737e8f",
654
+ ...props
655
+ }) {
656
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createCompressionSpringGeom(props) }) });
657
+ }
658
+
659
+ // lib/models/compressionspring/register.tsx
660
+ var model3 = defineModelRenderer({
661
+ name: "compressionspring",
662
+ schema: compressionSpringModelDefinitionSchema,
663
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(CompressionSpring, { ...props }),
664
+ pads: "none"
665
+ });
666
+ function register3(registry) {
667
+ registry.register(model3);
668
+ }
669
+
375
670
  // lib/models/flangedbushing/register.tsx
376
671
  import { flangedBushingModelDefinitionSchema } from "@tscircuit/modelprinter";
377
672
 
@@ -425,14 +720,14 @@ function FlangedBushing({
425
720
  }
426
721
 
427
722
  // lib/models/flangedbushing/register.tsx
428
- var model2 = defineModelRenderer({
723
+ var model4 = defineModelRenderer({
429
724
  name: "flangedbushing",
430
725
  schema: flangedBushingModelDefinitionSchema,
431
726
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlangedBushing, { ...props }),
432
727
  pads: "none"
433
728
  });
434
- function register2(registry) {
435
- registry.register(model2);
729
+ function register4(registry) {
730
+ registry.register(model4);
436
731
  }
437
732
 
438
733
  // lib/models/flatheadscrew/register.tsx
@@ -565,14 +860,14 @@ function FlatHeadScrew({
565
860
  }
566
861
 
567
862
  // lib/models/flatheadscrew/register.tsx
568
- var model3 = defineModelRenderer({
863
+ var model5 = defineModelRenderer({
569
864
  name: "flatheadscrew",
570
865
  schema: flatHeadScrewModelDefinitionSchema,
571
866
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlatHeadScrew, { ...props }),
572
867
  pads: "none"
573
868
  });
574
- function register3(registry) {
575
- registry.register(model3);
869
+ function register5(registry) {
870
+ registry.register(model5);
576
871
  }
577
872
 
578
873
  // lib/models/flexscreen/register.tsx
@@ -1250,14 +1545,14 @@ var FlexScreen = (props) => {
1250
1545
  };
1251
1546
 
1252
1547
  // lib/models/flexscreen/register.tsx
1253
- var model4 = defineModelRenderer({
1548
+ var model6 = defineModelRenderer({
1254
1549
  name: "flexscreen",
1255
1550
  schema: flexScreenModelDefinitionSchema,
1256
1551
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlexScreen, { ...props }),
1257
1552
  pads: "footprinter"
1258
1553
  });
1259
- function register4(registry) {
1260
- registry.register(model4);
1554
+ function register6(registry) {
1555
+ registry.register(model6);
1261
1556
  }
1262
1557
 
1263
1558
  // lib/models/helicalgear/register.tsx
@@ -1274,7 +1569,7 @@ import {
1274
1569
  getSpurGearDimensions,
1275
1570
  spurGearModelPropsSchema
1276
1571
  } from "@tscircuit/modelprinter";
1277
- import earcut from "earcut";
1572
+ import earcut2 from "earcut";
1278
1573
  function createSpurGearMesh(input) {
1279
1574
  return createTwistedSpurGearMesh(input);
1280
1575
  }
@@ -1380,7 +1675,7 @@ function createTwistedSpurGearMesh(input, twist = 0, segmentsPerTurn = 32) {
1380
1675
  };
1381
1676
  const cap = (outer, outerStart, upward, inner) => {
1382
1677
  const points = inner ? [...outer, ...inner.points] : outer;
1383
- const triangles = earcut(
1678
+ const triangles = earcut2(
1384
1679
  points.flatMap(([x, y]) => [x, y]),
1385
1680
  inner ? [outer.length] : []
1386
1681
  );
@@ -1463,14 +1758,14 @@ function HelicalGear({ color = "#737e8f", ...props }) {
1463
1758
  }
1464
1759
 
1465
1760
  // lib/models/helicalgear/register.tsx
1466
- var model5 = defineModelRenderer({
1761
+ var model7 = defineModelRenderer({
1467
1762
  name: "helicalgear",
1468
1763
  schema: helicalGearModelDefinitionSchema,
1469
1764
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HelicalGear, { ...props }),
1470
1765
  pads: "none"
1471
1766
  });
1472
- function register5(registry) {
1473
- registry.register(model5);
1767
+ function register7(registry) {
1768
+ registry.register(model7);
1474
1769
  }
1475
1770
 
1476
1771
  // lib/models/hexbolt/register.tsx
@@ -1611,14 +1906,14 @@ function HexBolt({ color = "#737e8f", ...props }) {
1611
1906
  }
1612
1907
 
1613
1908
  // lib/models/hexbolt/register.tsx
1614
- var model6 = defineModelRenderer({
1909
+ var model8 = defineModelRenderer({
1615
1910
  name: "hexbolt",
1616
1911
  schema: hexBoltModelDefinitionSchema,
1617
1912
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexBolt, { ...props }),
1618
1913
  pads: "none"
1619
1914
  });
1620
- function register6(registry) {
1621
- registry.register(model6);
1915
+ function register8(registry) {
1916
+ registry.register(model8);
1622
1917
  }
1623
1918
 
1624
1919
  // lib/models/hexnut/register.tsx
@@ -1741,14 +2036,14 @@ function HexNut({ color = "#737e8f", ...props }) {
1741
2036
  }
1742
2037
 
1743
2038
  // lib/models/hexnut/register.tsx
1744
- var model7 = defineModelRenderer({
2039
+ var model9 = defineModelRenderer({
1745
2040
  name: "hexnut",
1746
2041
  schema: hexNutModelDefinitionSchema,
1747
2042
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexNut, { ...props }),
1748
2043
  pads: "none"
1749
2044
  });
1750
- function register7(registry) {
1751
- registry.register(model7);
2045
+ function register9(registry) {
2046
+ registry.register(model9);
1752
2047
  }
1753
2048
 
1754
2049
  // lib/models/hexsocketbolt/register.tsx
@@ -1860,14 +2155,14 @@ function HexSocketBolt({
1860
2155
  }
1861
2156
 
1862
2157
  // lib/models/hexsocketbolt/register.tsx
1863
- var model8 = defineModelRenderer({
2158
+ var model10 = defineModelRenderer({
1864
2159
  name: "hexsocketbolt",
1865
2160
  schema: hexSocketBoltModelDefinitionSchema,
1866
2161
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexSocketBolt, { ...props }),
1867
2162
  pads: "none"
1868
2163
  });
1869
- function register8(registry) {
1870
- registry.register(model8);
2164
+ function register10(registry) {
2165
+ registry.register(model10);
1871
2166
  }
1872
2167
 
1873
2168
  // lib/models/nema/register.tsx
@@ -2136,14 +2431,14 @@ var NEMA17 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 17
2136
2431
  var NEMA23 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 23 });
2137
2432
 
2138
2433
  // lib/models/nema/register.tsx
2139
- var model9 = defineModelRenderer({
2434
+ var model11 = defineModelRenderer({
2140
2435
  name: "nema",
2141
2436
  schema: nemaMotorModelDefinitionSchema,
2142
2437
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(NemaMotor, { ...props }),
2143
2438
  pads: "none"
2144
2439
  });
2145
- function register9(registry) {
2146
- registry.register(model9);
2440
+ function register11(registry) {
2441
+ registry.register(model11);
2147
2442
  }
2148
2443
 
2149
2444
  // lib/models/panscrew/register.tsx
@@ -2355,14 +2650,14 @@ function PanScrew({ color = "#737e8f", ...props }) {
2355
2650
  }
2356
2651
 
2357
2652
  // lib/models/panscrew/register.tsx
2358
- var model10 = defineModelRenderer({
2653
+ var model12 = defineModelRenderer({
2359
2654
  name: "panscrew",
2360
2655
  schema: panScrewModelDefinitionSchema,
2361
2656
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PanScrew, { ...props }),
2362
2657
  pads: "none"
2363
2658
  });
2364
- function register10(registry) {
2365
- registry.register(model10);
2659
+ function register12(registry) {
2660
+ registry.register(model12);
2366
2661
  }
2367
2662
 
2368
2663
  // lib/models/plainbushing/register.tsx
@@ -2425,21 +2720,21 @@ function PlainBushing({
2425
2720
  }
2426
2721
 
2427
2722
  // lib/models/plainbushing/register.tsx
2428
- var model11 = defineModelRenderer({
2723
+ var model13 = defineModelRenderer({
2429
2724
  name: "plainbushing",
2430
2725
  schema: plainBushingModelDefinitionSchema,
2431
2726
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PlainBushing, { ...props }),
2432
2727
  pads: "none"
2433
2728
  });
2434
- function register11(registry) {
2435
- registry.register(model11);
2729
+ function register13(registry) {
2730
+ registry.register(model13);
2436
2731
  }
2437
2732
 
2438
2733
  // lib/models/sheetmetal/register.tsx
2439
2734
  import { sheetMetalModelDefinitionSchema } from "@tscircuit/modelprinter";
2440
2735
 
2441
2736
  // lib/mechanical/sheet-metal-mesh.ts
2442
- import earcut2 from "earcut";
2737
+ import earcut3 from "earcut";
2443
2738
  import {
2444
2739
  sheetMetalModelPropsSchema
2445
2740
  } from "@tscircuit/modelprinter";
@@ -2507,7 +2802,7 @@ function createSheetMetalMesh(input) {
2507
2802
  const loops = [outline, ...holes.map((hole) => [...hole].reverse())];
2508
2803
  const points = loops.flat();
2509
2804
  const starts = holes.map((_, i) => 4 + i * 64);
2510
- const triangles = earcut2(
2805
+ const triangles = earcut3(
2511
2806
  points.flatMap((p) => [p.u, p.v]),
2512
2807
  starts
2513
2808
  );
@@ -2592,14 +2887,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
2592
2887
  }
2593
2888
 
2594
2889
  // lib/models/sheetmetal/register.tsx
2595
- var model12 = defineModelRenderer({
2890
+ var model14 = defineModelRenderer({
2596
2891
  name: "sheetmetal",
2597
2892
  schema: sheetMetalModelDefinitionSchema,
2598
2893
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
2599
2894
  pads: "none"
2600
2895
  });
2601
- function register12(registry) {
2602
- registry.register(model12);
2896
+ function register14(registry) {
2897
+ registry.register(model14);
2603
2898
  }
2604
2899
 
2605
2900
  // lib/models/spurgear/register.tsx
@@ -2614,14 +2909,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
2614
2909
  }
2615
2910
 
2616
2911
  // lib/models/spurgear/register.tsx
2617
- var model13 = defineModelRenderer({
2912
+ var model15 = defineModelRenderer({
2618
2913
  name: "spurgear",
2619
2914
  schema: spurGearModelDefinitionSchema,
2620
2915
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
2621
2916
  pads: "none"
2622
2917
  });
2623
- function register13(registry) {
2624
- registry.register(model13);
2918
+ function register15(registry) {
2919
+ registry.register(model15);
2625
2920
  }
2626
2921
 
2627
2922
  // lib/models/wormgear/register.tsx
@@ -2632,7 +2927,7 @@ import {
2632
2927
  getWormGearDimensions,
2633
2928
  wormGearModelPropsSchema
2634
2929
  } from "@tscircuit/modelprinter";
2635
- import earcut3 from "earcut";
2930
+ import earcut4 from "earcut";
2636
2931
  var createWormGearMesh = (input) => {
2637
2932
  const props = wormGearModelPropsSchema.parse(input);
2638
2933
  const { outsideDiameter, rootDiameter, axialPitch, lead, toothThickness } = getWormGearDimensions(props);
@@ -2785,7 +3080,7 @@ var createWormGearMesh = (input) => {
2785
3080
  positions[vertex * 3],
2786
3081
  positions[vertex * 3 + 1]
2787
3082
  ]);
2788
- const triangles = earcut3(flat, [count], 2);
3083
+ const triangles = earcut4(flat, [count], 2);
2789
3084
  for (let index = 0; index < triangles.length; index += 3) {
2790
3085
  const a = vertices[triangles[index]];
2791
3086
  const b = vertices[triangles[index + 1]];
@@ -2813,14 +3108,14 @@ function WormGear({ color = "#737e8f", ...props }) {
2813
3108
  }
2814
3109
 
2815
3110
  // lib/models/wormgear/register.tsx
2816
- var model14 = defineModelRenderer({
3111
+ var model16 = defineModelRenderer({
2817
3112
  name: "wormgear",
2818
3113
  schema: wormGearModelDefinitionSchema,
2819
3114
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
2820
3115
  pads: "none"
2821
3116
  });
2822
- function register14(registry) {
2823
- registry.register(model14);
3117
+ function register16(registry) {
3118
+ registry.register(model16);
2824
3119
  }
2825
3120
 
2826
3121
  // lib/generated/model-renderers.ts
@@ -2839,6 +3134,8 @@ function registerAllModelRenderers(registry) {
2839
3134
  register12(registry);
2840
3135
  register13(registry);
2841
3136
  register14(registry);
3137
+ register15(registry);
3138
+ register16(registry);
2842
3139
  }
2843
3140
 
2844
3141
  // lib/default-model-registry.ts
@@ -10395,10 +10692,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
10395
10692
  var Footprinter3d = ({ footprint }) => {
10396
10693
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
10397
10694
  if (mp3.getModelNames().includes(modelFn)) {
10398
- const model15 = mp3.string(footprint).json();
10399
- const renderer = modelRendererRegistry.get(model15.fn);
10695
+ const model17 = mp3.string(footprint).json();
10696
+ const renderer = modelRendererRegistry.get(model17.fn);
10400
10697
  if (renderer) {
10401
- return renderer.render(model15);
10698
+ return renderer.render(model17);
10402
10699
  }
10403
10700
  }
10404
10701
  let normalizedFootprint = footprint;
@@ -11350,6 +11647,8 @@ function createJSCADRenderer(jscad4) {
11350
11647
  }
11351
11648
  export {
11352
11649
  ButtonScrew,
11650
+ CableGrommet,
11651
+ CompressionSpring,
11353
11652
  FlangedBushing,
11354
11653
  FlatHeadScrew,
11355
11654
  Fragment,
@@ -11369,6 +11668,10 @@ export {
11369
11668
  convertCSGToThreeGeom,
11370
11669
  createButtonScrewGeom,
11371
11670
  createButtonScrewMesh,
11671
+ createCableGrommetGeom,
11672
+ createCableGrommetMesh,
11673
+ createCompressionSpringGeom,
11674
+ createCompressionSpringMesh,
11372
11675
  createFlangedBushingGeom,
11373
11676
  createFlangedBushingMesh,
11374
11677
  createFlatHeadScrewGeom,