jscad-electronics 0.0.205 → 0.0.207

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(model20) {
187
- return model20;
186
+ function defineModelRenderer(model22) {
187
+ return model22;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model20) {
192
- if (typeof model20.name !== "string" || !/^[a-z]+$/.test(model20.name)) {
191
+ register(model22) {
192
+ if (typeof model22.name !== "string" || !/^[a-z]+$/.test(model22.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(model20.name)) {
198
- throw new Error(`Model renderer "${model20.name}" is already registered`);
197
+ if (this.models.has(model22.name)) {
198
+ throw new Error(`Model renderer "${model22.name}" is already registered`);
199
199
  }
200
- if (model20.pads !== "none" && model20.pads !== "footprinter") {
200
+ if (model22.pads !== "none" && model22.pads !== "footprinter") {
201
201
  throw new Error('Model renderer pads must be "none" or "footprinter"');
202
202
  }
203
- const { name, schema, render: render2, pads } = model20;
203
+ const { name, schema, render: render2, pads } = model22;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -454,6 +454,314 @@ function register2(registry) {
454
454
  registry.register(model2);
455
455
  }
456
456
 
457
+ // lib/models/clampingshaftcollar/register.tsx
458
+ import { clampingShaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
459
+
460
+ // lib/models/clampingshaftcollar/mesh.ts
461
+ import jscad3 from "@jscad/modeling";
462
+ import {
463
+ clampingShaftCollarModelPropsSchema,
464
+ getClampingShaftCollarDimensions
465
+ } from "@tscircuit/modelprinter";
466
+
467
+ // lib/mechanical/shaft-mount-geometry.ts
468
+ import jscad2 from "@jscad/modeling";
469
+ var bodySegments = 64;
470
+ var threadSegments = 24;
471
+ var samplesPerTurn = 12;
472
+ function assertShaftMountResolution(holes) {
473
+ let triangles = 0;
474
+ for (const hole of holes) {
475
+ const steps = hole.threadPitch ? Math.ceil(hole.depth / hole.threadPitch * samplesPerTurn) : 1;
476
+ if (!Number.isFinite(steps) || steps > 768)
477
+ throw new Error(
478
+ "Shaft mount exceeds mesh resolution limit (64 thread turns per hole)"
479
+ );
480
+ triangles += (steps + 1) * threadSegments * 2;
481
+ }
482
+ if (triangles > 1e5)
483
+ throw new Error("Shaft mount exceeds total mesh resolution limit");
484
+ }
485
+ function createAnnularSleeve({
486
+ outerRadius,
487
+ boreARadius,
488
+ boreBRadius = boreARadius,
489
+ length,
490
+ chamfer,
491
+ stepZ = length / 2
492
+ }) {
493
+ const halfAngle = Math.PI / bodySegments;
494
+ const cosine = Math.cos(halfAngle);
495
+ if ((Math.max(boreARadius, boreBRadius) + chamfer) / cosine >= (outerRadius - chamfer) * cosine - 1e-6)
496
+ throw new Error(
497
+ "Shaft mount wall/chamfer ligament exceeds mesh resolution limit"
498
+ );
499
+ const raw = [
500
+ [0, outerRadius - chamfer, false],
501
+ [chamfer, outerRadius, false],
502
+ [length - chamfer, outerRadius, false],
503
+ [length, outerRadius - chamfer, false],
504
+ [length, boreBRadius + chamfer, true],
505
+ [length - chamfer, boreBRadius, true],
506
+ [stepZ, boreBRadius, true],
507
+ [stepZ, boreARadius, true],
508
+ [chamfer, boreARadius, true],
509
+ [0, boreARadius + chamfer, true]
510
+ ];
511
+ const profile = raw.filter(
512
+ ([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
513
+ );
514
+ const positions = [];
515
+ const indices = [];
516
+ for (const [z, r, isBore] of profile)
517
+ for (let i = 0; i < bodySegments; i++) {
518
+ const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
519
+ const radius = isBore ? r / cosine : r;
520
+ positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
521
+ }
522
+ for (let row = 0; row < profile.length; row++)
523
+ for (let i = 0; i < bodySegments; i++) {
524
+ const next = (i + 1) % bodySegments;
525
+ const a = row * bodySegments + i, b = row * bodySegments + next;
526
+ const c = (row + 1) % profile.length * bodySegments + next, d = (row + 1) % profile.length * bodySegments + i;
527
+ indices.push(a, b, c, a, c, d);
528
+ }
529
+ return indexedMeshToGeom3({ positions, indices });
530
+ }
531
+ function createMountingHoleCutter(hole) {
532
+ assertShaftMountResolution([hole]);
533
+ const pitch = hole.threadPitch;
534
+ const steps = pitch ? Math.max(2, Math.ceil(hole.depth / pitch * samplesPerTurn)) : 1;
535
+ const segments = pitch ? threadSegments : 48;
536
+ const extension = 1e-4;
537
+ const radius = hole.diameter / 2;
538
+ const threadDepth = pitch ? Math.min(pitch * 0.541266, radius * 0.8) : 0;
539
+ const hand = hole.threadHand === "left" ? -1 : 1;
540
+ const positions = [];
541
+ const indices = [];
542
+ const [dx, dy, dz] = hole.direction;
543
+ if (Math.abs(dz) > 1e-10 || Math.abs(Math.hypot(dx, dy) - 1) > 1e-10)
544
+ throw new Error("Expected a horizontal unit hole axis");
545
+ const push = (x, y, z) => {
546
+ positions.push(
547
+ hole.start[0] + y * dy + z * dx,
548
+ hole.start[1] - y * dx + z * dy,
549
+ hole.start[2] + x
550
+ );
551
+ };
552
+ for (let row = 0; row <= steps; row++) {
553
+ const z = -extension + (hole.depth + 2 * extension) * row / steps;
554
+ for (let i = 0; i < segments; i++) {
555
+ const angle = i * Math.PI * 2 / segments;
556
+ const phase = pitch ? ((z / pitch - hand * angle / (Math.PI * 2)) % 1 + 1) % 1 : 0;
557
+ const distance2 = Math.min(phase, 1 - phase);
558
+ const r = radius - Math.min(
559
+ threadDepth,
560
+ Math.max(0, (distance2 - 1 / 8) * (pitch ?? 0) * Math.sqrt(3))
561
+ );
562
+ push(r * Math.cos(angle), r * Math.sin(angle), z);
563
+ }
564
+ }
565
+ for (let row = 0; row < steps; row++)
566
+ for (let i = 0; i < segments; i++) {
567
+ const next = (i + 1) % segments;
568
+ const a = row * segments + i, b = row * segments + next, c = (row + 1) * segments + next, d = (row + 1) * segments + i;
569
+ indices.push(a, b, c, a, c, d);
570
+ }
571
+ for (const end of [0, steps]) {
572
+ const center = positions.length / 3;
573
+ push(0, 0, end === 0 ? -extension : hole.depth + extension);
574
+ for (let i = 0; i < segments; i++) {
575
+ const a = end * segments + i, b = end * segments + (i + 1) % segments;
576
+ indices.push(center, end === 0 ? b : a, end === 0 ? a : b);
577
+ }
578
+ }
579
+ return indexedMeshToGeom3({ positions, indices });
580
+ }
581
+ function subtractShaftMountParts(body, ...cutters) {
582
+ const factor = 100;
583
+ const scaled = [body, ...cutters].map(
584
+ (geometry) => jscad2.transforms.scale([factor, factor, factor], geometry)
585
+ );
586
+ const result = jscad2.booleans.subtract(scaled[0], ...scaled.slice(1));
587
+ return jscad2.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
588
+ }
589
+ function finishShaftMountMesh(geometry) {
590
+ const positions = [];
591
+ const vertices = /* @__PURE__ */ new Map();
592
+ const tolerance = 1e-6;
593
+ const weld = (point) => {
594
+ const cell = point.map((v) => Math.floor(v / tolerance));
595
+ for (let x = -1; x <= 1; x++)
596
+ for (let y = -1; y <= 1; y++)
597
+ for (let z = -1; z <= 1; z++) {
598
+ const nearby = vertices.get(
599
+ [cell[0] + x, cell[1] + y, cell[2] + z].join(",")
600
+ ) ?? [];
601
+ for (const index2 of nearby)
602
+ if (Math.hypot(
603
+ ...point.map((v, axis) => v - positions[index2 * 3 + axis])
604
+ ) < tolerance)
605
+ return index2;
606
+ }
607
+ const index = positions.length / 3;
608
+ positions.push(...point);
609
+ const key = cell.join(",");
610
+ vertices.set(key, [...vertices.get(key) ?? [], index]);
611
+ return index;
612
+ };
613
+ const polygons = jscad2.geometries.geom3.toPolygons(geometry).map(
614
+ (polygon) => polygon.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
615
+ ).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
616
+ let longest = 0;
617
+ let origin = [];
618
+ let direction = [];
619
+ for (let i = 0; i < ids.length; i++)
620
+ for (let j = i + 1; j < ids.length; j++) {
621
+ const a = positions.slice(ids[i] * 3, ids[i] * 3 + 3);
622
+ const delta = positions.slice(ids[j] * 3, ids[j] * 3 + 3).map((v, axis) => v - a[axis]);
623
+ const squared = delta.reduce((sum, v) => sum + v * v, 0);
624
+ if (squared > longest) {
625
+ longest = squared;
626
+ origin = a;
627
+ direction = delta;
628
+ }
629
+ }
630
+ return ids.some((id) => {
631
+ const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
632
+ const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / longest;
633
+ return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
634
+ });
635
+ });
636
+ const edgeKey = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
637
+ const edges = /* @__PURE__ */ new Map();
638
+ for (const polygon of polygons)
639
+ for (let i = 0; i < polygon.length; i++) {
640
+ const a = polygon[i], b = polygon[(i + 1) % polygon.length], key = edgeKey(a, b);
641
+ const edge = edges.get(key) ?? { a, b, count: 0 };
642
+ edge.count++;
643
+ edges.set(key, edge);
644
+ }
645
+ const unmatched = [...edges.values()].filter((edge) => edge.count === 1);
646
+ const candidates = [...new Set(unmatched.flatMap((edge) => [edge.a, edge.b]))];
647
+ const splits = /* @__PURE__ */ new Map();
648
+ for (const { a, b } of unmatched) {
649
+ const origin = positions.slice(a * 3, a * 3 + 3);
650
+ const direction = positions.slice(b * 3, b * 3 + 3).map((v, axis) => v - origin[axis]);
651
+ const squared = direction.reduce((sum, v) => sum + v * v, 0);
652
+ const points = [];
653
+ for (const id of candidates) {
654
+ if (id === a || id === b) continue;
655
+ const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
656
+ const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / squared;
657
+ if (t <= 0 || t >= 1) continue;
658
+ const distance2 = Math.hypot(
659
+ ...delta.map((v, axis) => v - t * direction[axis])
660
+ );
661
+ if (distance2 < tolerance) points.push({ id, t });
662
+ }
663
+ points.sort((p, q) => p.t - q.t);
664
+ splits.set(
665
+ `${a},${b}`,
666
+ points.map((p) => p.id)
667
+ );
668
+ splits.set(`${b},${a}`, points.map((p) => p.id).reverse());
669
+ }
670
+ const indices = [];
671
+ for (const polygon of polygons) {
672
+ const perimeter = polygon.flatMap((a, i) => [
673
+ a,
674
+ ...(splits.get(`${a},${polygon[(i + 1) % polygon.length]}`) ?? []).filter((id) => !polygon.includes(id))
675
+ ]);
676
+ const unique = perimeter.filter(
677
+ (id, i) => id !== perimeter[(i + perimeter.length - 1) % perimeter.length]
678
+ );
679
+ if (unique.length === 3) {
680
+ indices.push(...unique);
681
+ continue;
682
+ }
683
+ const center = positions.length / 3;
684
+ positions.push(
685
+ ...[0, 1, 2].map(
686
+ (axis) => unique.reduce((sum, id) => sum + positions[id * 3 + axis], 0) / unique.length
687
+ )
688
+ );
689
+ for (let i = 0; i < unique.length; i++)
690
+ indices.push(center, unique[i], unique[(i + 1) % unique.length]);
691
+ }
692
+ const compact = [];
693
+ const remap = /* @__PURE__ */ new Map();
694
+ return {
695
+ positions: compact,
696
+ indices: indices.map((index) => {
697
+ let next = remap.get(index);
698
+ if (next === void 0) {
699
+ next = compact.length / 3;
700
+ remap.set(index, next);
701
+ compact.push(...positions.slice(index * 3, index * 3 + 3));
702
+ }
703
+ return next;
704
+ })
705
+ };
706
+ }
707
+
708
+ // lib/models/clampingshaftcollar/mesh.ts
709
+ function createClampingShaftCollarMesh(input) {
710
+ const props = clampingShaftCollarModelPropsSchema.parse(input);
711
+ const dimensions = getClampingShaftCollarDimensions(props);
712
+ assertShaftMountResolution([dimensions.threadedHole]);
713
+ const body = createAnnularSleeve({
714
+ outerRadius: props.outerDiameter / 2,
715
+ boreARadius: props.boreDiameter / 2,
716
+ length: props.width,
717
+ chamfer: props.chamfer
718
+ });
719
+ const s = dimensions.split;
720
+ const epsilon = 1e-4;
721
+ const slit = jscad3.primitives.cuboid({
722
+ size: [
723
+ s.xMax - s.xMin + epsilon,
724
+ s.yMax - s.yMin,
725
+ s.zMax - s.zMin + 2 * epsilon
726
+ ],
727
+ center: [
728
+ (s.xMax + s.xMin + epsilon) / 2,
729
+ (s.yMax + s.yMin) / 2,
730
+ (s.zMax + s.zMin) / 2
731
+ ]
732
+ });
733
+ return finishShaftMountMesh(
734
+ subtractShaftMountParts(
735
+ body,
736
+ slit,
737
+ createMountingHoleCutter(dimensions.clearanceHole),
738
+ createMountingHoleCutter(dimensions.threadedHole)
739
+ )
740
+ );
741
+ }
742
+
743
+ // lib/models/clampingshaftcollar/ClampingShaftCollar.tsx
744
+ function createClampingShaftCollarGeom(input) {
745
+ return indexedMeshToGeom3(createClampingShaftCollarMesh(input));
746
+ }
747
+ function ClampingShaftCollar({
748
+ color = "#737e8f",
749
+ ...props
750
+ }) {
751
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createClampingShaftCollarGeom(props) }) });
752
+ }
753
+
754
+ // lib/models/clampingshaftcollar/register.tsx
755
+ var model3 = defineModelRenderer({
756
+ name: "clampingshaftcollar",
757
+ schema: clampingShaftCollarModelDefinitionSchema,
758
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(ClampingShaftCollar, { ...props }),
759
+ pads: "none"
760
+ });
761
+ function register3(registry) {
762
+ registry.register(model3);
763
+ }
764
+
457
765
  // lib/models/compressionspring/register.tsx
458
766
  import { compressionSpringModelDefinitionSchema } from "@tscircuit/modelprinter";
459
767
 
@@ -657,14 +965,14 @@ function CompressionSpring({
657
965
  }
658
966
 
659
967
  // lib/models/compressionspring/register.tsx
660
- var model3 = defineModelRenderer({
968
+ var model4 = defineModelRenderer({
661
969
  name: "compressionspring",
662
970
  schema: compressionSpringModelDefinitionSchema,
663
971
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(CompressionSpring, { ...props }),
664
972
  pads: "none"
665
973
  });
666
- function register3(registry) {
667
- registry.register(model3);
974
+ function register4(registry) {
975
+ registry.register(model4);
668
976
  }
669
977
 
670
978
  // lib/models/flangedbushing/register.tsx
@@ -720,14 +1028,14 @@ function FlangedBushing({
720
1028
  }
721
1029
 
722
1030
  // lib/models/flangedbushing/register.tsx
723
- var model4 = defineModelRenderer({
1031
+ var model5 = defineModelRenderer({
724
1032
  name: "flangedbushing",
725
1033
  schema: flangedBushingModelDefinitionSchema,
726
1034
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlangedBushing, { ...props }),
727
1035
  pads: "none"
728
1036
  });
729
- function register4(registry) {
730
- registry.register(model4);
1037
+ function register5(registry) {
1038
+ registry.register(model5);
731
1039
  }
732
1040
 
733
1041
  // lib/models/flatheadscrew/register.tsx
@@ -860,14 +1168,14 @@ function FlatHeadScrew({
860
1168
  }
861
1169
 
862
1170
  // lib/models/flatheadscrew/register.tsx
863
- var model5 = defineModelRenderer({
1171
+ var model6 = defineModelRenderer({
864
1172
  name: "flatheadscrew",
865
1173
  schema: flatHeadScrewModelDefinitionSchema,
866
1174
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlatHeadScrew, { ...props }),
867
1175
  pads: "none"
868
1176
  });
869
- function register5(registry) {
870
- registry.register(model5);
1177
+ function register6(registry) {
1178
+ registry.register(model6);
871
1179
  }
872
1180
 
873
1181
  // lib/models/flexscreen/register.tsx
@@ -1545,14 +1853,14 @@ var FlexScreen = (props) => {
1545
1853
  };
1546
1854
 
1547
1855
  // lib/models/flexscreen/register.tsx
1548
- var model6 = defineModelRenderer({
1856
+ var model7 = defineModelRenderer({
1549
1857
  name: "flexscreen",
1550
1858
  schema: flexScreenModelDefinitionSchema,
1551
1859
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlexScreen, { ...props }),
1552
1860
  pads: "footprinter"
1553
1861
  });
1554
- function register6(registry) {
1555
- registry.register(model6);
1862
+ function register7(registry) {
1863
+ registry.register(model7);
1556
1864
  }
1557
1865
 
1558
1866
  // lib/models/helicalgear/register.tsx
@@ -1758,14 +2066,14 @@ function HelicalGear({ color = "#737e8f", ...props }) {
1758
2066
  }
1759
2067
 
1760
2068
  // lib/models/helicalgear/register.tsx
1761
- var model7 = defineModelRenderer({
2069
+ var model8 = defineModelRenderer({
1762
2070
  name: "helicalgear",
1763
2071
  schema: helicalGearModelDefinitionSchema,
1764
2072
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HelicalGear, { ...props }),
1765
2073
  pads: "none"
1766
2074
  });
1767
- function register7(registry) {
1768
- registry.register(model7);
2075
+ function register8(registry) {
2076
+ registry.register(model8);
1769
2077
  }
1770
2078
 
1771
2079
  // lib/models/hexbolt/register.tsx
@@ -1906,14 +2214,14 @@ function HexBolt({ color = "#737e8f", ...props }) {
1906
2214
  }
1907
2215
 
1908
2216
  // lib/models/hexbolt/register.tsx
1909
- var model8 = defineModelRenderer({
2217
+ var model9 = defineModelRenderer({
1910
2218
  name: "hexbolt",
1911
2219
  schema: hexBoltModelDefinitionSchema,
1912
2220
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexBolt, { ...props }),
1913
2221
  pads: "none"
1914
2222
  });
1915
- function register8(registry) {
1916
- registry.register(model8);
2223
+ function register9(registry) {
2224
+ registry.register(model9);
1917
2225
  }
1918
2226
 
1919
2227
  // lib/models/hexnut/register.tsx
@@ -2036,14 +2344,14 @@ function HexNut({ color = "#737e8f", ...props }) {
2036
2344
  }
2037
2345
 
2038
2346
  // lib/models/hexnut/register.tsx
2039
- var model9 = defineModelRenderer({
2347
+ var model10 = defineModelRenderer({
2040
2348
  name: "hexnut",
2041
2349
  schema: hexNutModelDefinitionSchema,
2042
2350
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexNut, { ...props }),
2043
2351
  pads: "none"
2044
2352
  });
2045
- function register9(registry) {
2046
- registry.register(model9);
2353
+ function register10(registry) {
2354
+ registry.register(model10);
2047
2355
  }
2048
2356
 
2049
2357
  // lib/models/hexsocketbolt/register.tsx
@@ -2155,24 +2463,24 @@ function HexSocketBolt({
2155
2463
  }
2156
2464
 
2157
2465
  // lib/models/hexsocketbolt/register.tsx
2158
- var model10 = defineModelRenderer({
2466
+ var model11 = defineModelRenderer({
2159
2467
  name: "hexsocketbolt",
2160
2468
  schema: hexSocketBoltModelDefinitionSchema,
2161
2469
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexSocketBolt, { ...props }),
2162
2470
  pads: "none"
2163
2471
  });
2164
- function register10(registry) {
2165
- registry.register(model10);
2472
+ function register11(registry) {
2473
+ registry.register(model11);
2166
2474
  }
2167
2475
 
2168
2476
  // lib/models/nema/register.tsx
2169
2477
  import { nemaMotorModelDefinitionSchema } from "@tscircuit/modelprinter";
2170
2478
 
2171
2479
  // lib/NemaMotor.tsx
2172
- import jscad3 from "@jscad/modeling";
2480
+ import jscad5 from "@jscad/modeling";
2173
2481
 
2174
2482
  // lib/utils/nemaMotorWireGeometry.ts
2175
- import jscad2 from "@jscad/modeling";
2483
+ import jscad4 from "@jscad/modeling";
2176
2484
  import {
2177
2485
  getJstMotorConnector,
2178
2486
  getNemaMotorReferencePoints
@@ -2190,9 +2498,9 @@ function createNemaMotorWireGeometry(input) {
2190
2498
  if (p.wireConnection === "none") return [];
2191
2499
  const { position } = getNemaMotorReferencePoints(p).wireside;
2192
2500
  const angle = p.wireSideAngle * Math.PI / 180;
2193
- const place = (geometry) => jscad2.transforms.translate(
2501
+ const place = (geometry) => jscad4.transforms.translate(
2194
2502
  [position.x, position.y, position.z],
2195
- jscad2.transforms.rotateZ(angle, geometry)
2503
+ jscad4.transforms.rotateZ(angle, geometry)
2196
2504
  );
2197
2505
  if (p.wireConnection === "stubs") {
2198
2506
  const colors = [
@@ -2208,15 +2516,15 @@ function createNemaMotorWireGeometry(input) {
2208
2516
  return Array.from({ length: p.wireCount }, (_, i) => ({
2209
2517
  color: colors[i],
2210
2518
  geometry: place(
2211
- jscad2.transforms.translate(
2519
+ jscad4.transforms.translate(
2212
2520
  [
2213
2521
  (p.wireLength - 0.15) / 2,
2214
2522
  (i - (p.wireCount - 1) / 2) * p.wireDiameter * 1.5,
2215
2523
  0
2216
2524
  ],
2217
- jscad2.transforms.rotateY(
2525
+ jscad4.transforms.rotateY(
2218
2526
  Math.PI / 2,
2219
- jscad2.primitives.cylinder({
2527
+ jscad4.primitives.cylinder({
2220
2528
  height: p.wireLength + 0.15,
2221
2529
  radius: p.wireDiameter / 2,
2222
2530
  segments: 24
@@ -2231,12 +2539,12 @@ function createNemaMotorWireGeometry(input) {
2231
2539
  const wall = pitch === 2 ? 0.6 : 0.3;
2232
2540
  const contactLength = pitch === 2 ? 3.4 : 2.4;
2233
2541
  const contactSize = pitch === 2 ? 0.5 : 0.3;
2234
- const shell = jscad2.booleans.subtract(
2235
- jscad2.primitives.cuboid({
2542
+ const shell = jscad4.booleans.subtract(
2543
+ jscad4.primitives.cuboid({
2236
2544
  size: [matingDepth + 0.1, bodyWidth, bodyHeight],
2237
2545
  center: [(matingDepth - 0.1) / 2, 0, 0]
2238
2546
  }),
2239
- jscad2.primitives.cuboid({
2547
+ jscad4.primitives.cuboid({
2240
2548
  size: [matingDepth - 0.5, bodyWidth - 2 * wall, bodyHeight - 2 * wall],
2241
2549
  center: [matingDepth / 2 + 0.55, 0, 0]
2242
2550
  })
@@ -2246,7 +2554,7 @@ function createNemaMotorWireGeometry(input) {
2246
2554
  ...Array.from({ length: pinCount }, (_, i) => ({
2247
2555
  color: "#b8bec6",
2248
2556
  geometry: place(
2249
- jscad2.primitives.cuboid({
2557
+ jscad4.primitives.cuboid({
2250
2558
  size: [contactLength, contactSize, contactSize],
2251
2559
  center: [contactLength / 2, (i - (pinCount - 1) / 2) * pitch, 0]
2252
2560
  })
@@ -2354,7 +2662,7 @@ function createNemaMotorSections(input) {
2354
2662
  }
2355
2663
 
2356
2664
  // lib/NemaMotor.tsx
2357
- var generalize = jscad3.modifiers.generalize;
2665
+ var generalize = jscad5.modifiers.generalize;
2358
2666
  function NemaMotor({
2359
2667
  bodyColor = "#242830",
2360
2668
  capColor = "#aeb5bd",
@@ -2363,7 +2671,7 @@ function NemaMotor({
2363
2671
  ...props
2364
2672
  }) {
2365
2673
  const p = resolveNemaMotorProps(props);
2366
- const screw = p.backFace === "screws" ? jscad3.transforms.rotateX(
2674
+ const screw = p.backFace === "screws" ? jscad5.transforms.rotateX(
2367
2675
  Math.PI,
2368
2676
  createHexSocketBoltGeom({
2369
2677
  metricSize: p.backFaceScrewSize,
@@ -2374,14 +2682,14 @@ function NemaMotor({
2374
2682
  const halfPitch = p.backFaceHoleSpacing / 2;
2375
2683
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
2376
2684
  createNemaMotorSections(p).map((section, index) => {
2377
- const outline = jscad3.geometries.geom2.fromPoints(section.outline);
2378
- const profile = section.holes.length ? jscad3.booleans.subtract(
2685
+ const outline = jscad5.geometries.geom2.fromPoints(section.outline);
2686
+ const profile = section.holes.length ? jscad5.booleans.subtract(
2379
2687
  outline,
2380
- ...section.holes.map((h2) => jscad3.geometries.geom2.fromPoints(h2))
2688
+ ...section.holes.map((h2) => jscad5.geometries.geom2.fromPoints(h2))
2381
2689
  ) : outline;
2382
- const geometry = jscad3.transforms.translate(
2690
+ const geometry = jscad5.transforms.translate(
2383
2691
  [0, 0, section.zMin],
2384
- jscad3.extrusions.extrudeLinear(
2692
+ jscad5.extrusions.extrudeLinear(
2385
2693
  { height: section.zMax - section.zMin },
2386
2694
  profile
2387
2695
  )
@@ -2414,7 +2722,7 @@ function NemaMotor({
2414
2722
  children: /* @__PURE__ */ jsx(
2415
2723
  Custom,
2416
2724
  {
2417
- geometry: jscad3.transforms.translate(
2725
+ geometry: jscad5.transforms.translate(
2418
2726
  [x, y, -p.bodyLength],
2419
2727
  generalize({ simplify: true }, screw)
2420
2728
  )
@@ -2431,14 +2739,14 @@ var NEMA17 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 17
2431
2739
  var NEMA23 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 23 });
2432
2740
 
2433
2741
  // lib/models/nema/register.tsx
2434
- var model11 = defineModelRenderer({
2742
+ var model12 = defineModelRenderer({
2435
2743
  name: "nema",
2436
2744
  schema: nemaMotorModelDefinitionSchema,
2437
2745
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(NemaMotor, { ...props }),
2438
2746
  pads: "none"
2439
2747
  });
2440
- function register11(registry) {
2441
- registry.register(model11);
2748
+ function register12(registry) {
2749
+ registry.register(model12);
2442
2750
  }
2443
2751
 
2444
2752
  // lib/models/panscrew/register.tsx
@@ -2650,14 +2958,14 @@ function PanScrew({ color = "#737e8f", ...props }) {
2650
2958
  }
2651
2959
 
2652
2960
  // lib/models/panscrew/register.tsx
2653
- var model12 = defineModelRenderer({
2961
+ var model13 = defineModelRenderer({
2654
2962
  name: "panscrew",
2655
2963
  schema: panScrewModelDefinitionSchema,
2656
2964
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PanScrew, { ...props }),
2657
2965
  pads: "none"
2658
2966
  });
2659
- function register12(registry) {
2660
- registry.register(model12);
2967
+ function register13(registry) {
2968
+ registry.register(model13);
2661
2969
  }
2662
2970
 
2663
2971
  // lib/models/plainbushing/register.tsx
@@ -2720,14 +3028,60 @@ function PlainBushing({
2720
3028
  }
2721
3029
 
2722
3030
  // lib/models/plainbushing/register.tsx
2723
- var model13 = defineModelRenderer({
3031
+ var model14 = defineModelRenderer({
2724
3032
  name: "plainbushing",
2725
3033
  schema: plainBushingModelDefinitionSchema,
2726
3034
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PlainBushing, { ...props }),
2727
3035
  pads: "none"
2728
3036
  });
2729
- function register13(registry) {
2730
- registry.register(model13);
3037
+ function register14(registry) {
3038
+ registry.register(model14);
3039
+ }
3040
+
3041
+ // lib/models/shaftcollar/register.tsx
3042
+ import { shaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
3043
+
3044
+ // lib/models/shaftcollar/mesh.ts
3045
+ import "@jscad/modeling";
3046
+ import {
3047
+ shaftCollarModelPropsSchema,
3048
+ getShaftCollarDimensions
3049
+ } from "@tscircuit/modelprinter";
3050
+ function createShaftCollarMesh(input) {
3051
+ const props = shaftCollarModelPropsSchema.parse(input);
3052
+ const dimensions = getShaftCollarDimensions(props);
3053
+ assertShaftMountResolution([dimensions.screwHole]);
3054
+ const body = createAnnularSleeve({
3055
+ outerRadius: props.outerDiameter / 2,
3056
+ boreARadius: props.boreDiameter / 2,
3057
+ length: props.width,
3058
+ chamfer: props.chamfer
3059
+ });
3060
+ return finishShaftMountMesh(
3061
+ subtractShaftMountParts(
3062
+ body,
3063
+ createMountingHoleCutter(dimensions.screwHole)
3064
+ )
3065
+ );
3066
+ }
3067
+
3068
+ // lib/models/shaftcollar/ShaftCollar.tsx
3069
+ function createShaftCollarGeom(input) {
3070
+ return indexedMeshToGeom3(createShaftCollarMesh(input));
3071
+ }
3072
+ function ShaftCollar({ color = "#737e8f", ...props }) {
3073
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createShaftCollarGeom(props) }) });
3074
+ }
3075
+
3076
+ // lib/models/shaftcollar/register.tsx
3077
+ var model15 = defineModelRenderer({
3078
+ name: "shaftcollar",
3079
+ schema: shaftCollarModelDefinitionSchema,
3080
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(ShaftCollar, { ...props }),
3081
+ pads: "none"
3082
+ });
3083
+ function register15(registry) {
3084
+ registry.register(model15);
2731
3085
  }
2732
3086
 
2733
3087
  // lib/models/sheetmetal/register.tsx
@@ -2887,14 +3241,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
2887
3241
  }
2888
3242
 
2889
3243
  // lib/models/sheetmetal/register.tsx
2890
- var model14 = defineModelRenderer({
3244
+ var model16 = defineModelRenderer({
2891
3245
  name: "sheetmetal",
2892
3246
  schema: sheetMetalModelDefinitionSchema,
2893
3247
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
2894
3248
  pads: "none"
2895
3249
  });
2896
- function register14(registry) {
2897
- registry.register(model14);
3250
+ function register16(registry) {
3251
+ registry.register(model16);
2898
3252
  }
2899
3253
 
2900
3254
  // lib/models/spurgear/register.tsx
@@ -2909,14 +3263,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
2909
3263
  }
2910
3264
 
2911
3265
  // lib/models/spurgear/register.tsx
2912
- var model15 = defineModelRenderer({
3266
+ var model17 = defineModelRenderer({
2913
3267
  name: "spurgear",
2914
3268
  schema: spurGearModelDefinitionSchema,
2915
3269
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
2916
3270
  pads: "none"
2917
3271
  });
2918
- function register15(registry) {
2919
- registry.register(model15);
3272
+ function register17(registry) {
3273
+ registry.register(model17);
2920
3274
  }
2921
3275
 
2922
3276
  // lib/models/tslotextrusion/register.tsx
@@ -3066,14 +3420,14 @@ function TSlotExtrusion({
3066
3420
  }
3067
3421
 
3068
3422
  // lib/models/tslotextrusion/register.tsx
3069
- var model16 = defineModelRenderer({
3423
+ var model18 = defineModelRenderer({
3070
3424
  name: "tslotextrusion",
3071
3425
  schema: tSlotExtrusionModelDefinitionSchema,
3072
3426
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotExtrusion, { ...props }),
3073
3427
  pads: "none"
3074
3428
  });
3075
- function register16(registry) {
3076
- registry.register(model16);
3429
+ function register18(registry) {
3430
+ registry.register(model18);
3077
3431
  }
3078
3432
 
3079
3433
  // lib/models/tslotgusset/register.tsx
@@ -3126,14 +3480,14 @@ function TSlotGusset({ color = "#8995a3", ...props }) {
3126
3480
  }
3127
3481
 
3128
3482
  // lib/models/tslotgusset/register.tsx
3129
- var model17 = defineModelRenderer({
3483
+ var model19 = defineModelRenderer({
3130
3484
  name: "tslotgusset",
3131
3485
  schema: tSlotGussetModelDefinitionSchema,
3132
3486
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotGusset, { ...props }),
3133
3487
  pads: "none"
3134
3488
  });
3135
- function register17(registry) {
3136
- registry.register(model17);
3489
+ function register19(registry) {
3490
+ registry.register(model19);
3137
3491
  }
3138
3492
 
3139
3493
  // lib/models/tslotinsidecorner/register.tsx
@@ -3213,14 +3567,14 @@ function TSlotInsideCorner({
3213
3567
  }
3214
3568
 
3215
3569
  // lib/models/tslotinsidecorner/register.tsx
3216
- var model18 = defineModelRenderer({
3570
+ var model20 = defineModelRenderer({
3217
3571
  name: "tslotinsidecorner",
3218
3572
  schema: tSlotInsideCornerModelDefinitionSchema,
3219
3573
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotInsideCorner, { ...props }),
3220
3574
  pads: "none"
3221
3575
  });
3222
- function register18(registry) {
3223
- registry.register(model18);
3576
+ function register20(registry) {
3577
+ registry.register(model20);
3224
3578
  }
3225
3579
 
3226
3580
  // lib/models/wormgear/register.tsx
@@ -3412,14 +3766,14 @@ function WormGear({ color = "#737e8f", ...props }) {
3412
3766
  }
3413
3767
 
3414
3768
  // lib/models/wormgear/register.tsx
3415
- var model19 = defineModelRenderer({
3769
+ var model21 = defineModelRenderer({
3416
3770
  name: "wormgear",
3417
3771
  schema: wormGearModelDefinitionSchema,
3418
3772
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
3419
3773
  pads: "none"
3420
3774
  });
3421
- function register19(registry) {
3422
- registry.register(model19);
3775
+ function register21(registry) {
3776
+ registry.register(model21);
3423
3777
  }
3424
3778
 
3425
3779
  // lib/generated/model-renderers.ts
@@ -3443,6 +3797,8 @@ function registerAllModelRenderers(registry) {
3443
3797
  register17(registry);
3444
3798
  register18(registry);
3445
3799
  register19(registry);
3800
+ register20(registry);
3801
+ register21(registry);
3446
3802
  }
3447
3803
 
3448
3804
  // lib/default-model-registry.ts
@@ -10999,10 +11355,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
10999
11355
  var Footprinter3d = ({ footprint }) => {
11000
11356
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
11001
11357
  if (mp3.getModelNames().includes(modelFn)) {
11002
- const model20 = mp3.string(footprint).json();
11003
- const renderer = modelRendererRegistry.get(model20.fn);
11358
+ const model22 = mp3.string(footprint).json();
11359
+ const renderer = modelRendererRegistry.get(model22.fn);
11004
11360
  if (renderer) {
11005
- return renderer.render(model20);
11361
+ return renderer.render(model22);
11006
11362
  }
11007
11363
  }
11008
11364
  let normalizedFootprint = footprint;
@@ -11835,8 +12191,8 @@ function renderNode(node, colorCtx, renderCtx) {
11835
12191
  }
11836
12192
  return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
11837
12193
  }
11838
- function render(root, jscad4) {
11839
- const geometries = renderNode(root, void 0, { jscad: jscad4 });
12194
+ function render(root, jscad7) {
12195
+ const geometries = renderNode(root, void 0, { jscad: jscad7 });
11840
12196
  return {
11841
12197
  geometries: geometries.map(
11842
12198
  (entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
@@ -11928,24 +12284,24 @@ function convertCSGToThreeGeom(csg) {
11928
12284
  }
11929
12285
 
11930
12286
  // lib/vanilla/index.ts
11931
- function getJscadModelForFootprint(footprint, jscad4) {
12287
+ function getJscadModelForFootprint(footprint, jscad7) {
11932
12288
  const vnode = h(Footprinter3d, { footprint });
11933
- return render(vnode, jscad4);
12289
+ return render(vnode, jscad7);
11934
12290
  }
11935
- function getJscadModelForFootprintWithPads(footprint, jscad4) {
12291
+ function getJscadModelForFootprintWithPads(footprint, jscad7) {
11936
12292
  const vnode = h(
11937
12293
  Fragment,
11938
12294
  {},
11939
12295
  h(Footprinter3d, { footprint }),
11940
12296
  h(ExtrudedPads, { footprint })
11941
12297
  );
11942
- return render(vnode, jscad4);
12298
+ return render(vnode, jscad7);
11943
12299
  }
11944
- function createJSCADRenderer(jscad4) {
12300
+ function createJSCADRenderer(jscad7) {
11945
12301
  function createJSCADRoot(container) {
11946
12302
  return {
11947
12303
  render(element) {
11948
- const { geometries } = render(element, jscad4);
12304
+ const { geometries } = render(element, jscad7);
11949
12305
  container.splice(0, container.length, ...geometries);
11950
12306
  }
11951
12307
  };
@@ -11955,6 +12311,7 @@ function createJSCADRenderer(jscad4) {
11955
12311
  export {
11956
12312
  ButtonScrew,
11957
12313
  CableGrommet,
12314
+ ClampingShaftCollar,
11958
12315
  CompressionSpring,
11959
12316
  FlangedBushing,
11960
12317
  FlatHeadScrew,
@@ -11969,6 +12326,7 @@ export {
11969
12326
  NemaMotor,
11970
12327
  PanScrew,
11971
12328
  PlainBushing,
12329
+ ShaftCollar,
11972
12330
  SheetMetal,
11973
12331
  SpurGear,
11974
12332
  TSlotExtrusion,
@@ -11980,6 +12338,8 @@ export {
11980
12338
  createButtonScrewMesh,
11981
12339
  createCableGrommetGeom,
11982
12340
  createCableGrommetMesh,
12341
+ createClampingShaftCollarGeom,
12342
+ createClampingShaftCollarMesh,
11983
12343
  createCompressionSpringGeom,
11984
12344
  createCompressionSpringMesh,
11985
12345
  createFlangedBushingGeom,
@@ -11999,6 +12359,8 @@ export {
11999
12359
  createPanScrewMesh,
12000
12360
  createPlainBushingGeom,
12001
12361
  createPlainBushingMesh,
12362
+ createShaftCollarGeom,
12363
+ createShaftCollarMesh,
12002
12364
  createSheetMetalGeom,
12003
12365
  createSheetMetalMesh,
12004
12366
  createSpurGearGeom,