jscad-electronics 0.0.205 → 0.0.206

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, CompressionSpringModelPropsInput, FlangedBushingModelPropsInput, FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexNutModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, PlainBushingModelPropsInput, SheetMetalModelPropsInput, TSlotExtrusionModelPropsInput, TSlotGussetModelPropsInput, TSlotInsideCornerModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
6
+ import { ButtonScrewModelPropsInput, CableGrommetModelPropsInput, CompressionSpringModelPropsInput, FlangedBushingModelPropsInput, FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexNutModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, PlainBushingModelPropsInput, ShaftCollarModelPropsInput, SheetMetalModelPropsInput, TSlotExtrusionModelPropsInput, TSlotGussetModelPropsInput, TSlotInsideCornerModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
7
7
 
8
8
  type VNode = {
9
9
  type: any;
@@ -243,6 +243,22 @@ type PlainBushingProps = PlainBushingModelPropsInput & {
243
243
  declare function createPlainBushingGeom(input: PlainBushingModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
244
244
  declare function PlainBushing({ color, ...props }: PlainBushingProps): react_jsx_runtime.JSX.Element;
245
245
 
246
+ type ShaftMountMesh = {
247
+ positions: number[];
248
+ indices: number[];
249
+ };
250
+
251
+ type ShaftCollarMesh = ShaftMountMesh;
252
+ /** Geometry is driven by the corresponding modelprinter schema and hole layout. */
253
+ declare function createShaftCollarMesh(input: ShaftCollarModelPropsInput): ShaftCollarMesh;
254
+
255
+ type ShaftCollarProps = ShaftCollarModelPropsInput & {
256
+ color?: string;
257
+ };
258
+ /** Datum and mounting-hole coordinates follow the modelprinter contract. */
259
+ declare function createShaftCollarGeom(input: ShaftCollarModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
260
+ declare function ShaftCollar({ color, ...props }: ShaftCollarProps): react_jsx_runtime.JSX.Element;
261
+
246
262
  interface SheetMetalMesh {
247
263
  positions: number[];
248
264
  indices: number[];
@@ -342,4 +358,4 @@ declare function createJSCADRenderer(jscad: typeof jscadModeling): {
342
358
  };
343
359
  };
344
360
 
345
- 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, TSlotExtrusion, type TSlotExtrusionMesh, type TSlotExtrusionProps, TSlotGusset, type TSlotGussetMesh, type TSlotGussetProps, TSlotInsideCorner, type TSlotInsideCornerMesh, type TSlotInsideCornerProps, 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, createTSlotExtrusionGeom, createTSlotExtrusionMesh, createTSlotGussetGeom, createTSlotGussetMesh, createTSlotInsideCornerGeom, createTSlotInsideCornerMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
361
+ 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, ShaftCollar, type ShaftCollarMesh, type ShaftCollarProps, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, TSlotExtrusion, type TSlotExtrusionMesh, type TSlotExtrusionProps, TSlotGusset, type TSlotGussetMesh, type TSlotGussetProps, TSlotInsideCorner, type TSlotInsideCornerMesh, type TSlotInsideCornerProps, 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, createShaftCollarGeom, createShaftCollarMesh, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createTSlotExtrusionGeom, createTSlotExtrusionMesh, createTSlotGussetGeom, createTSlotGussetMesh, createTSlotInsideCornerGeom, createTSlotInsideCornerMesh, 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(model20) {
187
- return model20;
186
+ function defineModelRenderer(model21) {
187
+ return model21;
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(model21) {
192
+ if (typeof model21.name !== "string" || !/^[a-z]+$/.test(model21.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(model21.name)) {
198
+ throw new Error(`Model renderer "${model21.name}" is already registered`);
199
199
  }
200
- if (model20.pads !== "none" && model20.pads !== "footprinter") {
200
+ if (model21.pads !== "none" && model21.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 } = model21;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -2730,6 +2730,295 @@ function register13(registry) {
2730
2730
  registry.register(model13);
2731
2731
  }
2732
2732
 
2733
+ // lib/models/shaftcollar/register.tsx
2734
+ import { shaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
2735
+
2736
+ // lib/models/shaftcollar/mesh.ts
2737
+ import "@jscad/modeling";
2738
+ import {
2739
+ shaftCollarModelPropsSchema,
2740
+ getShaftCollarDimensions
2741
+ } from "@tscircuit/modelprinter";
2742
+
2743
+ // lib/mechanical/shaft-mount-geometry.ts
2744
+ import jscad4 from "@jscad/modeling";
2745
+ var bodySegments = 64;
2746
+ var threadSegments = 24;
2747
+ var samplesPerTurn = 12;
2748
+ function assertShaftMountResolution(holes) {
2749
+ let triangles = 0;
2750
+ for (const hole of holes) {
2751
+ const steps = hole.threadPitch ? Math.ceil(hole.depth / hole.threadPitch * samplesPerTurn) : 1;
2752
+ if (!Number.isFinite(steps) || steps > 768)
2753
+ throw new Error(
2754
+ "Shaft mount exceeds mesh resolution limit (64 thread turns per hole)"
2755
+ );
2756
+ triangles += (steps + 1) * threadSegments * 2;
2757
+ }
2758
+ if (triangles > 1e5)
2759
+ throw new Error("Shaft mount exceeds total mesh resolution limit");
2760
+ }
2761
+ function createAnnularSleeve({
2762
+ outerRadius,
2763
+ boreARadius,
2764
+ boreBRadius = boreARadius,
2765
+ length,
2766
+ chamfer,
2767
+ stepZ = length / 2
2768
+ }) {
2769
+ const halfAngle = Math.PI / bodySegments;
2770
+ const cosine = Math.cos(halfAngle);
2771
+ if ((Math.max(boreARadius, boreBRadius) + chamfer) / cosine >= (outerRadius - chamfer) * cosine - 1e-6)
2772
+ throw new Error(
2773
+ "Shaft mount wall/chamfer ligament exceeds mesh resolution limit"
2774
+ );
2775
+ const raw = [
2776
+ [0, outerRadius - chamfer, false],
2777
+ [chamfer, outerRadius, false],
2778
+ [length - chamfer, outerRadius, false],
2779
+ [length, outerRadius - chamfer, false],
2780
+ [length, boreBRadius + chamfer, true],
2781
+ [length - chamfer, boreBRadius, true],
2782
+ [stepZ, boreBRadius, true],
2783
+ [stepZ, boreARadius, true],
2784
+ [chamfer, boreARadius, true],
2785
+ [0, boreARadius + chamfer, true]
2786
+ ];
2787
+ const profile = raw.filter(
2788
+ ([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
2789
+ );
2790
+ const positions = [];
2791
+ const indices = [];
2792
+ for (const [z, r, isBore] of profile)
2793
+ for (let i = 0; i < bodySegments; i++) {
2794
+ const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
2795
+ const radius = isBore ? r / cosine : r;
2796
+ positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
2797
+ }
2798
+ for (let row = 0; row < profile.length; row++)
2799
+ for (let i = 0; i < bodySegments; i++) {
2800
+ const next = (i + 1) % bodySegments;
2801
+ const a = row * bodySegments + i, b = row * bodySegments + next;
2802
+ const c = (row + 1) % profile.length * bodySegments + next, d = (row + 1) % profile.length * bodySegments + i;
2803
+ indices.push(a, b, c, a, c, d);
2804
+ }
2805
+ return indexedMeshToGeom3({ positions, indices });
2806
+ }
2807
+ function createMountingHoleCutter(hole) {
2808
+ assertShaftMountResolution([hole]);
2809
+ const pitch = hole.threadPitch;
2810
+ const steps = pitch ? Math.max(2, Math.ceil(hole.depth / pitch * samplesPerTurn)) : 1;
2811
+ const segments = pitch ? threadSegments : 48;
2812
+ const extension = 1e-4;
2813
+ const radius = hole.diameter / 2;
2814
+ const threadDepth = pitch ? Math.min(pitch * 0.541266, radius * 0.8) : 0;
2815
+ const hand = hole.threadHand === "left" ? -1 : 1;
2816
+ const positions = [];
2817
+ const indices = [];
2818
+ const [dx, dy, dz] = hole.direction;
2819
+ if (Math.abs(dz) > 1e-10 || Math.abs(Math.hypot(dx, dy) - 1) > 1e-10)
2820
+ throw new Error("Expected a horizontal unit hole axis");
2821
+ const push = (x, y, z) => {
2822
+ positions.push(
2823
+ hole.start[0] + y * dy + z * dx,
2824
+ hole.start[1] - y * dx + z * dy,
2825
+ hole.start[2] + x
2826
+ );
2827
+ };
2828
+ for (let row = 0; row <= steps; row++) {
2829
+ const z = -extension + (hole.depth + 2 * extension) * row / steps;
2830
+ for (let i = 0; i < segments; i++) {
2831
+ const angle = i * Math.PI * 2 / segments;
2832
+ const phase = pitch ? ((z / pitch - hand * angle / (Math.PI * 2)) % 1 + 1) % 1 : 0;
2833
+ const distance2 = Math.min(phase, 1 - phase);
2834
+ const r = radius - Math.min(
2835
+ threadDepth,
2836
+ Math.max(0, (distance2 - 1 / 8) * (pitch ?? 0) * Math.sqrt(3))
2837
+ );
2838
+ push(r * Math.cos(angle), r * Math.sin(angle), z);
2839
+ }
2840
+ }
2841
+ for (let row = 0; row < steps; row++)
2842
+ for (let i = 0; i < segments; i++) {
2843
+ const next = (i + 1) % segments;
2844
+ const a = row * segments + i, b = row * segments + next, c = (row + 1) * segments + next, d = (row + 1) * segments + i;
2845
+ indices.push(a, b, c, a, c, d);
2846
+ }
2847
+ for (const end of [0, steps]) {
2848
+ const center = positions.length / 3;
2849
+ push(0, 0, end === 0 ? -extension : hole.depth + extension);
2850
+ for (let i = 0; i < segments; i++) {
2851
+ const a = end * segments + i, b = end * segments + (i + 1) % segments;
2852
+ indices.push(center, end === 0 ? b : a, end === 0 ? a : b);
2853
+ }
2854
+ }
2855
+ return indexedMeshToGeom3({ positions, indices });
2856
+ }
2857
+ function subtractShaftMountParts(body, ...cutters) {
2858
+ const factor = 100;
2859
+ const scaled = [body, ...cutters].map(
2860
+ (geometry) => jscad4.transforms.scale([factor, factor, factor], geometry)
2861
+ );
2862
+ const result = jscad4.booleans.subtract(scaled[0], ...scaled.slice(1));
2863
+ return jscad4.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
2864
+ }
2865
+ function finishShaftMountMesh(geometry) {
2866
+ const positions = [];
2867
+ const vertices = /* @__PURE__ */ new Map();
2868
+ const tolerance = 1e-6;
2869
+ const weld = (point) => {
2870
+ const cell = point.map((v) => Math.floor(v / tolerance));
2871
+ for (let x = -1; x <= 1; x++)
2872
+ for (let y = -1; y <= 1; y++)
2873
+ for (let z = -1; z <= 1; z++) {
2874
+ const nearby = vertices.get(
2875
+ [cell[0] + x, cell[1] + y, cell[2] + z].join(",")
2876
+ ) ?? [];
2877
+ for (const index2 of nearby)
2878
+ if (Math.hypot(
2879
+ ...point.map((v, axis) => v - positions[index2 * 3 + axis])
2880
+ ) < tolerance)
2881
+ return index2;
2882
+ }
2883
+ const index = positions.length / 3;
2884
+ positions.push(...point);
2885
+ const key = cell.join(",");
2886
+ vertices.set(key, [...vertices.get(key) ?? [], index]);
2887
+ return index;
2888
+ };
2889
+ const polygons = jscad4.geometries.geom3.toPolygons(geometry).map(
2890
+ (polygon) => polygon.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
2891
+ ).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
2892
+ let longest = 0;
2893
+ let origin = [];
2894
+ let direction = [];
2895
+ for (let i = 0; i < ids.length; i++)
2896
+ for (let j = i + 1; j < ids.length; j++) {
2897
+ const a = positions.slice(ids[i] * 3, ids[i] * 3 + 3);
2898
+ const delta = positions.slice(ids[j] * 3, ids[j] * 3 + 3).map((v, axis) => v - a[axis]);
2899
+ const squared = delta.reduce((sum, v) => sum + v * v, 0);
2900
+ if (squared > longest) {
2901
+ longest = squared;
2902
+ origin = a;
2903
+ direction = delta;
2904
+ }
2905
+ }
2906
+ return ids.some((id) => {
2907
+ const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
2908
+ const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / longest;
2909
+ return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
2910
+ });
2911
+ });
2912
+ const edgeKey = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
2913
+ const edges = /* @__PURE__ */ new Map();
2914
+ for (const polygon of polygons)
2915
+ for (let i = 0; i < polygon.length; i++) {
2916
+ const a = polygon[i], b = polygon[(i + 1) % polygon.length], key = edgeKey(a, b);
2917
+ const edge = edges.get(key) ?? { a, b, count: 0 };
2918
+ edge.count++;
2919
+ edges.set(key, edge);
2920
+ }
2921
+ const unmatched = [...edges.values()].filter((edge) => edge.count === 1);
2922
+ const candidates = [...new Set(unmatched.flatMap((edge) => [edge.a, edge.b]))];
2923
+ const splits = /* @__PURE__ */ new Map();
2924
+ for (const { a, b } of unmatched) {
2925
+ const origin = positions.slice(a * 3, a * 3 + 3);
2926
+ const direction = positions.slice(b * 3, b * 3 + 3).map((v, axis) => v - origin[axis]);
2927
+ const squared = direction.reduce((sum, v) => sum + v * v, 0);
2928
+ const points = [];
2929
+ for (const id of candidates) {
2930
+ if (id === a || id === b) continue;
2931
+ const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
2932
+ const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / squared;
2933
+ if (t <= 0 || t >= 1) continue;
2934
+ const distance2 = Math.hypot(
2935
+ ...delta.map((v, axis) => v - t * direction[axis])
2936
+ );
2937
+ if (distance2 < tolerance) points.push({ id, t });
2938
+ }
2939
+ points.sort((p, q) => p.t - q.t);
2940
+ splits.set(
2941
+ `${a},${b}`,
2942
+ points.map((p) => p.id)
2943
+ );
2944
+ splits.set(`${b},${a}`, points.map((p) => p.id).reverse());
2945
+ }
2946
+ const indices = [];
2947
+ for (const polygon of polygons) {
2948
+ const perimeter = polygon.flatMap((a, i) => [
2949
+ a,
2950
+ ...(splits.get(`${a},${polygon[(i + 1) % polygon.length]}`) ?? []).filter((id) => !polygon.includes(id))
2951
+ ]);
2952
+ const unique = perimeter.filter(
2953
+ (id, i) => id !== perimeter[(i + perimeter.length - 1) % perimeter.length]
2954
+ );
2955
+ if (unique.length === 3) {
2956
+ indices.push(...unique);
2957
+ continue;
2958
+ }
2959
+ const center = positions.length / 3;
2960
+ positions.push(
2961
+ ...[0, 1, 2].map(
2962
+ (axis) => unique.reduce((sum, id) => sum + positions[id * 3 + axis], 0) / unique.length
2963
+ )
2964
+ );
2965
+ for (let i = 0; i < unique.length; i++)
2966
+ indices.push(center, unique[i], unique[(i + 1) % unique.length]);
2967
+ }
2968
+ const compact = [];
2969
+ const remap = /* @__PURE__ */ new Map();
2970
+ return {
2971
+ positions: compact,
2972
+ indices: indices.map((index) => {
2973
+ let next = remap.get(index);
2974
+ if (next === void 0) {
2975
+ next = compact.length / 3;
2976
+ remap.set(index, next);
2977
+ compact.push(...positions.slice(index * 3, index * 3 + 3));
2978
+ }
2979
+ return next;
2980
+ })
2981
+ };
2982
+ }
2983
+
2984
+ // lib/models/shaftcollar/mesh.ts
2985
+ function createShaftCollarMesh(input) {
2986
+ const props = shaftCollarModelPropsSchema.parse(input);
2987
+ const dimensions = getShaftCollarDimensions(props);
2988
+ assertShaftMountResolution([dimensions.screwHole]);
2989
+ const body = createAnnularSleeve({
2990
+ outerRadius: props.outerDiameter / 2,
2991
+ boreARadius: props.boreDiameter / 2,
2992
+ length: props.width,
2993
+ chamfer: props.chamfer
2994
+ });
2995
+ return finishShaftMountMesh(
2996
+ subtractShaftMountParts(
2997
+ body,
2998
+ createMountingHoleCutter(dimensions.screwHole)
2999
+ )
3000
+ );
3001
+ }
3002
+
3003
+ // lib/models/shaftcollar/ShaftCollar.tsx
3004
+ function createShaftCollarGeom(input) {
3005
+ return indexedMeshToGeom3(createShaftCollarMesh(input));
3006
+ }
3007
+ function ShaftCollar({ color = "#737e8f", ...props }) {
3008
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createShaftCollarGeom(props) }) });
3009
+ }
3010
+
3011
+ // lib/models/shaftcollar/register.tsx
3012
+ var model14 = defineModelRenderer({
3013
+ name: "shaftcollar",
3014
+ schema: shaftCollarModelDefinitionSchema,
3015
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(ShaftCollar, { ...props }),
3016
+ pads: "none"
3017
+ });
3018
+ function register14(registry) {
3019
+ registry.register(model14);
3020
+ }
3021
+
2733
3022
  // lib/models/sheetmetal/register.tsx
2734
3023
  import { sheetMetalModelDefinitionSchema } from "@tscircuit/modelprinter";
2735
3024
 
@@ -2887,14 +3176,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
2887
3176
  }
2888
3177
 
2889
3178
  // lib/models/sheetmetal/register.tsx
2890
- var model14 = defineModelRenderer({
3179
+ var model15 = defineModelRenderer({
2891
3180
  name: "sheetmetal",
2892
3181
  schema: sheetMetalModelDefinitionSchema,
2893
3182
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
2894
3183
  pads: "none"
2895
3184
  });
2896
- function register14(registry) {
2897
- registry.register(model14);
3185
+ function register15(registry) {
3186
+ registry.register(model15);
2898
3187
  }
2899
3188
 
2900
3189
  // lib/models/spurgear/register.tsx
@@ -2909,14 +3198,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
2909
3198
  }
2910
3199
 
2911
3200
  // lib/models/spurgear/register.tsx
2912
- var model15 = defineModelRenderer({
3201
+ var model16 = defineModelRenderer({
2913
3202
  name: "spurgear",
2914
3203
  schema: spurGearModelDefinitionSchema,
2915
3204
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
2916
3205
  pads: "none"
2917
3206
  });
2918
- function register15(registry) {
2919
- registry.register(model15);
3207
+ function register16(registry) {
3208
+ registry.register(model16);
2920
3209
  }
2921
3210
 
2922
3211
  // lib/models/tslotextrusion/register.tsx
@@ -3066,14 +3355,14 @@ function TSlotExtrusion({
3066
3355
  }
3067
3356
 
3068
3357
  // lib/models/tslotextrusion/register.tsx
3069
- var model16 = defineModelRenderer({
3358
+ var model17 = defineModelRenderer({
3070
3359
  name: "tslotextrusion",
3071
3360
  schema: tSlotExtrusionModelDefinitionSchema,
3072
3361
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotExtrusion, { ...props }),
3073
3362
  pads: "none"
3074
3363
  });
3075
- function register16(registry) {
3076
- registry.register(model16);
3364
+ function register17(registry) {
3365
+ registry.register(model17);
3077
3366
  }
3078
3367
 
3079
3368
  // lib/models/tslotgusset/register.tsx
@@ -3126,14 +3415,14 @@ function TSlotGusset({ color = "#8995a3", ...props }) {
3126
3415
  }
3127
3416
 
3128
3417
  // lib/models/tslotgusset/register.tsx
3129
- var model17 = defineModelRenderer({
3418
+ var model18 = defineModelRenderer({
3130
3419
  name: "tslotgusset",
3131
3420
  schema: tSlotGussetModelDefinitionSchema,
3132
3421
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotGusset, { ...props }),
3133
3422
  pads: "none"
3134
3423
  });
3135
- function register17(registry) {
3136
- registry.register(model17);
3424
+ function register18(registry) {
3425
+ registry.register(model18);
3137
3426
  }
3138
3427
 
3139
3428
  // lib/models/tslotinsidecorner/register.tsx
@@ -3213,14 +3502,14 @@ function TSlotInsideCorner({
3213
3502
  }
3214
3503
 
3215
3504
  // lib/models/tslotinsidecorner/register.tsx
3216
- var model18 = defineModelRenderer({
3505
+ var model19 = defineModelRenderer({
3217
3506
  name: "tslotinsidecorner",
3218
3507
  schema: tSlotInsideCornerModelDefinitionSchema,
3219
3508
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotInsideCorner, { ...props }),
3220
3509
  pads: "none"
3221
3510
  });
3222
- function register18(registry) {
3223
- registry.register(model18);
3511
+ function register19(registry) {
3512
+ registry.register(model19);
3224
3513
  }
3225
3514
 
3226
3515
  // lib/models/wormgear/register.tsx
@@ -3412,14 +3701,14 @@ function WormGear({ color = "#737e8f", ...props }) {
3412
3701
  }
3413
3702
 
3414
3703
  // lib/models/wormgear/register.tsx
3415
- var model19 = defineModelRenderer({
3704
+ var model20 = defineModelRenderer({
3416
3705
  name: "wormgear",
3417
3706
  schema: wormGearModelDefinitionSchema,
3418
3707
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
3419
3708
  pads: "none"
3420
3709
  });
3421
- function register19(registry) {
3422
- registry.register(model19);
3710
+ function register20(registry) {
3711
+ registry.register(model20);
3423
3712
  }
3424
3713
 
3425
3714
  // lib/generated/model-renderers.ts
@@ -3443,6 +3732,7 @@ function registerAllModelRenderers(registry) {
3443
3732
  register17(registry);
3444
3733
  register18(registry);
3445
3734
  register19(registry);
3735
+ register20(registry);
3446
3736
  }
3447
3737
 
3448
3738
  // lib/default-model-registry.ts
@@ -10999,10 +11289,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
10999
11289
  var Footprinter3d = ({ footprint }) => {
11000
11290
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
11001
11291
  if (mp3.getModelNames().includes(modelFn)) {
11002
- const model20 = mp3.string(footprint).json();
11003
- const renderer = modelRendererRegistry.get(model20.fn);
11292
+ const model21 = mp3.string(footprint).json();
11293
+ const renderer = modelRendererRegistry.get(model21.fn);
11004
11294
  if (renderer) {
11005
- return renderer.render(model20);
11295
+ return renderer.render(model21);
11006
11296
  }
11007
11297
  }
11008
11298
  let normalizedFootprint = footprint;
@@ -11835,8 +12125,8 @@ function renderNode(node, colorCtx, renderCtx) {
11835
12125
  }
11836
12126
  return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
11837
12127
  }
11838
- function render(root, jscad4) {
11839
- const geometries = renderNode(root, void 0, { jscad: jscad4 });
12128
+ function render(root, jscad6) {
12129
+ const geometries = renderNode(root, void 0, { jscad: jscad6 });
11840
12130
  return {
11841
12131
  geometries: geometries.map(
11842
12132
  (entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
@@ -11928,24 +12218,24 @@ function convertCSGToThreeGeom(csg) {
11928
12218
  }
11929
12219
 
11930
12220
  // lib/vanilla/index.ts
11931
- function getJscadModelForFootprint(footprint, jscad4) {
12221
+ function getJscadModelForFootprint(footprint, jscad6) {
11932
12222
  const vnode = h(Footprinter3d, { footprint });
11933
- return render(vnode, jscad4);
12223
+ return render(vnode, jscad6);
11934
12224
  }
11935
- function getJscadModelForFootprintWithPads(footprint, jscad4) {
12225
+ function getJscadModelForFootprintWithPads(footprint, jscad6) {
11936
12226
  const vnode = h(
11937
12227
  Fragment,
11938
12228
  {},
11939
12229
  h(Footprinter3d, { footprint }),
11940
12230
  h(ExtrudedPads, { footprint })
11941
12231
  );
11942
- return render(vnode, jscad4);
12232
+ return render(vnode, jscad6);
11943
12233
  }
11944
- function createJSCADRenderer(jscad4) {
12234
+ function createJSCADRenderer(jscad6) {
11945
12235
  function createJSCADRoot(container) {
11946
12236
  return {
11947
12237
  render(element) {
11948
- const { geometries } = render(element, jscad4);
12238
+ const { geometries } = render(element, jscad6);
11949
12239
  container.splice(0, container.length, ...geometries);
11950
12240
  }
11951
12241
  };
@@ -11969,6 +12259,7 @@ export {
11969
12259
  NemaMotor,
11970
12260
  PanScrew,
11971
12261
  PlainBushing,
12262
+ ShaftCollar,
11972
12263
  SheetMetal,
11973
12264
  SpurGear,
11974
12265
  TSlotExtrusion,
@@ -11999,6 +12290,8 @@ export {
11999
12290
  createPanScrewMesh,
12000
12291
  createPlainBushingGeom,
12001
12292
  createPlainBushingMesh,
12293
+ createShaftCollarGeom,
12294
+ createShaftCollarMesh,
12002
12295
  createSheetMetalGeom,
12003
12296
  createSheetMetalMesh,
12004
12297
  createSpurGearGeom,