jscad-electronics 0.0.201 → 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.d.ts CHANGED
@@ -3,7 +3,7 @@ import { BufferGeometry } from 'three';
3
3
  import * as jscadModeling from '@jscad/modeling';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as _jscad_modeling_src_geometries_types from '@jscad/modeling/src/geometries/types';
6
- import { ButtonScrewModelPropsInput, CableGrommetModelPropsInput, FlangedBushingModelPropsInput, FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexNutModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, PlainBushingModelPropsInput, SheetMetalModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
6
+ import { ButtonScrewModelPropsInput, CableGrommetModelPropsInput, CompressionSpringModelPropsInput, FlangedBushingModelPropsInput, FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexNutModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, PlainBushingModelPropsInput, SheetMetalModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
7
7
 
8
8
  type VNode = {
9
9
  type: any;
@@ -62,6 +62,23 @@ type CableGrommetProps = CableGrommetModelPropsInput & {
62
62
  declare function createCableGrommetGeom(input: CableGrommetModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
63
63
  declare function CableGrommet({ color, ...props }: CableGrommetProps): react_jsx_runtime.JSX.Element;
64
64
 
65
+ interface CompressionSpringMesh {
66
+ positions: number[];
67
+ indices: number[];
68
+ }
69
+ interface CompressionSpringMeshOptions {
70
+ segmentsPerTurn?: number;
71
+ wireSegments?: number;
72
+ }
73
+ /** Imported piecewise centerline, radial/axial wire sections, planar ground ends. */
74
+ declare function createCompressionSpringMesh(input: CompressionSpringModelPropsInput, options?: CompressionSpringMeshOptions): CompressionSpringMesh;
75
+
76
+ type CompressionSpringProps = CompressionSpringModelPropsInput & {
77
+ color?: string;
78
+ };
79
+ declare function createCompressionSpringGeom(input: CompressionSpringModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
80
+ declare function CompressionSpring({ color, ...props }: CompressionSpringProps): react_jsx_runtime.JSX.Element;
81
+
65
82
  /** Shared ring vertices and outward counterclockwise triangles, in millimeters. */
66
83
  interface FlangedBushingMesh {
67
84
  positions: number[];
@@ -280,4 +297,4 @@ declare function createJSCADRenderer(jscad: typeof jscadModeling): {
280
297
  };
281
298
  };
282
299
 
283
- export { ButtonScrew, type ButtonScrewMesh, type ButtonScrewMeshOptions, type ButtonScrewProps, CableGrommet, type CableGrommetMesh, type CableGrommetMeshOptions, type CableGrommetProps, type ColoredGeom, FlangedBushing, type FlangedBushingMesh, type FlangedBushingProps, FlatHeadScrew, type FlatHeadScrewMesh, type FlatHeadScrewMeshOptions, type FlatHeadScrewProps, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, HexBolt, type HexBoltMesh, type HexBoltMeshOptions, type HexBoltProps, HexNut, type HexNutMesh, type HexNutMeshOptions, type HexNutProps, HexSocketBolt, type HexSocketBoltMesh, type HexSocketBoltProps, NEMA17, NEMA23, NEMA8, type NemaFrameMotorProps, NemaMotor, type NemaMotorProps, PanScrew, type PanScrewMesh, type PanScrewMeshOptions, type PanScrewProps, PlainBushing, type PlainBushingMesh, type PlainBushingProps, type RenderResult, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, type VNode, WormGear, type WormGearMesh, type WormGearProps, convertCSGToThreeGeom, createButtonScrewGeom, createButtonScrewMesh, createCableGrommetGeom, createCableGrommetMesh, createFlangedBushingGeom, createFlangedBushingMesh, createFlatHeadScrewGeom, createFlatHeadScrewMesh, createHelicalGearGeom, createHelicalGearMesh, createHexBoltGeom, createHexBoltMesh, createHexNutGeom, createHexNutMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createPanScrewGeom, createPanScrewMesh, createPlainBushingGeom, createPlainBushingMesh, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
300
+ export { ButtonScrew, type ButtonScrewMesh, type ButtonScrewMeshOptions, type ButtonScrewProps, CableGrommet, type CableGrommetMesh, type CableGrommetMeshOptions, type CableGrommetProps, type ColoredGeom, CompressionSpring, type CompressionSpringMesh, type CompressionSpringMeshOptions, type CompressionSpringProps, FlangedBushing, type FlangedBushingMesh, type FlangedBushingProps, FlatHeadScrew, type FlatHeadScrewMesh, type FlatHeadScrewMeshOptions, type FlatHeadScrewProps, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, HexBolt, type HexBoltMesh, type HexBoltMeshOptions, type HexBoltProps, HexNut, type HexNutMesh, type HexNutMeshOptions, type HexNutProps, HexSocketBolt, type HexSocketBoltMesh, type HexSocketBoltProps, NEMA17, NEMA23, NEMA8, type NemaFrameMotorProps, NemaMotor, type NemaMotorProps, PanScrew, type PanScrewMesh, type PanScrewMeshOptions, type PanScrewProps, PlainBushing, type PlainBushingMesh, type PlainBushingProps, type RenderResult, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, type VNode, WormGear, type WormGearMesh, type WormGearProps, convertCSGToThreeGeom, createButtonScrewGeom, createButtonScrewMesh, createCableGrommetGeom, createCableGrommetMesh, createCompressionSpringGeom, createCompressionSpringMesh, createFlangedBushingGeom, createFlangedBushingMesh, createFlatHeadScrewGeom, createFlatHeadScrewMesh, createHelicalGearGeom, createHelicalGearMesh, createHexBoltGeom, createHexBoltMesh, createHexNutGeom, createHexNutMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createPanScrewGeom, createPanScrewMesh, createPlainBushingGeom, createPlainBushingMesh, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
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(model16) {
187
- return model16;
186
+ function defineModelRenderer(model17) {
187
+ return model17;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model16) {
192
- if (typeof model16.name !== "string" || !/^[a-z]+$/.test(model16.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(model16.name)) {
198
- throw new Error(`Model renderer "${model16.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 (model16.pads !== "none" && model16.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 } = model16;
203
+ const { name, schema, render: render2, pads } = model17;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -454,6 +454,219 @@ function register2(registry) {
454
454
  registry.register(model2);
455
455
  }
456
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
+
457
670
  // lib/models/flangedbushing/register.tsx
458
671
  import { flangedBushingModelDefinitionSchema } from "@tscircuit/modelprinter";
459
672
 
@@ -507,14 +720,14 @@ function FlangedBushing({
507
720
  }
508
721
 
509
722
  // lib/models/flangedbushing/register.tsx
510
- var model3 = defineModelRenderer({
723
+ var model4 = defineModelRenderer({
511
724
  name: "flangedbushing",
512
725
  schema: flangedBushingModelDefinitionSchema,
513
726
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlangedBushing, { ...props }),
514
727
  pads: "none"
515
728
  });
516
- function register3(registry) {
517
- registry.register(model3);
729
+ function register4(registry) {
730
+ registry.register(model4);
518
731
  }
519
732
 
520
733
  // lib/models/flatheadscrew/register.tsx
@@ -647,14 +860,14 @@ function FlatHeadScrew({
647
860
  }
648
861
 
649
862
  // lib/models/flatheadscrew/register.tsx
650
- var model4 = defineModelRenderer({
863
+ var model5 = defineModelRenderer({
651
864
  name: "flatheadscrew",
652
865
  schema: flatHeadScrewModelDefinitionSchema,
653
866
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlatHeadScrew, { ...props }),
654
867
  pads: "none"
655
868
  });
656
- function register4(registry) {
657
- registry.register(model4);
869
+ function register5(registry) {
870
+ registry.register(model5);
658
871
  }
659
872
 
660
873
  // lib/models/flexscreen/register.tsx
@@ -1332,14 +1545,14 @@ var FlexScreen = (props) => {
1332
1545
  };
1333
1546
 
1334
1547
  // lib/models/flexscreen/register.tsx
1335
- var model5 = defineModelRenderer({
1548
+ var model6 = defineModelRenderer({
1336
1549
  name: "flexscreen",
1337
1550
  schema: flexScreenModelDefinitionSchema,
1338
1551
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlexScreen, { ...props }),
1339
1552
  pads: "footprinter"
1340
1553
  });
1341
- function register5(registry) {
1342
- registry.register(model5);
1554
+ function register6(registry) {
1555
+ registry.register(model6);
1343
1556
  }
1344
1557
 
1345
1558
  // lib/models/helicalgear/register.tsx
@@ -1356,7 +1569,7 @@ import {
1356
1569
  getSpurGearDimensions,
1357
1570
  spurGearModelPropsSchema
1358
1571
  } from "@tscircuit/modelprinter";
1359
- import earcut from "earcut";
1572
+ import earcut2 from "earcut";
1360
1573
  function createSpurGearMesh(input) {
1361
1574
  return createTwistedSpurGearMesh(input);
1362
1575
  }
@@ -1462,7 +1675,7 @@ function createTwistedSpurGearMesh(input, twist = 0, segmentsPerTurn = 32) {
1462
1675
  };
1463
1676
  const cap = (outer, outerStart, upward, inner) => {
1464
1677
  const points = inner ? [...outer, ...inner.points] : outer;
1465
- const triangles = earcut(
1678
+ const triangles = earcut2(
1466
1679
  points.flatMap(([x, y]) => [x, y]),
1467
1680
  inner ? [outer.length] : []
1468
1681
  );
@@ -1545,14 +1758,14 @@ function HelicalGear({ color = "#737e8f", ...props }) {
1545
1758
  }
1546
1759
 
1547
1760
  // lib/models/helicalgear/register.tsx
1548
- var model6 = defineModelRenderer({
1761
+ var model7 = defineModelRenderer({
1549
1762
  name: "helicalgear",
1550
1763
  schema: helicalGearModelDefinitionSchema,
1551
1764
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HelicalGear, { ...props }),
1552
1765
  pads: "none"
1553
1766
  });
1554
- function register6(registry) {
1555
- registry.register(model6);
1767
+ function register7(registry) {
1768
+ registry.register(model7);
1556
1769
  }
1557
1770
 
1558
1771
  // lib/models/hexbolt/register.tsx
@@ -1693,14 +1906,14 @@ function HexBolt({ color = "#737e8f", ...props }) {
1693
1906
  }
1694
1907
 
1695
1908
  // lib/models/hexbolt/register.tsx
1696
- var model7 = defineModelRenderer({
1909
+ var model8 = defineModelRenderer({
1697
1910
  name: "hexbolt",
1698
1911
  schema: hexBoltModelDefinitionSchema,
1699
1912
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexBolt, { ...props }),
1700
1913
  pads: "none"
1701
1914
  });
1702
- function register7(registry) {
1703
- registry.register(model7);
1915
+ function register8(registry) {
1916
+ registry.register(model8);
1704
1917
  }
1705
1918
 
1706
1919
  // lib/models/hexnut/register.tsx
@@ -1823,14 +2036,14 @@ function HexNut({ color = "#737e8f", ...props }) {
1823
2036
  }
1824
2037
 
1825
2038
  // lib/models/hexnut/register.tsx
1826
- var model8 = defineModelRenderer({
2039
+ var model9 = defineModelRenderer({
1827
2040
  name: "hexnut",
1828
2041
  schema: hexNutModelDefinitionSchema,
1829
2042
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexNut, { ...props }),
1830
2043
  pads: "none"
1831
2044
  });
1832
- function register8(registry) {
1833
- registry.register(model8);
2045
+ function register9(registry) {
2046
+ registry.register(model9);
1834
2047
  }
1835
2048
 
1836
2049
  // lib/models/hexsocketbolt/register.tsx
@@ -1942,14 +2155,14 @@ function HexSocketBolt({
1942
2155
  }
1943
2156
 
1944
2157
  // lib/models/hexsocketbolt/register.tsx
1945
- var model9 = defineModelRenderer({
2158
+ var model10 = defineModelRenderer({
1946
2159
  name: "hexsocketbolt",
1947
2160
  schema: hexSocketBoltModelDefinitionSchema,
1948
2161
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexSocketBolt, { ...props }),
1949
2162
  pads: "none"
1950
2163
  });
1951
- function register9(registry) {
1952
- registry.register(model9);
2164
+ function register10(registry) {
2165
+ registry.register(model10);
1953
2166
  }
1954
2167
 
1955
2168
  // lib/models/nema/register.tsx
@@ -2218,14 +2431,14 @@ var NEMA17 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 17
2218
2431
  var NEMA23 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 23 });
2219
2432
 
2220
2433
  // lib/models/nema/register.tsx
2221
- var model10 = defineModelRenderer({
2434
+ var model11 = defineModelRenderer({
2222
2435
  name: "nema",
2223
2436
  schema: nemaMotorModelDefinitionSchema,
2224
2437
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(NemaMotor, { ...props }),
2225
2438
  pads: "none"
2226
2439
  });
2227
- function register10(registry) {
2228
- registry.register(model10);
2440
+ function register11(registry) {
2441
+ registry.register(model11);
2229
2442
  }
2230
2443
 
2231
2444
  // lib/models/panscrew/register.tsx
@@ -2437,14 +2650,14 @@ function PanScrew({ color = "#737e8f", ...props }) {
2437
2650
  }
2438
2651
 
2439
2652
  // lib/models/panscrew/register.tsx
2440
- var model11 = defineModelRenderer({
2653
+ var model12 = defineModelRenderer({
2441
2654
  name: "panscrew",
2442
2655
  schema: panScrewModelDefinitionSchema,
2443
2656
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PanScrew, { ...props }),
2444
2657
  pads: "none"
2445
2658
  });
2446
- function register11(registry) {
2447
- registry.register(model11);
2659
+ function register12(registry) {
2660
+ registry.register(model12);
2448
2661
  }
2449
2662
 
2450
2663
  // lib/models/plainbushing/register.tsx
@@ -2507,21 +2720,21 @@ function PlainBushing({
2507
2720
  }
2508
2721
 
2509
2722
  // lib/models/plainbushing/register.tsx
2510
- var model12 = defineModelRenderer({
2723
+ var model13 = defineModelRenderer({
2511
2724
  name: "plainbushing",
2512
2725
  schema: plainBushingModelDefinitionSchema,
2513
2726
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PlainBushing, { ...props }),
2514
2727
  pads: "none"
2515
2728
  });
2516
- function register12(registry) {
2517
- registry.register(model12);
2729
+ function register13(registry) {
2730
+ registry.register(model13);
2518
2731
  }
2519
2732
 
2520
2733
  // lib/models/sheetmetal/register.tsx
2521
2734
  import { sheetMetalModelDefinitionSchema } from "@tscircuit/modelprinter";
2522
2735
 
2523
2736
  // lib/mechanical/sheet-metal-mesh.ts
2524
- import earcut2 from "earcut";
2737
+ import earcut3 from "earcut";
2525
2738
  import {
2526
2739
  sheetMetalModelPropsSchema
2527
2740
  } from "@tscircuit/modelprinter";
@@ -2589,7 +2802,7 @@ function createSheetMetalMesh(input) {
2589
2802
  const loops = [outline, ...holes.map((hole) => [...hole].reverse())];
2590
2803
  const points = loops.flat();
2591
2804
  const starts = holes.map((_, i) => 4 + i * 64);
2592
- const triangles = earcut2(
2805
+ const triangles = earcut3(
2593
2806
  points.flatMap((p) => [p.u, p.v]),
2594
2807
  starts
2595
2808
  );
@@ -2674,14 +2887,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
2674
2887
  }
2675
2888
 
2676
2889
  // lib/models/sheetmetal/register.tsx
2677
- var model13 = defineModelRenderer({
2890
+ var model14 = defineModelRenderer({
2678
2891
  name: "sheetmetal",
2679
2892
  schema: sheetMetalModelDefinitionSchema,
2680
2893
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
2681
2894
  pads: "none"
2682
2895
  });
2683
- function register13(registry) {
2684
- registry.register(model13);
2896
+ function register14(registry) {
2897
+ registry.register(model14);
2685
2898
  }
2686
2899
 
2687
2900
  // lib/models/spurgear/register.tsx
@@ -2696,14 +2909,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
2696
2909
  }
2697
2910
 
2698
2911
  // lib/models/spurgear/register.tsx
2699
- var model14 = defineModelRenderer({
2912
+ var model15 = defineModelRenderer({
2700
2913
  name: "spurgear",
2701
2914
  schema: spurGearModelDefinitionSchema,
2702
2915
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
2703
2916
  pads: "none"
2704
2917
  });
2705
- function register14(registry) {
2706
- registry.register(model14);
2918
+ function register15(registry) {
2919
+ registry.register(model15);
2707
2920
  }
2708
2921
 
2709
2922
  // lib/models/wormgear/register.tsx
@@ -2714,7 +2927,7 @@ import {
2714
2927
  getWormGearDimensions,
2715
2928
  wormGearModelPropsSchema
2716
2929
  } from "@tscircuit/modelprinter";
2717
- import earcut3 from "earcut";
2930
+ import earcut4 from "earcut";
2718
2931
  var createWormGearMesh = (input) => {
2719
2932
  const props = wormGearModelPropsSchema.parse(input);
2720
2933
  const { outsideDiameter, rootDiameter, axialPitch, lead, toothThickness } = getWormGearDimensions(props);
@@ -2867,7 +3080,7 @@ var createWormGearMesh = (input) => {
2867
3080
  positions[vertex * 3],
2868
3081
  positions[vertex * 3 + 1]
2869
3082
  ]);
2870
- const triangles = earcut3(flat, [count], 2);
3083
+ const triangles = earcut4(flat, [count], 2);
2871
3084
  for (let index = 0; index < triangles.length; index += 3) {
2872
3085
  const a = vertices[triangles[index]];
2873
3086
  const b = vertices[triangles[index + 1]];
@@ -2895,14 +3108,14 @@ function WormGear({ color = "#737e8f", ...props }) {
2895
3108
  }
2896
3109
 
2897
3110
  // lib/models/wormgear/register.tsx
2898
- var model15 = defineModelRenderer({
3111
+ var model16 = defineModelRenderer({
2899
3112
  name: "wormgear",
2900
3113
  schema: wormGearModelDefinitionSchema,
2901
3114
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
2902
3115
  pads: "none"
2903
3116
  });
2904
- function register15(registry) {
2905
- registry.register(model15);
3117
+ function register16(registry) {
3118
+ registry.register(model16);
2906
3119
  }
2907
3120
 
2908
3121
  // lib/generated/model-renderers.ts
@@ -2922,6 +3135,7 @@ function registerAllModelRenderers(registry) {
2922
3135
  register13(registry);
2923
3136
  register14(registry);
2924
3137
  register15(registry);
3138
+ register16(registry);
2925
3139
  }
2926
3140
 
2927
3141
  // lib/default-model-registry.ts
@@ -10478,10 +10692,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
10478
10692
  var Footprinter3d = ({ footprint }) => {
10479
10693
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
10480
10694
  if (mp3.getModelNames().includes(modelFn)) {
10481
- const model16 = mp3.string(footprint).json();
10482
- const renderer = modelRendererRegistry.get(model16.fn);
10695
+ const model17 = mp3.string(footprint).json();
10696
+ const renderer = modelRendererRegistry.get(model17.fn);
10483
10697
  if (renderer) {
10484
- return renderer.render(model16);
10698
+ return renderer.render(model17);
10485
10699
  }
10486
10700
  }
10487
10701
  let normalizedFootprint = footprint;
@@ -11434,6 +11648,7 @@ function createJSCADRenderer(jscad4) {
11434
11648
  export {
11435
11649
  ButtonScrew,
11436
11650
  CableGrommet,
11651
+ CompressionSpring,
11437
11652
  FlangedBushing,
11438
11653
  FlatHeadScrew,
11439
11654
  Fragment,
@@ -11455,6 +11670,8 @@ export {
11455
11670
  createButtonScrewMesh,
11456
11671
  createCableGrommetGeom,
11457
11672
  createCableGrommetMesh,
11673
+ createCompressionSpringGeom,
11674
+ createCompressionSpringMesh,
11458
11675
  createFlangedBushingGeom,
11459
11676
  createFlangedBushingMesh,
11460
11677
  createFlatHeadScrewGeom,