@tscircuit/3d-viewer 0.0.544 → 0.0.545

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.
Files changed (2) hide show
  1. package/dist/index.js +799 -351
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -14433,7 +14433,7 @@ var require_browser = __commonJS({
14433
14433
 
14434
14434
  // src/CadViewer.tsx
14435
14435
  import { useState as useState36, useCallback as useCallback21, useRef as useRef26, useEffect as useEffect45 } from "react";
14436
- import * as THREE39 from "three";
14436
+ import * as THREE43 from "three";
14437
14437
 
14438
14438
  // src/CadViewerJscad.tsx
14439
14439
  import { su as su11 } from "@tscircuit/circuit-json-util";
@@ -28889,8 +28889,8 @@ var FootprinterModel = ({
28889
28889
  };
28890
28890
 
28891
28891
  // src/three-components/GltfModel.tsx
28892
- import { useState as useState4, useEffect as useEffect6 } from "react";
28893
- import * as THREE5 from "three";
28892
+ import { useState as useState4, useEffect as useEffect7 } from "react";
28893
+ import * as THREE7 from "three";
28894
28894
  import { GLTFLoader } from "three-stdlib";
28895
28895
 
28896
28896
  // src/react-three/getDefaultEnvironmentMap.ts
@@ -28920,6 +28920,170 @@ var getDefaultEnvironmentMap = (renderer) => {
28920
28920
  return texture;
28921
28921
  };
28922
28922
 
28923
+ // src/three-components/useCadModelTransformGraph.ts
28924
+ import { useEffect as useEffect6, useMemo as useMemo5 } from "react";
28925
+ import * as THREE6 from "three";
28926
+
28927
+ // src/utils/cad-model-fit.ts
28928
+ import * as THREE5 from "three";
28929
+ function getObjectBoundsRelativeToParent(object) {
28930
+ const bounds = new THREE5.Box3();
28931
+ let hasBounds = false;
28932
+ object.updateWorldMatrix(true, false);
28933
+ const parentInverseMatrix = object.parent ? object.parent.matrixWorld.clone().invert() : new THREE5.Matrix4();
28934
+ object.traverse((node) => {
28935
+ node.updateWorldMatrix(true, false);
28936
+ if (node instanceof THREE5.Mesh && node.geometry) {
28937
+ if (!node.geometry.boundingBox) {
28938
+ node.geometry.computeBoundingBox();
28939
+ }
28940
+ if (node.geometry.boundingBox) {
28941
+ const transformedBounds = node.geometry.boundingBox.clone();
28942
+ transformedBounds.applyMatrix4(node.matrixWorld);
28943
+ transformedBounds.applyMatrix4(parentInverseMatrix);
28944
+ if (!hasBounds) {
28945
+ bounds.copy(transformedBounds);
28946
+ hasBounds = true;
28947
+ } else {
28948
+ bounds.union(transformedBounds);
28949
+ }
28950
+ }
28951
+ }
28952
+ });
28953
+ return hasBounds ? bounds : null;
28954
+ }
28955
+ function getLocalBoundsSize(object) {
28956
+ const bounds = getObjectBoundsRelativeToParent(object);
28957
+ if (!bounds) {
28958
+ return new THREE5.Vector3();
28959
+ }
28960
+ return bounds.getSize(new THREE5.Vector3());
28961
+ }
28962
+ function getCadModelFitScale(object, targetSize, fitMode = "contain_within_bounds") {
28963
+ if (!targetSize) {
28964
+ return [1, 1, 1];
28965
+ }
28966
+ const size4 = getLocalBoundsSize(object);
28967
+ const safeScale = [
28968
+ size4.x > 0 ? targetSize[0] / size4.x : 1,
28969
+ size4.y > 0 ? targetSize[1] / size4.y : 1,
28970
+ size4.z > 0 ? targetSize[2] / size4.z : 1
28971
+ ];
28972
+ if (fitMode === "fill_bounds") {
28973
+ return safeScale;
28974
+ }
28975
+ const uniformScale = Math.min(...safeScale);
28976
+ return [uniformScale, uniformScale, uniformScale];
28977
+ }
28978
+
28979
+ // src/three-components/useCadModelTransformGraph.ts
28980
+ var useCadModelTransformGraph = ({
28981
+ model,
28982
+ position,
28983
+ rotation,
28984
+ modelOffset = [0, 0, 0],
28985
+ modelRotation = [0, 0, 0],
28986
+ sourceCoordinateTransform,
28987
+ modelSize,
28988
+ modelFitMode = "contain_within_bounds",
28989
+ scale: scale2
28990
+ }) => {
28991
+ const { rootObject } = useThree();
28992
+ const boardTransformGroup = useMemo5(() => new THREE6.Group(), []);
28993
+ const fitTransformGroup = useMemo5(() => new THREE6.Group(), []);
28994
+ const modelTransformGroup = useMemo5(() => new THREE6.Group(), []);
28995
+ const loaderTransformGroup = useMemo5(() => new THREE6.Group(), []);
28996
+ useEffect6(() => {
28997
+ boardTransformGroup.add(fitTransformGroup);
28998
+ return () => {
28999
+ boardTransformGroup.remove(fitTransformGroup);
29000
+ };
29001
+ }, [boardTransformGroup, fitTransformGroup]);
29002
+ useEffect6(() => {
29003
+ fitTransformGroup.add(modelTransformGroup);
29004
+ return () => {
29005
+ fitTransformGroup.remove(modelTransformGroup);
29006
+ };
29007
+ }, [fitTransformGroup, modelTransformGroup]);
29008
+ useEffect6(() => {
29009
+ modelTransformGroup.add(loaderTransformGroup);
29010
+ return () => {
29011
+ modelTransformGroup.remove(loaderTransformGroup);
29012
+ };
29013
+ }, [modelTransformGroup, loaderTransformGroup]);
29014
+ useEffect6(() => {
29015
+ while (loaderTransformGroup.children.length > 0) {
29016
+ const firstChild = loaderTransformGroup.children[0];
29017
+ if (!firstChild) break;
29018
+ loaderTransformGroup.remove(firstChild);
29019
+ }
29020
+ if (model) {
29021
+ loaderTransformGroup.add(model);
29022
+ }
29023
+ }, [loaderTransformGroup, model]);
29024
+ useEffect6(() => {
29025
+ if (!sourceCoordinateTransform) {
29026
+ loaderTransformGroup.matrixAutoUpdate = true;
29027
+ loaderTransformGroup.position.set(0, 0, 0);
29028
+ loaderTransformGroup.rotation.set(0, 0, 0);
29029
+ loaderTransformGroup.scale.set(1, 1, 1);
29030
+ loaderTransformGroup.updateMatrix();
29031
+ return;
29032
+ }
29033
+ loaderTransformGroup.matrixAutoUpdate = false;
29034
+ loaderTransformGroup.matrix.copy(sourceCoordinateTransform);
29035
+ loaderTransformGroup.matrixWorldNeedsUpdate = true;
29036
+ }, [loaderTransformGroup, sourceCoordinateTransform]);
29037
+ useEffect6(() => {
29038
+ if (!rootObject) return;
29039
+ rootObject.add(boardTransformGroup);
29040
+ return () => {
29041
+ rootObject.remove(boardTransformGroup);
29042
+ };
29043
+ }, [rootObject, boardTransformGroup]);
29044
+ useEffect6(() => {
29045
+ if (position) {
29046
+ boardTransformGroup.position.fromArray(position);
29047
+ } else {
29048
+ boardTransformGroup.position.set(0, 0, 0);
29049
+ }
29050
+ if (rotation) {
29051
+ boardTransformGroup.rotation.fromArray(rotation);
29052
+ } else {
29053
+ boardTransformGroup.rotation.set(0, 0, 0);
29054
+ }
29055
+ modelTransformGroup.position.fromArray(modelOffset);
29056
+ modelTransformGroup.rotation.fromArray(modelRotation);
29057
+ modelTransformGroup.scale.setScalar(scale2 ?? 1);
29058
+ if (!model) {
29059
+ fitTransformGroup.scale.set(1, 1, 1);
29060
+ return;
29061
+ }
29062
+ fitTransformGroup.scale.set(1, 1, 1);
29063
+ fitTransformGroup.updateWorldMatrix(true, true);
29064
+ const fitScale = getCadModelFitScale(
29065
+ modelTransformGroup,
29066
+ modelSize,
29067
+ modelFitMode
29068
+ );
29069
+ fitTransformGroup.scale.set(fitScale[0], fitScale[1], fitScale[2]);
29070
+ }, [
29071
+ boardTransformGroup,
29072
+ fitTransformGroup,
29073
+ model,
29074
+ modelFitMode,
29075
+ modelOffset,
29076
+ loaderTransformGroup,
29077
+ modelTransformGroup,
29078
+ modelRotation,
29079
+ modelSize,
29080
+ position,
29081
+ rotation,
29082
+ scale2
29083
+ ]);
29084
+ return { boardTransformGroup };
29085
+ };
29086
+
28923
29087
  // src/three-components/GltfModel.tsx
28924
29088
  import { jsx as jsx6 } from "react/jsx-runtime";
28925
29089
  var DEFAULT_ENV_MAP_INTENSITY = 1.25;
@@ -28927,16 +29091,32 @@ function GltfModel({
28927
29091
  gltfUrl,
28928
29092
  position,
28929
29093
  rotation,
29094
+ modelOffset = [0, 0, 0],
29095
+ modelRotation = [0, 0, 0],
29096
+ sourceCoordinateTransform,
29097
+ modelSize,
29098
+ modelFitMode = "contain_within_bounds",
28930
29099
  onHover,
28931
29100
  onUnhover,
28932
29101
  isHovered,
28933
29102
  scale: scale2,
28934
29103
  isTranslucent = false
28935
29104
  }) {
28936
- const { renderer, rootObject } = useThree();
29105
+ const { renderer } = useThree();
28937
29106
  const [model, setModel] = useState4(null);
28938
29107
  const [loadError, setLoadError] = useState4(null);
28939
- useEffect6(() => {
29108
+ const { boardTransformGroup } = useCadModelTransformGraph({
29109
+ model,
29110
+ position,
29111
+ rotation,
29112
+ modelOffset,
29113
+ modelRotation,
29114
+ sourceCoordinateTransform,
29115
+ modelSize,
29116
+ modelFitMode,
29117
+ scale: scale2
29118
+ });
29119
+ useEffect7(() => {
28940
29120
  if (!gltfUrl) return;
28941
29121
  const loader = new GLTFLoader();
28942
29122
  let isMounted = true;
@@ -28946,7 +29126,7 @@ function GltfModel({
28946
29126
  if (!isMounted) return;
28947
29127
  const scene = gltf.scene;
28948
29128
  scene.traverse((child) => {
28949
- if (child instanceof THREE5.Mesh && child.material) {
29129
+ if (child instanceof THREE7.Mesh && child.material) {
28950
29130
  const setMaterialTransparency = (mat) => {
28951
29131
  mat.transparent = isTranslucent;
28952
29132
  mat.opacity = isTranslucent ? 0.5 : 1;
@@ -28975,35 +29155,13 @@ function GltfModel({
28975
29155
  isMounted = false;
28976
29156
  };
28977
29157
  }, [gltfUrl, isTranslucent]);
28978
- useEffect6(() => {
28979
- if (!model) return;
28980
- if (position) model.position.fromArray(position);
28981
- if (rotation) model.rotation.fromArray(rotation);
28982
- if (scale2 !== void 0) model.scale.setScalar(scale2);
28983
- }, [
28984
- model,
28985
- position?.[0],
28986
- position?.[1],
28987
- position?.[2],
28988
- rotation?.[0],
28989
- rotation?.[1],
28990
- rotation?.[2],
28991
- scale2
28992
- ]);
28993
- useEffect6(() => {
28994
- if (!rootObject || !model) return;
28995
- rootObject.add(model);
28996
- return () => {
28997
- rootObject.remove(model);
28998
- };
28999
- }, [rootObject, model]);
29000
- useEffect6(() => {
29158
+ useEffect7(() => {
29001
29159
  if (!model || !renderer) return;
29002
29160
  const environmentMap = getDefaultEnvironmentMap(renderer);
29003
29161
  if (!environmentMap) return;
29004
29162
  const previousMaterialState = [];
29005
29163
  const applyEnvironmentToMaterial = (material) => {
29006
- if (!(material instanceof THREE5.MeshStandardMaterial)) return;
29164
+ if (!(material instanceof THREE7.MeshStandardMaterial)) return;
29007
29165
  previousMaterialState.push({
29008
29166
  material,
29009
29167
  envMap: material.envMap ?? null,
@@ -29016,7 +29174,7 @@ function GltfModel({
29016
29174
  material.needsUpdate = true;
29017
29175
  };
29018
29176
  model.traverse((child) => {
29019
- if (!(child instanceof THREE5.Mesh)) return;
29177
+ if (!(child instanceof THREE7.Mesh)) return;
29020
29178
  const material = child.material;
29021
29179
  if (Array.isArray(material)) {
29022
29180
  material.forEach(applyEnvironmentToMaterial);
@@ -29032,10 +29190,10 @@ function GltfModel({
29032
29190
  });
29033
29191
  };
29034
29192
  }, [model, renderer]);
29035
- useEffect6(() => {
29193
+ useEffect7(() => {
29036
29194
  if (!model) return;
29037
29195
  model.traverse((child) => {
29038
- if (child instanceof THREE5.Mesh && child.material instanceof THREE5.MeshStandardMaterial) {
29196
+ if (child instanceof THREE7.Mesh && child.material instanceof THREE7.MeshStandardMaterial) {
29039
29197
  if (isHovered) {
29040
29198
  child.material.emissive.setHex(255);
29041
29199
  child.material.emissiveIntensity = 0.2;
@@ -29055,7 +29213,7 @@ function GltfModel({
29055
29213
  isHovered,
29056
29214
  onHover,
29057
29215
  onUnhover,
29058
- object: model
29216
+ object: boardTransformGroup
29059
29217
  }
29060
29218
  );
29061
29219
  }
@@ -29063,29 +29221,33 @@ function GltfModel({
29063
29221
  // src/three-components/JscadModel.tsx
29064
29222
  var import_jscad_planner = __toESM(require_dist(), 1);
29065
29223
  var import_modeling = __toESM(require_src(), 1);
29066
- import * as THREE6 from "three";
29067
- import { useMemo as useMemo6, useEffect as useEffect7 } from "react";
29224
+ import * as THREE8 from "three";
29225
+ import { useMemo as useMemo6, useEffect as useEffect8 } from "react";
29068
29226
  import { jsx as jsx7 } from "react/jsx-runtime";
29069
29227
  var JscadModel = ({
29070
29228
  jscadPlan,
29071
29229
  positionOffset,
29072
29230
  rotationOffset,
29231
+ modelOffset = [0, 0, 0],
29232
+ modelRotation = [0, 0, 0],
29233
+ sourceCoordinateTransform,
29234
+ modelSize,
29235
+ modelFitMode = "contain_within_bounds",
29073
29236
  onHover,
29074
29237
  onUnhover,
29075
29238
  isHovered,
29076
29239
  scale: scale2,
29077
29240
  isTranslucent = false
29078
29241
  }) => {
29079
- const { rootObject } = useThree();
29080
29242
  const { threeGeom, material } = useMemo6(() => {
29081
29243
  const jscadObject = (0, import_jscad_planner.executeJscadOperations)(import_modeling.default, jscadPlan);
29082
29244
  if (!jscadObject || !jscadObject.polygons && !jscadObject.sides) {
29083
29245
  return { threeGeom: null, material: null };
29084
29246
  }
29085
29247
  const threeGeom2 = convertCSGToThreeGeom(jscadObject);
29086
- const material2 = new THREE6.MeshStandardMaterial({
29248
+ const material2 = new THREE8.MeshStandardMaterial({
29087
29249
  vertexColors: true,
29088
- side: THREE6.DoubleSide,
29250
+ side: THREE8.DoubleSide,
29089
29251
  transparent: isTranslucent,
29090
29252
  opacity: isTranslucent ? 0.5 : 1,
29091
29253
  depthWrite: !isTranslucent
@@ -29094,36 +29256,25 @@ var JscadModel = ({
29094
29256
  }, [jscadPlan, isTranslucent]);
29095
29257
  const mesh = useMemo6(() => {
29096
29258
  if (!threeGeom) return null;
29097
- const createdMesh = new THREE6.Mesh(threeGeom, material);
29259
+ const createdMesh = new THREE8.Mesh(threeGeom, material);
29098
29260
  createdMesh.renderOrder = isTranslucent ? 2 : 1;
29099
29261
  return createdMesh;
29100
29262
  }, [threeGeom, material, isTranslucent]);
29101
- useEffect7(() => {
29102
- if (!mesh || !rootObject) return;
29103
- rootObject.add(mesh);
29104
- return () => {
29105
- rootObject.remove(mesh);
29106
- };
29107
- }, [rootObject, mesh]);
29108
- useEffect7(() => {
29109
- if (!mesh) return;
29110
- if (positionOffset) mesh.position.fromArray(positionOffset);
29111
- if (rotationOffset) mesh.rotation.fromArray(rotationOffset);
29112
- if (scale2 !== void 0) mesh.scale.setScalar(scale2);
29113
- }, [
29114
- mesh,
29115
- positionOffset?.[0],
29116
- positionOffset?.[1],
29117
- positionOffset?.[2],
29118
- rotationOffset?.[0],
29119
- rotationOffset?.[1],
29120
- rotationOffset?.[2],
29121
- scale2
29122
- ]);
29123
- useMemo6(() => {
29263
+ const { boardTransformGroup } = useCadModelTransformGraph({
29264
+ model: mesh,
29265
+ position: positionOffset,
29266
+ rotation: rotationOffset,
29267
+ modelOffset,
29268
+ modelRotation,
29269
+ sourceCoordinateTransform,
29270
+ modelSize,
29271
+ modelFitMode,
29272
+ scale: scale2
29273
+ });
29274
+ useEffect8(() => {
29124
29275
  if (!material) return;
29125
29276
  if (isHovered) {
29126
- const color = new THREE6.Color(material.color.getHex());
29277
+ const color = new THREE8.Color(material.color.getHex());
29127
29278
  material.emissive.copy(color);
29128
29279
  material.emissive.setRGB(0, 0, 1);
29129
29280
  material.emissiveIntensity = 0.2;
@@ -29138,13 +29289,13 @@ var JscadModel = ({
29138
29289
  isHovered,
29139
29290
  onHover,
29140
29291
  onUnhover,
29141
- object: mesh
29292
+ object: boardTransformGroup
29142
29293
  }
29143
29294
  );
29144
29295
  };
29145
29296
 
29146
29297
  // src/hooks/use-global-obj-loader.ts
29147
- import { useState as useState5, useEffect as useEffect8 } from "react";
29298
+ import { useState as useState5, useEffect as useEffect9 } from "react";
29148
29299
  import { MTLLoader, OBJLoader } from "three-stdlib";
29149
29300
 
29150
29301
  // src/utils/vrml.ts
@@ -29172,7 +29323,7 @@ if (typeof window !== "undefined" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {
29172
29323
  }
29173
29324
  function useGlobalObjLoader(url) {
29174
29325
  const [obj, setObj] = useState5(null);
29175
- useEffect8(() => {
29326
+ useEffect9(() => {
29176
29327
  if (!url) return;
29177
29328
  const cleanUrl = url.replace(/&cachebust_origin=$/, "");
29178
29329
  const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE;
@@ -29248,13 +29399,18 @@ function useGlobalObjLoader(url) {
29248
29399
  }
29249
29400
 
29250
29401
  // src/three-components/MixedStlModel.tsx
29251
- import { useEffect as useEffect9, useMemo as useMemo7 } from "react";
29252
- import * as THREE7 from "three";
29402
+ import { useMemo as useMemo7 } from "react";
29403
+ import * as THREE9 from "three";
29253
29404
  import { jsx as jsx8 } from "react/jsx-runtime";
29254
29405
  function MixedStlModel({
29255
29406
  url,
29256
29407
  position,
29257
29408
  rotation,
29409
+ modelOffset = [0, 0, 0],
29410
+ modelRotation = [0, 0, 0],
29411
+ sourceCoordinateTransform,
29412
+ modelSize,
29413
+ modelFitMode = "contain_within_bounds",
29258
29414
  onHover,
29259
29415
  onUnhover,
29260
29416
  isHovered,
@@ -29262,11 +29418,10 @@ function MixedStlModel({
29262
29418
  isTranslucent = false
29263
29419
  }) {
29264
29420
  const obj = useGlobalObjLoader(url);
29265
- const { rootObject } = useThree();
29266
29421
  const model = useMemo7(() => {
29267
29422
  if (obj && !(obj instanceof Error)) {
29268
29423
  obj.traverse((child) => {
29269
- if (child instanceof THREE7.Mesh && child.material) {
29424
+ if (child instanceof THREE9.Mesh && child.material) {
29270
29425
  const setMaterialTransparency = (mat) => {
29271
29426
  mat.transparent = isTranslucent;
29272
29427
  mat.opacity = isTranslucent ? 0.5 : 1;
@@ -29283,51 +29438,26 @@ function MixedStlModel({
29283
29438
  });
29284
29439
  return obj;
29285
29440
  }
29286
- return new THREE7.Mesh(
29287
- new THREE7.BoxGeometry(0.5, 0.5, 0.5),
29288
- new THREE7.MeshStandardMaterial({
29441
+ return new THREE9.Mesh(
29442
+ new THREE9.BoxGeometry(0.5, 0.5, 0.5),
29443
+ new THREE9.MeshStandardMaterial({
29289
29444
  transparent: true,
29290
29445
  color: "red",
29291
29446
  opacity: 0.25
29292
29447
  })
29293
29448
  );
29294
29449
  }, [obj, isTranslucent]);
29295
- useEffect9(() => {
29296
- if (!rootObject || !model) return;
29297
- rootObject.add(model);
29298
- return () => {
29299
- rootObject.remove(model);
29300
- };
29301
- }, [rootObject, model]);
29302
- useEffect9(() => {
29303
- if (!model) return;
29304
- if (position) {
29305
- if (Array.isArray(position)) {
29306
- model.position.fromArray(position);
29307
- } else {
29308
- model.position.copy(position);
29309
- }
29310
- }
29311
- if (rotation) {
29312
- if (Array.isArray(rotation)) {
29313
- model.rotation.fromArray(rotation);
29314
- } else {
29315
- model.rotation.copy(rotation);
29316
- }
29317
- }
29318
- if (scale2 !== void 0) {
29319
- model.scale.setScalar(scale2);
29320
- }
29321
- }, [
29450
+ const { boardTransformGroup } = useCadModelTransformGraph({
29322
29451
  model,
29323
- Array.isArray(position) ? position[0] : position?.x,
29324
- Array.isArray(position) ? position[1] : position?.y,
29325
- Array.isArray(position) ? position[2] : position?.z,
29326
- Array.isArray(rotation) ? rotation[0] : rotation?.x,
29327
- Array.isArray(rotation) ? rotation[1] : rotation?.y,
29328
- Array.isArray(rotation) ? rotation[2] : rotation?.z,
29329
- scale2
29330
- ]);
29452
+ position: Array.isArray(position) ? position : position ? [position.x, position.y, position.z] : void 0,
29453
+ rotation: Array.isArray(rotation) ? rotation : rotation ? [rotation.x, rotation.y, rotation.z] : void 0,
29454
+ modelOffset,
29455
+ modelRotation,
29456
+ sourceCoordinateTransform,
29457
+ modelSize,
29458
+ modelFitMode,
29459
+ scale: scale2
29460
+ });
29331
29461
  if (obj instanceof Error) {
29332
29462
  throw obj;
29333
29463
  }
@@ -29337,7 +29467,7 @@ function MixedStlModel({
29337
29467
  isHovered,
29338
29468
  onHover,
29339
29469
  onUnhover,
29340
- object: model
29470
+ object: boardTransformGroup
29341
29471
  }
29342
29472
  );
29343
29473
  }
@@ -29348,8 +29478,8 @@ import {
29348
29478
  BufferGeometry as BufferGeometry2,
29349
29479
  Color as Color3,
29350
29480
  Float32BufferAttribute,
29351
- Group as Group2,
29352
- Mesh as Mesh5,
29481
+ Group as Group3,
29482
+ Mesh as Mesh6,
29353
29483
  MeshStandardMaterial as MeshStandardMaterial5
29354
29484
  } from "three";
29355
29485
  import { GLTFExporter } from "three-stdlib";
@@ -29379,7 +29509,7 @@ async function loadOcctImport() {
29379
29509
  return occtImportPromise;
29380
29510
  }
29381
29511
  function occtMeshesToGroup(meshes) {
29382
- const group = new Group2();
29512
+ const group = new Group3();
29383
29513
  for (const mesh of meshes) {
29384
29514
  const positions = mesh.attributes.position?.array ?? [];
29385
29515
  const indices = mesh.index?.array ?? [];
@@ -29398,7 +29528,7 @@ function occtMeshesToGroup(meshes) {
29398
29528
  const material = new MeshStandardMaterial5({
29399
29529
  color: mesh.color ? new Color3(mesh.color[0], mesh.color[1], mesh.color[2]) : new Color3(0.82, 0.82, 0.82)
29400
29530
  });
29401
- const threeMesh = new Mesh5(geometry, material);
29531
+ const threeMesh = new Mesh6(geometry, material);
29402
29532
  threeMesh.name = mesh.name;
29403
29533
  group.add(threeMesh);
29404
29534
  }
@@ -29488,6 +29618,11 @@ var StepModel = ({
29488
29618
  stepUrl,
29489
29619
  position,
29490
29620
  rotation,
29621
+ modelOffset,
29622
+ modelRotation,
29623
+ sourceCoordinateTransform,
29624
+ modelSize,
29625
+ modelFitMode,
29491
29626
  scale: scale2,
29492
29627
  onHover,
29493
29628
  onUnhover,
@@ -29580,6 +29715,11 @@ var StepModel = ({
29580
29715
  gltfUrl: stepGltfUrl,
29581
29716
  position,
29582
29717
  rotation,
29718
+ modelOffset,
29719
+ modelRotation,
29720
+ sourceCoordinateTransform,
29721
+ modelSize,
29722
+ modelFitMode,
29583
29723
  scale: scale2,
29584
29724
  onHover,
29585
29725
  onUnhover,
@@ -29589,6 +29729,287 @@ var StepModel = ({
29589
29729
  );
29590
29730
  };
29591
29731
 
29732
+ // src/utils/cad-model-loader-transform.ts
29733
+ import * as THREE10 from "three";
29734
+ function applyCoordinateTransform(point, config) {
29735
+ let { x, y, z: z21 } = point;
29736
+ if (config.axisMapping) {
29737
+ const original = { x, y, z: z21 };
29738
+ if (config.axisMapping.x) {
29739
+ x = getAxisValue(original, config.axisMapping.x);
29740
+ }
29741
+ if (config.axisMapping.y) {
29742
+ y = getAxisValue(original, config.axisMapping.y);
29743
+ }
29744
+ if (config.axisMapping.z) {
29745
+ z21 = getAxisValue(original, config.axisMapping.z);
29746
+ }
29747
+ }
29748
+ x *= config.flipX ?? 1;
29749
+ y *= config.flipY ?? 1;
29750
+ z21 *= config.flipZ ?? 1;
29751
+ if (config.rotation) {
29752
+ if (config.rotation.x) {
29753
+ const rad = config.rotation.x * Math.PI / 180;
29754
+ const cos = Math.cos(rad);
29755
+ const sin = Math.sin(rad);
29756
+ const newY = y * cos - z21 * sin;
29757
+ const newZ = y * sin + z21 * cos;
29758
+ y = newY;
29759
+ z21 = newZ;
29760
+ }
29761
+ if (config.rotation.y) {
29762
+ const rad = config.rotation.y * Math.PI / 180;
29763
+ const cos = Math.cos(rad);
29764
+ const sin = Math.sin(rad);
29765
+ const newX = x * cos + z21 * sin;
29766
+ const newZ = -x * sin + z21 * cos;
29767
+ x = newX;
29768
+ z21 = newZ;
29769
+ }
29770
+ if (config.rotation.z) {
29771
+ const rad = config.rotation.z * Math.PI / 180;
29772
+ const cos = Math.cos(rad);
29773
+ const sin = Math.sin(rad);
29774
+ const newX = x * cos - y * sin;
29775
+ const newY = x * sin + y * cos;
29776
+ x = newX;
29777
+ y = newY;
29778
+ }
29779
+ }
29780
+ return { x, y, z: z21 };
29781
+ }
29782
+ function getAxisValue(original, mapping) {
29783
+ switch (mapping) {
29784
+ case "x":
29785
+ return original.x;
29786
+ case "y":
29787
+ return original.y;
29788
+ case "z":
29789
+ return original.z;
29790
+ case "-x":
29791
+ return -original.x;
29792
+ case "-y":
29793
+ return -original.y;
29794
+ case "-z":
29795
+ return -original.z;
29796
+ default:
29797
+ return 0;
29798
+ }
29799
+ }
29800
+ var COORDINATE_TRANSFORMS = {
29801
+ Z_UP_TO_Y_UP: {
29802
+ axisMapping: { x: "x", y: "-z", z: "y" }
29803
+ },
29804
+ Z_OUT_OF_TOP: {
29805
+ axisMapping: { x: "x", y: "z", z: "-y" }
29806
+ },
29807
+ STEP_INVERTED: {
29808
+ axisMapping: { x: "-x", y: "z", z: "-y" }
29809
+ },
29810
+ USB_PORT_FIX: {
29811
+ flipY: -1
29812
+ },
29813
+ Z_UP_TO_Y_UP_USB_FIX: {
29814
+ axisMapping: { x: "x", y: "-z", z: "y" },
29815
+ flipZ: -1
29816
+ },
29817
+ FOOTPRINTER_MODEL_TRANSFORM: {
29818
+ axisMapping: { x: "x", y: "-z", z: "y" },
29819
+ flipX: -1,
29820
+ rotation: { x: 180, y: 180 }
29821
+ },
29822
+ IDENTITY: {},
29823
+ TEST_ROTATE_X_90: {
29824
+ axisMapping: { x: "x", y: "-z", z: "y" },
29825
+ rotation: { x: 90 }
29826
+ },
29827
+ TEST_ROTATE_X_270: {
29828
+ axisMapping: { x: "x", y: "-z", z: "y" },
29829
+ rotation: { x: 270 }
29830
+ },
29831
+ TEST_ROTATE_Y_90: {
29832
+ axisMapping: { x: "x", y: "-z", z: "y" },
29833
+ rotation: { y: 90 }
29834
+ },
29835
+ TEST_ROTATE_Y_270: {
29836
+ axisMapping: { x: "x", y: "-z", z: "y" },
29837
+ rotation: { y: 270 }
29838
+ },
29839
+ TEST_ROTATE_Z_90: {
29840
+ axisMapping: { x: "x", y: "-z", z: "y" },
29841
+ rotation: { z: 90 }
29842
+ },
29843
+ TEST_ROTATE_Z_270: {
29844
+ axisMapping: { x: "x", y: "-z", z: "y" },
29845
+ rotation: { z: 270 }
29846
+ },
29847
+ TEST_FLIP_X: {
29848
+ axisMapping: { x: "x", y: "-z", z: "y" },
29849
+ flipX: -1
29850
+ },
29851
+ TEST_FLIP_Z: {
29852
+ axisMapping: { x: "x", y: "-z", z: "y" },
29853
+ flipZ: -1
29854
+ },
29855
+ OBJ_Z_UP_TO_Y_UP: {
29856
+ axisMapping: { x: "x", y: "z", z: "y" }
29857
+ }
29858
+ };
29859
+ function getDefaultModelTransform(cad, options) {
29860
+ if (options.coordinateTransform) {
29861
+ return options.coordinateTransform;
29862
+ }
29863
+ if (options.usingGlbCoordinates) {
29864
+ return void 0;
29865
+ }
29866
+ if (options.hasFootprinterModel) {
29867
+ return COORDINATE_TRANSFORMS.FOOTPRINTER_MODEL_TRANSFORM;
29868
+ }
29869
+ if (options.usingObjFormat) {
29870
+ return void 0;
29871
+ }
29872
+ if (options.usingStepFormat) {
29873
+ return COORDINATE_TRANSFORMS.STEP_INVERTED;
29874
+ }
29875
+ return COORDINATE_TRANSFORMS.Z_UP_TO_Y_UP_USB_FIX;
29876
+ }
29877
+ function getCadLoaderTransformConfig(cad, modelType) {
29878
+ return getDefaultModelTransform(cad, {
29879
+ usingGlbCoordinates: modelType === "gltf" || modelType === "glb" || modelType === "jscad",
29880
+ usingObjFormat: modelType === "obj" || modelType === "wrl",
29881
+ usingStepFormat: modelType === "step",
29882
+ hasFootprinterModel: modelType === "footprinter"
29883
+ });
29884
+ }
29885
+ function getCadLoaderTransformMatrix(config) {
29886
+ if (!config) {
29887
+ return void 0;
29888
+ }
29889
+ const basisX = applyCoordinateTransform({ x: 1, y: 0, z: 0 }, config);
29890
+ const basisY = applyCoordinateTransform({ x: 0, y: 1, z: 0 }, config);
29891
+ const basisZ = applyCoordinateTransform({ x: 0, y: 0, z: 1 }, config);
29892
+ return new THREE10.Matrix4().makeBasis(
29893
+ new THREE10.Vector3(basisX.x, basisX.y, basisX.z),
29894
+ new THREE10.Vector3(basisY.x, basisY.y, basisY.z),
29895
+ new THREE10.Vector3(basisZ.x, basisZ.y, basisZ.z)
29896
+ );
29897
+ }
29898
+
29899
+ // src/utils/cad-model-transform.ts
29900
+ import * as THREE11 from "three";
29901
+ function toRadians(value) {
29902
+ return value * Math.PI / 180;
29903
+ }
29904
+ function getOrientationRotationForBoardNormal(modelBoardNormalDirection) {
29905
+ if (modelBoardNormalDirection === "z+") {
29906
+ return [0, 0, 0];
29907
+ }
29908
+ switch (modelBoardNormalDirection) {
29909
+ case "x+":
29910
+ return [0, toRadians(-90), 0];
29911
+ case "x-":
29912
+ return [0, toRadians(90), 0];
29913
+ case "y+":
29914
+ return [toRadians(90), 0, 0];
29915
+ case "y-":
29916
+ return [toRadians(-90), 0, 0];
29917
+ case "z-":
29918
+ return [toRadians(180), 0, 0];
29919
+ default:
29920
+ return [0, 0, 0];
29921
+ }
29922
+ }
29923
+ function getAdjustedCadPosition(cadComponent, layer, pcbThickness) {
29924
+ if (!cadComponent.position) {
29925
+ return void 0;
29926
+ }
29927
+ let boardRelativeZ = cadComponent.position.z;
29928
+ if (layer === "bottom" && cadComponent.position.z >= 0) {
29929
+ boardRelativeZ = -(cadComponent.position.z + pcbThickness);
29930
+ }
29931
+ return [cadComponent.position.x, cadComponent.position.y, boardRelativeZ];
29932
+ }
29933
+ function getBaseCadRotation(cadComponent, layer) {
29934
+ if (!cadComponent.rotation) {
29935
+ return layer === "bottom" ? [Math.PI, 0, 0] : [0, 0, 0];
29936
+ }
29937
+ return [
29938
+ toRadians(cadComponent.rotation.x),
29939
+ toRadians(cadComponent.rotation.y),
29940
+ toRadians(cadComponent.rotation.z)
29941
+ ];
29942
+ }
29943
+ function rotateOriginPosition(origin, boardNormalRotation) {
29944
+ const vector = new THREE11.Vector3(origin.x, origin.y, origin.z);
29945
+ const euler = new THREE11.Euler(
29946
+ boardNormalRotation[0],
29947
+ boardNormalRotation[1],
29948
+ boardNormalRotation[2],
29949
+ "XYZ"
29950
+ );
29951
+ vector.applyEuler(euler);
29952
+ return [vector.x, vector.y, vector.z];
29953
+ }
29954
+ function getModelOriginOffset(cadComponent, loaderTransform, modelRotation) {
29955
+ if (!cadComponent.model_origin_position) {
29956
+ return [0, 0, 0];
29957
+ }
29958
+ const originInLoaderSpace = loaderTransform ? applyCoordinateTransform(
29959
+ cadComponent.model_origin_position,
29960
+ loaderTransform
29961
+ ) : cadComponent.model_origin_position;
29962
+ return rotateOriginPosition(originInLoaderSpace, modelRotation);
29963
+ }
29964
+ function getCadModelTransform(cadComponent, options) {
29965
+ const position = getAdjustedCadPosition(
29966
+ cadComponent,
29967
+ options.layer,
29968
+ options.pcbThickness
29969
+ );
29970
+ const rotation = getBaseCadRotation(cadComponent, options.layer);
29971
+ const loaderTransform = getCadLoaderTransformConfig(
29972
+ cadComponent,
29973
+ options.modelType
29974
+ );
29975
+ const modelRotation = getOrientationRotationForBoardNormal(
29976
+ cadComponent.model_board_normal_direction ?? "z+"
29977
+ );
29978
+ const rotatedOrigin = getModelOriginOffset(
29979
+ cadComponent,
29980
+ loaderTransform,
29981
+ modelRotation
29982
+ );
29983
+ return {
29984
+ position,
29985
+ rotation,
29986
+ modelPosition: [-rotatedOrigin[0], -rotatedOrigin[1], -rotatedOrigin[2]],
29987
+ modelRotation,
29988
+ scale: cadComponent.model_unit_to_mm_scale_factor ?? void 0,
29989
+ fitMode: cadComponent.model_object_fit ?? "contain_within_bounds",
29990
+ size: cadComponent.size ? [cadComponent.size.x, cadComponent.size.y, cadComponent.size.z] : void 0
29991
+ };
29992
+ }
29993
+
29994
+ // src/utils/get-cad-model-type.ts
29995
+ var getCadModelType = (cadComponent) => {
29996
+ if (cadComponent.model_glb_url || cadComponent.model_gltf_url) {
29997
+ return cadComponent.model_glb_url ? "glb" : "gltf";
29998
+ }
29999
+ if (cadComponent.model_step_url) return "step";
30000
+ if (cadComponent.model_obj_url || cadComponent.model_wrl_url || cadComponent.model_stl_url) {
30001
+ if (cadComponent.model_wrl_url) return "wrl";
30002
+ if (cadComponent.model_stl_url) return "stl";
30003
+ return "obj";
30004
+ }
30005
+ if (cadComponent.model_jscad) return "jscad";
30006
+ if (cadComponent.footprinter_string) return "footprinter";
30007
+ return "unknown";
30008
+ };
30009
+ var getRenderedCadModelType = (modelType) => {
30010
+ return modelType === "step" ? "glb" : modelType;
30011
+ };
30012
+
29592
30013
  // src/utils/resolve-model-url.ts
29593
30014
  var resolveModelUrl = (modelUrl, resolveStaticAsset) => {
29594
30015
  if (!modelUrl) return void 0;
@@ -29665,7 +30086,7 @@ var AnyCadComponent = ({
29665
30086
  [resolveStaticAsset]
29666
30087
  );
29667
30088
  const url = resolveModelUrlWithStaticResolver(
29668
- cad_component.model_obj_url ?? cad_component.model_wrl_url ?? cad_component.model_stl_url
30089
+ cad_component.model_wrl_url ?? cad_component.model_stl_url ?? cad_component.model_obj_url
29669
30090
  );
29670
30091
  const gltfUrl = resolveModelUrlWithStaticResolver(
29671
30092
  cad_component.model_glb_url ?? cad_component.model_gltf_url
@@ -29683,81 +30104,94 @@ var AnyCadComponent = ({
29683
30104
  (elm) => elm.type === "pcb_component" && elm.source_component_id === cad_component.source_component_id
29684
30105
  );
29685
30106
  const layer = pcbComponent?.layer ?? "top";
29686
- const rotationOffset = useMemo8(() => {
29687
- const baseRotation = cad_component.rotation ? tuple(
29688
- cad_component.rotation.x * Math.PI / 180,
29689
- cad_component.rotation.y * Math.PI / 180,
29690
- cad_component.rotation.z * Math.PI / 180
29691
- ) : tuple(0, 0, 0);
29692
- if (layer === "bottom") {
29693
- }
29694
- return baseRotation;
29695
- }, [cad_component.rotation, layer]);
29696
- const adjustedPosition = useMemo8(() => {
29697
- if (!cad_component.position) return void 0;
29698
- let z21;
29699
- if (layer === "top") {
29700
- z21 = cad_component.position.z;
29701
- } else if (layer === "bottom") {
29702
- z21 = -(cad_component.position.z + pcbThickness);
29703
- } else {
29704
- z21 = cad_component.position.z;
29705
- }
29706
- return [cad_component.position.x, cad_component.position.y, z21];
29707
- }, [cad_component.position, layer, pcbThickness]);
30107
+ const sourceModelType = getCadModelType(cad_component);
30108
+ const renderedModelType = getRenderedCadModelType(sourceModelType);
30109
+ const gltfModelType = cad_component.model_glb_url ? "glb" : "gltf";
30110
+ const meshModelType = cad_component.model_wrl_url ? "wrl" : cad_component.model_stl_url ? "stl" : "obj";
30111
+ const modelTransform = useMemo8(
30112
+ () => getCadModelTransform(cad_component, {
30113
+ layer,
30114
+ pcbThickness,
30115
+ modelType: renderedModelType
30116
+ }),
30117
+ [cad_component, layer, pcbThickness, renderedModelType]
30118
+ );
30119
+ const rotationOffset = tuple(...modelTransform.rotation);
30120
+ const adjustedPosition = modelTransform.position;
29708
30121
  const fallbackModelComponents = useMemo8(() => {
29709
30122
  const components = [];
29710
- if (url) {
30123
+ if (gltfUrl) {
29711
30124
  components.push(
29712
30125
  /* @__PURE__ */ jsx10(
29713
- MixedStlModel,
30126
+ GltfModel,
29714
30127
  {
29715
- url,
30128
+ gltfUrl,
29716
30129
  position: adjustedPosition,
29717
30130
  rotation: rotationOffset,
29718
- scale: cad_component.model_unit_to_mm_scale_factor,
30131
+ modelOffset: modelTransform.modelPosition,
30132
+ modelRotation: modelTransform.modelRotation,
30133
+ sourceCoordinateTransform: getCadLoaderTransformMatrix(
30134
+ getCadLoaderTransformConfig(cad_component, gltfModelType)
30135
+ ),
30136
+ scale: modelTransform.scale,
30137
+ modelSize: modelTransform.size,
30138
+ modelFitMode: modelTransform.fitMode,
29719
30139
  onHover: handleHover,
29720
30140
  onUnhover: handleUnhover,
29721
30141
  isHovered,
29722
30142
  isTranslucent: cad_component.show_as_translucent_model
29723
30143
  },
29724
- `${cad_component.cad_component_id}-mixed-${url}`
30144
+ `${cad_component.cad_component_id}-gltf-${gltfUrl}`
29725
30145
  )
29726
30146
  );
29727
30147
  }
29728
- if (gltfUrl) {
30148
+ if (stepUrl && !cad_component.model_jscad && !cad_component.footprinter_string) {
29729
30149
  components.push(
29730
30150
  /* @__PURE__ */ jsx10(
29731
- GltfModel,
30151
+ StepModel,
29732
30152
  {
29733
- gltfUrl,
30153
+ stepUrl,
29734
30154
  position: adjustedPosition,
29735
30155
  rotation: rotationOffset,
29736
- scale: cad_component.model_unit_to_mm_scale_factor,
30156
+ modelOffset: modelTransform.modelPosition,
30157
+ modelRotation: modelTransform.modelRotation,
30158
+ sourceCoordinateTransform: getCadLoaderTransformMatrix(
30159
+ getCadLoaderTransformConfig(cad_component, renderedModelType)
30160
+ ),
30161
+ scale: modelTransform.scale,
30162
+ modelSize: modelTransform.size,
30163
+ modelFitMode: modelTransform.fitMode,
29737
30164
  onHover: handleHover,
29738
30165
  onUnhover: handleUnhover,
29739
30166
  isHovered,
29740
30167
  isTranslucent: cad_component.show_as_translucent_model
29741
30168
  },
29742
- `${cad_component.cad_component_id}-gltf-${gltfUrl}`
30169
+ `${cad_component.cad_component_id}-step-${stepUrl}`
29743
30170
  )
29744
30171
  );
29745
30172
  }
29746
- if (stepUrl && !cad_component.model_jscad && !cad_component.footprinter_string) {
30173
+ if (url) {
29747
30174
  components.push(
29748
30175
  /* @__PURE__ */ jsx10(
29749
- StepModel,
30176
+ MixedStlModel,
29750
30177
  {
29751
- stepUrl,
30178
+ url,
29752
30179
  position: adjustedPosition,
29753
30180
  rotation: rotationOffset,
29754
- scale: cad_component.model_unit_to_mm_scale_factor,
30181
+ modelOffset: modelTransform.modelPosition,
30182
+ modelRotation: modelTransform.modelRotation,
30183
+ sourceCoordinateTransform: getCadLoaderTransformMatrix(
30184
+ getCadLoaderTransformConfig(cad_component, meshModelType)
30185
+ ),
30186
+ scale: modelTransform.scale,
30187
+ modelSize: modelTransform.size,
30188
+ modelFitMode: modelTransform.fitMode,
29755
30189
  onHover: handleHover,
29756
30190
  onUnhover: handleUnhover,
29757
30191
  isHovered,
29758
30192
  isTranslucent: cad_component.show_as_translucent_model
29759
30193
  },
29760
- `${cad_component.cad_component_id}-step-${stepUrl}`
30194
+ `${cad_component.cad_component_id}-mixed-${url}`
29761
30195
  )
29762
30196
  );
29763
30197
  }
@@ -29767,12 +30201,19 @@ var AnyCadComponent = ({
29767
30201
  cad_component.cad_component_id,
29768
30202
  cad_component.footprinter_string,
29769
30203
  cad_component.model_jscad,
29770
- cad_component.model_unit_to_mm_scale_factor,
29771
30204
  cad_component.show_as_translucent_model,
29772
30205
  gltfUrl,
30206
+ gltfModelType,
29773
30207
  handleHover,
29774
30208
  handleUnhover,
29775
30209
  isHovered,
30210
+ meshModelType,
30211
+ modelTransform.modelPosition,
30212
+ modelTransform.modelRotation,
30213
+ modelTransform.scale,
30214
+ modelTransform.fitMode,
30215
+ modelTransform.size,
30216
+ renderedModelType,
29776
30217
  rotationOffset,
29777
30218
  stepUrl,
29778
30219
  url
@@ -29811,7 +30252,14 @@ var AnyCadComponent = ({
29811
30252
  jscadPlan: cad_component.model_jscad,
29812
30253
  positionOffset: adjustedPosition,
29813
30254
  rotationOffset,
29814
- scale: cad_component.model_unit_to_mm_scale_factor,
30255
+ modelOffset: modelTransform.modelPosition,
30256
+ modelRotation: modelTransform.modelRotation,
30257
+ sourceCoordinateTransform: getCadLoaderTransformMatrix(
30258
+ getCadLoaderTransformConfig(cad_component, "jscad")
30259
+ ),
30260
+ scale: modelTransform.scale,
30261
+ modelSize: modelTransform.size,
30262
+ modelFitMode: modelTransform.fitMode,
29815
30263
  onHover: handleHover,
29816
30264
  onUnhover: handleUnhover,
29817
30265
  isHovered,
@@ -29826,7 +30274,7 @@ var AnyCadComponent = ({
29826
30274
  positionOffset: adjustedPosition,
29827
30275
  rotationOffset,
29828
30276
  footprint: cad_component.footprinter_string,
29829
- scale: cad_component.model_unit_to_mm_scale_factor,
30277
+ scale: modelTransform.scale,
29830
30278
  onHover: handleHover,
29831
30279
  onUnhover: handleUnhover,
29832
30280
  isHovered,
@@ -29872,12 +30320,12 @@ var AnyCadComponent = ({
29872
30320
 
29873
30321
  // src/CadViewerContainer.tsx
29874
30322
  import { forwardRef as forwardRef2, useEffect as useEffect18, useMemo as useMemo14, useState as useState10 } from "react";
29875
- import * as THREE16 from "three";
30323
+ import * as THREE20 from "three";
29876
30324
 
29877
30325
  // package.json
29878
30326
  var package_default = {
29879
30327
  name: "@tscircuit/3d-viewer",
29880
- version: "0.0.543",
30328
+ version: "0.0.544",
29881
30329
  main: "./dist/index.js",
29882
30330
  module: "./dist/index.js",
29883
30331
  type: "module",
@@ -29906,7 +30354,7 @@ var package_default = {
29906
30354
  dependencies: {
29907
30355
  "@jscad/regl-renderer": "^2.6.12",
29908
30356
  "@jscad/stl-serializer": "^2.1.20",
29909
- "circuit-json": "^0.0.391",
30357
+ "circuit-json": "^0.0.405",
29910
30358
  "circuit-to-canvas": "^0.0.92",
29911
30359
  "react-hot-toast": "^2.6.0",
29912
30360
  three: "^0.165.0",
@@ -29945,7 +30393,7 @@ var package_default = {
29945
30393
  "react-use-gesture": "^9.1.3",
29946
30394
  semver: "^7.7.0",
29947
30395
  "strip-ansi": "^7.1.0",
29948
- tscircuit: "^0.0.1532",
30396
+ tscircuit: "^0.0.1541",
29949
30397
  tsup: "^8.3.6",
29950
30398
  typescript: "^5.7.3",
29951
30399
  vite: "^7.1.5",
@@ -29963,7 +30411,7 @@ import {
29963
30411
  useImperativeHandle,
29964
30412
  useMemo as useMemo10
29965
30413
  } from "react";
29966
- import * as THREE10 from "three";
30414
+ import * as THREE14 from "three";
29967
30415
 
29968
30416
  // src/react-three/remove-existing-canvases.ts
29969
30417
  function removeExistingCanvases(container) {
@@ -29971,10 +30419,10 @@ function removeExistingCanvases(container) {
29971
30419
  }
29972
30420
 
29973
30421
  // src/react-three/configure-renderer.ts
29974
- import * as THREE8 from "three";
30422
+ import * as THREE12 from "three";
29975
30423
  var configureRenderer = (renderer) => {
29976
- renderer.outputColorSpace = THREE8.SRGBColorSpace;
29977
- renderer.toneMapping = THREE8.ACESFilmicToneMapping;
30424
+ renderer.outputColorSpace = THREE12.SRGBColorSpace;
30425
+ renderer.toneMapping = THREE12.ACESFilmicToneMapping;
29978
30426
  renderer.toneMappingExposure = 1;
29979
30427
  };
29980
30428
 
@@ -29987,7 +30435,7 @@ import {
29987
30435
  useRef as useRef3,
29988
30436
  useState as useState8
29989
30437
  } from "react";
29990
- import * as THREE9 from "three";
30438
+ import * as THREE13 from "three";
29991
30439
  import { jsx as jsx11 } from "react/jsx-runtime";
29992
30440
  var CAMERA_KEY = "cadViewerCameraStateSession";
29993
30441
  var saveCameraToSession = (camera, controls) => {
@@ -30036,7 +30484,7 @@ var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition
30036
30484
  );
30037
30485
  const [cameraPosition, setCameraPosition] = useState8(initialCameraPosition ?? null);
30038
30486
  const [cameraRotation, setCameraRotation] = useState8(
30039
- new THREE9.Euler(0, 0, 0)
30487
+ new THREE13.Euler(0, 0, 0)
30040
30488
  );
30041
30489
  const baseDistance = useMemo9(() => {
30042
30490
  const [x, y, z21] = initialCameraPosition ?? [5, -5, 5];
@@ -30217,16 +30665,16 @@ var Canvas = forwardRef(
30217
30665
  },
30218
30666
  []
30219
30667
  );
30220
- const scene = useMemo10(() => new THREE10.Scene(), []);
30668
+ const scene = useMemo10(() => new THREE14.Scene(), []);
30221
30669
  if (sceneProps?.up) {
30222
30670
  scene.up.set(sceneProps.up.x, sceneProps.up.y, sceneProps.up.z);
30223
30671
  }
30224
- const rootObject = useRef4(new THREE10.Object3D());
30672
+ const rootObject = useRef4(new THREE14.Object3D());
30225
30673
  useImperativeHandle(ref, () => rootObject.current);
30226
30674
  useEffect12(() => {
30227
30675
  if (!mountRef.current) return;
30228
30676
  removeExistingCanvases(mountRef.current);
30229
- const renderer = new THREE10.WebGLRenderer({ antialias: true, alpha: true });
30677
+ const renderer = new THREE14.WebGLRenderer({ antialias: true, alpha: true });
30230
30678
  configureRenderer(renderer);
30231
30679
  renderer.setSize(
30232
30680
  mountRef.current.clientWidth,
@@ -30235,7 +30683,7 @@ var Canvas = forwardRef(
30235
30683
  renderer.setPixelRatio(window.devicePixelRatio);
30236
30684
  mountRef.current.appendChild(renderer.domElement);
30237
30685
  const aspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
30238
- const camera = cameraType === "perspective" ? new THREE10.PerspectiveCamera(75, aspect, 0.1, 1e3) : new THREE10.OrthographicCamera(
30686
+ const camera = cameraType === "perspective" ? new THREE14.PerspectiveCamera(75, aspect, 0.1, 1e3) : new THREE14.OrthographicCamera(
30239
30687
  -10 * aspect,
30240
30688
  10 * aspect,
30241
30689
  10,
@@ -30272,7 +30720,7 @@ var Canvas = forwardRef(
30272
30720
  });
30273
30721
  onCreatedRef.current?.({ camera, renderer });
30274
30722
  let animationFrameId;
30275
- const clock = new THREE10.Clock();
30723
+ const clock = new THREE14.Clock();
30276
30724
  const animate = () => {
30277
30725
  const time = clock.getElapsedTime();
30278
30726
  const delta = clock.getDelta();
@@ -30284,9 +30732,9 @@ var Canvas = forwardRef(
30284
30732
  const handleResize = () => {
30285
30733
  if (mountRef.current) {
30286
30734
  const newAspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
30287
- if (camera instanceof THREE10.PerspectiveCamera) {
30735
+ if (camera instanceof THREE14.PerspectiveCamera) {
30288
30736
  camera.aspect = newAspect;
30289
- } else if (camera instanceof THREE10.OrthographicCamera) {
30737
+ } else if (camera instanceof THREE14.OrthographicCamera) {
30290
30738
  camera.left = -10 * newAspect;
30291
30739
  camera.right = 10 * newAspect;
30292
30740
  camera.top = 10;
@@ -30324,7 +30772,7 @@ var Canvas = forwardRef(
30324
30772
 
30325
30773
  // src/react-three/OrbitControls.tsx
30326
30774
  import { useEffect as useEffect13, useMemo as useMemo11 } from "react";
30327
- import * as THREE11 from "three";
30775
+ import * as THREE15 from "three";
30328
30776
  import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
30329
30777
  var OrbitControls = ({
30330
30778
  autoRotate,
@@ -30368,9 +30816,9 @@ var OrbitControls = ({
30368
30816
  if (dampingFactor !== void 0) controls.dampingFactor = dampingFactor;
30369
30817
  controls.zoomToCursor = true;
30370
30818
  controls.mouseButtons = {
30371
- LEFT: THREE11.MOUSE.ROTATE,
30819
+ LEFT: THREE15.MOUSE.ROTATE,
30372
30820
  // Left click to rotate
30373
- MIDDLE: THREE11.MOUSE.PAN,
30821
+ MIDDLE: THREE15.MOUSE.PAN,
30374
30822
  // Middle click to pan
30375
30823
  RIGHT: null
30376
30824
  // Right-click always disabled - only context menu
@@ -30411,7 +30859,7 @@ var OrbitControls = ({
30411
30859
 
30412
30860
  // src/react-three/Grid.tsx
30413
30861
  import { useEffect as useEffect14, useMemo as useMemo12 } from "react";
30414
- import * as THREE12 from "three";
30862
+ import * as THREE16 from "three";
30415
30863
  var vertexShader = `
30416
30864
  varying vec3 worldPosition;
30417
30865
  void main() {
@@ -30457,24 +30905,24 @@ var Grid = ({
30457
30905
  const { scene, camera } = useThree();
30458
30906
  const size4 = 1e3;
30459
30907
  const gridMesh = useMemo12(() => {
30460
- const geometry = new THREE12.PlaneGeometry(size4, size4);
30908
+ const geometry = new THREE16.PlaneGeometry(size4, size4);
30461
30909
  geometry.rotateX(-Math.PI / 2);
30462
- const material = new THREE12.ShaderMaterial({
30910
+ const material = new THREE16.ShaderMaterial({
30463
30911
  vertexShader,
30464
30912
  fragmentShader,
30465
30913
  uniforms: {
30466
30914
  cellSize: { value: cellSize },
30467
30915
  sectionSize: { value: sectionSize },
30468
- gridColor: { value: new THREE12.Color(15658734) },
30469
- sectionColor: { value: new THREE12.Color(13421823) },
30916
+ gridColor: { value: new THREE16.Color(15658734) },
30917
+ sectionColor: { value: new THREE16.Color(13421823) },
30470
30918
  fadeDistance: { value: 100 },
30471
30919
  // Fade out based on sectionSize
30472
30920
  fadeStrength: { value: 1.5 }
30473
30921
  },
30474
30922
  transparent: true,
30475
- side: THREE12.DoubleSide
30923
+ side: THREE16.DoubleSide
30476
30924
  });
30477
- const mesh = new THREE12.Mesh(geometry, material);
30925
+ const mesh = new THREE16.Mesh(geometry, material);
30478
30926
  if (rotation) {
30479
30927
  mesh.rotation.fromArray(rotation);
30480
30928
  }
@@ -30503,15 +30951,15 @@ var Grid = ({
30503
30951
 
30504
30952
  // src/react-three/Lights.tsx
30505
30953
  import { useEffect as useEffect15, useMemo as useMemo13 } from "react";
30506
- import * as THREE13 from "three";
30954
+ import * as THREE17 from "three";
30507
30955
  var Lights = () => {
30508
30956
  const { scene } = useThree();
30509
30957
  const ambientLight = useMemo13(
30510
- () => new THREE13.AmbientLight(16777215, Math.PI / 2),
30958
+ () => new THREE17.AmbientLight(16777215, Math.PI / 2),
30511
30959
  []
30512
30960
  );
30513
30961
  const pointLight = useMemo13(() => {
30514
- const light = new THREE13.PointLight(16777215, Math.PI / 4);
30962
+ const light = new THREE17.PointLight(16777215, Math.PI / 4);
30515
30963
  light.position.set(-10, -10, 10);
30516
30964
  light.decay = 0;
30517
30965
  return light;
@@ -30530,7 +30978,7 @@ var Lights = () => {
30530
30978
 
30531
30979
  // src/hooks/cameraAnimation.ts
30532
30980
  import { useCallback as useCallback6, useEffect as useEffect16, useRef as useRef5 } from "react";
30533
- import * as THREE14 from "three";
30981
+ import * as THREE18 from "three";
30534
30982
  var easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
30535
30983
  var CameraAnimatorWithContext = () => {
30536
30984
  const {
@@ -30541,24 +30989,24 @@ var CameraAnimatorWithContext = () => {
30541
30989
  getPresetConfig
30542
30990
  } = useCameraController();
30543
30991
  const animationRef = useRef5(null);
30544
- const tempQuaternion = useRef5(new THREE14.Quaternion());
30545
- const tempTarget = useRef5(new THREE14.Vector3());
30546
- const tempUp = useRef5(new THREE14.Vector3());
30547
- const tempRoll = useRef5(new THREE14.Quaternion());
30548
- const tempRollTarget = useRef5(new THREE14.Quaternion());
30549
- const baseOrientationHelper = useRef5(new THREE14.Object3D());
30550
- const orientationHelper = useRef5(new THREE14.Object3D());
30992
+ const tempQuaternion = useRef5(new THREE18.Quaternion());
30993
+ const tempTarget = useRef5(new THREE18.Vector3());
30994
+ const tempUp = useRef5(new THREE18.Vector3());
30995
+ const tempRoll = useRef5(new THREE18.Quaternion());
30996
+ const tempRollTarget = useRef5(new THREE18.Quaternion());
30997
+ const baseOrientationHelper = useRef5(new THREE18.Object3D());
30998
+ const orientationHelper = useRef5(new THREE18.Object3D());
30551
30999
  const animateTo = useCallback6(
30552
31000
  ({ position, target, up, durationMs = 600 }) => {
30553
31001
  if (!mainCameraRef.current) return;
30554
31002
  const currentTarget = controlsRef.current?.target ?? defaultTarget;
30555
- const toPosition = new THREE14.Vector3(
31003
+ const toPosition = new THREE18.Vector3(
30556
31004
  position[0],
30557
31005
  position[1],
30558
31006
  position[2]
30559
31007
  );
30560
- const resolvedTarget = target ? new THREE14.Vector3(target[0], target[1], target[2]) : defaultTarget.clone();
30561
- const resolvedUp = new THREE14.Vector3(...up ?? [0, 0, 1]).normalize();
31008
+ const resolvedTarget = target ? new THREE18.Vector3(target[0], target[1], target[2]) : defaultTarget.clone();
31009
+ const resolvedUp = new THREE18.Vector3(...up ?? [0, 0, 1]).normalize();
30562
31010
  const toOrientationHelper = orientationHelper.current;
30563
31011
  toOrientationHelper.position.copy(toPosition);
30564
31012
  toOrientationHelper.up.copy(resolvedUp);
@@ -30715,14 +31163,14 @@ var useCameraSession = () => {
30715
31163
 
30716
31164
  // src/three-components/OrientationCubeCanvas.tsx
30717
31165
  import { useEffect as useEffect17, useRef as useRef7 } from "react";
30718
- import * as THREE15 from "three";
31166
+ import * as THREE19 from "three";
30719
31167
  import { Text as TroikaText } from "troika-three-text";
30720
31168
  import { jsx as jsx13 } from "react/jsx-runtime";
30721
31169
  function computePointInFront(rotationVector, distance5) {
30722
- const quaternion = new THREE15.Quaternion().setFromEuler(
30723
- new THREE15.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
31170
+ const quaternion = new THREE19.Quaternion().setFromEuler(
31171
+ new THREE19.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
30724
31172
  );
30725
- const forwardVector = new THREE15.Vector3(0, 0, 1);
31173
+ const forwardVector = new THREE19.Vector3(0, 0, 1);
30726
31174
  forwardVector.applyQuaternion(quaternion);
30727
31175
  const result = forwardVector.multiplyScalar(distance5);
30728
31176
  return result;
@@ -30740,7 +31188,7 @@ var OrientationCubeCanvas = () => {
30740
31188
  const canvas = document.createElement("canvas");
30741
31189
  canvasRef.current = canvas;
30742
31190
  containerRef.current.appendChild(canvas);
30743
- const renderer = new THREE15.WebGLRenderer({
31191
+ const renderer = new THREE19.WebGLRenderer({
30744
31192
  canvas,
30745
31193
  antialias: true,
30746
31194
  alpha: true
@@ -30748,26 +31196,26 @@ var OrientationCubeCanvas = () => {
30748
31196
  renderer.setSize(120, 120);
30749
31197
  renderer.setPixelRatio(window.devicePixelRatio);
30750
31198
  rendererRef.current = renderer;
30751
- const scene = new THREE15.Scene();
31199
+ const scene = new THREE19.Scene();
30752
31200
  sceneRef.current = scene;
30753
- const camera = new THREE15.PerspectiveCamera(75, 1, 0.1, 1e3);
31201
+ const camera = new THREE19.PerspectiveCamera(75, 1, 0.1, 1e3);
30754
31202
  camera.up.set(0, 0, 1);
30755
31203
  cameraRef.current = camera;
30756
- const ambientLight = new THREE15.AmbientLight(16777215, Math.PI / 2);
31204
+ const ambientLight = new THREE19.AmbientLight(16777215, Math.PI / 2);
30757
31205
  scene.add(ambientLight);
30758
- const group = new THREE15.Group();
31206
+ const group = new THREE19.Group();
30759
31207
  group.rotation.fromArray([Math.PI / 2, 0, 0]);
30760
31208
  const cubeSize = 1;
30761
- const box = new THREE15.Mesh(
30762
- new THREE15.BoxGeometry(cubeSize, cubeSize, cubeSize),
30763
- new THREE15.MeshStandardMaterial({ color: "white" })
31209
+ const box = new THREE19.Mesh(
31210
+ new THREE19.BoxGeometry(cubeSize, cubeSize, cubeSize),
31211
+ new THREE19.MeshStandardMaterial({ color: "white" })
30764
31212
  );
30765
31213
  group.add(box);
30766
- const edges = new THREE15.LineSegments(
30767
- new THREE15.EdgesGeometry(
30768
- new THREE15.BoxGeometry(cubeSize, cubeSize, cubeSize)
31214
+ const edges = new THREE19.LineSegments(
31215
+ new THREE19.EdgesGeometry(
31216
+ new THREE19.BoxGeometry(cubeSize, cubeSize, cubeSize)
30769
31217
  ),
30770
- new THREE15.LineBasicMaterial({ color: 0, linewidth: 2 })
31218
+ new THREE19.LineBasicMaterial({ color: 0, linewidth: 2 })
30771
31219
  );
30772
31220
  group.add(edges);
30773
31221
  scene.add(group);
@@ -30821,7 +31269,7 @@ var OrientationCubeCanvas = () => {
30821
31269
  const animate = () => {
30822
31270
  if (mainCameraRef.current) {
30823
31271
  const cameraPosition = computePointInFront(
30824
- mainCameraRef.current.rotation ?? new THREE15.Euler(0, 0, 0),
31272
+ mainCameraRef.current.rotation ?? new THREE19.Euler(0, 0, 0),
30825
31273
  2
30826
31274
  );
30827
31275
  if (!cameraPosition.equals(camera.position)) {
@@ -30925,7 +31373,7 @@ var CadViewerContainer = forwardRef2(
30925
31373
  Canvas,
30926
31374
  {
30927
31375
  ref,
30928
- scene: { up: new THREE16.Vector3(0, 0, 1) },
31376
+ scene: { up: new THREE20.Vector3(0, 0, 1) },
30929
31377
  camera: { up: [0, 0, 1], position: initialCameraPosition },
30930
31378
  onCreated: ({ camera }) => {
30931
31379
  mainCameraRef.current = camera;
@@ -32520,7 +32968,7 @@ var Text = ({
32520
32968
  };
32521
32969
 
32522
32970
  // src/three-components/Error3d.tsx
32523
- import * as THREE17 from "three";
32971
+ import * as THREE21 from "three";
32524
32972
  import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs4 } from "react/jsx-runtime";
32525
32973
  var Error3d = ({
32526
32974
  error,
@@ -32554,7 +33002,7 @@ var Error3d = ({
32554
33002
  return [0, 0, 0];
32555
33003
  }, [cad_component]);
32556
33004
  const group = useMemo17(() => {
32557
- const g = new THREE17.Group();
33005
+ const g = new THREE21.Group();
32558
33006
  g.position.fromArray(position);
32559
33007
  return g;
32560
33008
  }, [position]);
@@ -32614,9 +33062,9 @@ var Error3d = ({
32614
33062
  };
32615
33063
  var ErrorBox = ({ parent }) => {
32616
33064
  const mesh = useMemo17(() => {
32617
- const m = new THREE17.Mesh(
32618
- new THREE17.BoxGeometry(0.5, 0.5, 0.5),
32619
- new THREE17.MeshStandardMaterial({
33065
+ const m = new THREE21.Mesh(
33066
+ new THREE21.BoxGeometry(0.5, 0.5, 0.5),
33067
+ new THREE21.MeshStandardMaterial({
32620
33068
  depthTest: false,
32621
33069
  transparent: true,
32622
33070
  color: "red",
@@ -32638,7 +33086,7 @@ var ErrorBox = ({ parent }) => {
32638
33086
 
32639
33087
  // src/three-components/STLModel.tsx
32640
33088
  import { useState as useState14, useEffect as useEffect23, useMemo as useMemo18 } from "react";
32641
- import * as THREE18 from "three";
33089
+ import * as THREE22 from "three";
32642
33090
  import { STLLoader } from "three-stdlib";
32643
33091
  function STLModel({
32644
33092
  stlUrl,
@@ -32671,15 +33119,15 @@ function STLModel({
32671
33119
  const mesh = useMemo18(() => {
32672
33120
  if (!geom) return null;
32673
33121
  const isBoardLayer = layerType === "board";
32674
- const material = new THREE18.MeshStandardMaterial({
32675
- color: Array.isArray(color) ? new THREE18.Color(color[0], color[1], color[2]) : color,
33122
+ const material = new THREE22.MeshStandardMaterial({
33123
+ color: Array.isArray(color) ? new THREE22.Color(color[0], color[1], color[2]) : color,
32676
33124
  transparent: opacity !== 1,
32677
33125
  opacity,
32678
33126
  polygonOffset: isBoardLayer,
32679
33127
  polygonOffsetFactor: isBoardLayer ? 6 : 0,
32680
33128
  polygonOffsetUnits: isBoardLayer ? 6 : 0
32681
33129
  });
32682
- const createdMesh = new THREE18.Mesh(geom, material);
33130
+ const createdMesh = new THREE22.Mesh(geom, material);
32683
33131
  createdMesh.renderOrder = isBoardLayer ? -1 : 1;
32684
33132
  return createdMesh;
32685
33133
  }, [geom, color, opacity, layerType]);
@@ -32739,7 +33187,7 @@ import { su as su8 } from "@tscircuit/circuit-json-util";
32739
33187
  import { useEffect as useEffect24, useMemo as useMemo19 } from "react";
32740
33188
 
32741
33189
  // src/textures/create-combined-board-textures.ts
32742
- import * as THREE29 from "three";
33190
+ import * as THREE33 from "three";
32743
33191
 
32744
33192
  // node_modules/@tscircuit/math-utils/dist/chunk-5N7UJNVK.js
32745
33193
  var getBoundsFromPoints = (points) => {
@@ -32794,7 +33242,7 @@ function calculateOutlineBounds(boardData) {
32794
33242
  // src/utils/pad-texture.ts
32795
33243
  import { su as su5 } from "@tscircuit/circuit-json-util";
32796
33244
  import { CircuitToCanvasDrawer } from "circuit-to-canvas";
32797
- import * as THREE19 from "three";
33245
+ import * as THREE23 from "three";
32798
33246
  function createPadTextureForLayer({
32799
33247
  layer,
32800
33248
  circuitJson,
@@ -32867,10 +33315,10 @@ function createPadTextureForLayer({
32867
33315
  drawSoldermaskTop: false,
32868
33316
  drawSoldermaskBottom: false
32869
33317
  });
32870
- const texture = new THREE19.CanvasTexture(canvas);
33318
+ const texture = new THREE23.CanvasTexture(canvas);
32871
33319
  texture.generateMipmaps = true;
32872
- texture.minFilter = THREE19.LinearMipmapLinearFilter;
32873
- texture.magFilter = THREE19.LinearFilter;
33320
+ texture.minFilter = THREE23.LinearMipmapLinearFilter;
33321
+ texture.magFilter = THREE23.LinearFilter;
32874
33322
  texture.anisotropy = 16;
32875
33323
  texture.needsUpdate = true;
32876
33324
  return texture;
@@ -32878,7 +33326,7 @@ function createPadTextureForLayer({
32878
33326
 
32879
33327
  // src/utils/panel-outline-texture.ts
32880
33328
  import { su as su6 } from "@tscircuit/circuit-json-util";
32881
- import * as THREE20 from "three";
33329
+ import * as THREE24 from "three";
32882
33330
  var resolvePanelIdForTexture = (circuitJson) => {
32883
33331
  const panels = circuitJson.filter(
32884
33332
  (e) => e.type === "pcb_panel"
@@ -32946,17 +33394,17 @@ function createPanelOutlineTextureForLayer({
32946
33394
  );
32947
33395
  }
32948
33396
  });
32949
- const texture = new THREE20.CanvasTexture(canvas);
33397
+ const texture = new THREE24.CanvasTexture(canvas);
32950
33398
  texture.generateMipmaps = true;
32951
- texture.minFilter = THREE20.LinearMipmapLinearFilter;
32952
- texture.magFilter = THREE20.LinearFilter;
33399
+ texture.minFilter = THREE24.LinearMipmapLinearFilter;
33400
+ texture.magFilter = THREE24.LinearFilter;
32953
33401
  texture.anisotropy = 16;
32954
33402
  texture.needsUpdate = true;
32955
33403
  return texture;
32956
33404
  }
32957
33405
 
32958
33406
  // src/utils/trace-texture.ts
32959
- import * as THREE21 from "three";
33407
+ import * as THREE25 from "three";
32960
33408
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer2 } from "circuit-to-canvas";
32961
33409
  import { getElementRenderLayers, su as su7 } from "@tscircuit/circuit-json-util";
32962
33410
 
@@ -33073,17 +33521,17 @@ function createTraceTextureForLayer({
33073
33521
  drawSoldermaskTop: false,
33074
33522
  drawSoldermaskBottom: false
33075
33523
  });
33076
- const texture = new THREE21.CanvasTexture(canvas);
33524
+ const texture = new THREE25.CanvasTexture(canvas);
33077
33525
  texture.generateMipmaps = true;
33078
- texture.minFilter = THREE21.LinearMipmapLinearFilter;
33079
- texture.magFilter = THREE21.LinearFilter;
33526
+ texture.minFilter = THREE25.LinearMipmapLinearFilter;
33527
+ texture.magFilter = THREE25.LinearFilter;
33080
33528
  texture.anisotropy = 16;
33081
33529
  texture.needsUpdate = true;
33082
33530
  return texture;
33083
33531
  }
33084
33532
 
33085
33533
  // src/textures/create-copper-text-texture-for-layer.ts
33086
- import * as THREE22 from "three";
33534
+ import * as THREE26 from "three";
33087
33535
 
33088
33536
  // src/textures/copper-text/copper-text-drawing.ts
33089
33537
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer3 } from "circuit-to-canvas";
@@ -33194,17 +33642,17 @@ function createCopperTextTextureForLayer({
33194
33642
  elements,
33195
33643
  copperColor
33196
33644
  });
33197
- const texture = new THREE22.CanvasTexture(canvas);
33645
+ const texture = new THREE26.CanvasTexture(canvas);
33198
33646
  texture.generateMipmaps = true;
33199
- texture.minFilter = THREE22.LinearMipmapLinearFilter;
33200
- texture.magFilter = THREE22.LinearFilter;
33647
+ texture.minFilter = THREE26.LinearMipmapLinearFilter;
33648
+ texture.magFilter = THREE26.LinearFilter;
33201
33649
  texture.anisotropy = 16;
33202
33650
  texture.needsUpdate = true;
33203
33651
  return texture;
33204
33652
  }
33205
33653
 
33206
33654
  // src/textures/create-copper-pour-texture-for-layer.ts
33207
- import * as THREE23 from "three";
33655
+ import * as THREE27 from "three";
33208
33656
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer4 } from "circuit-to-canvas";
33209
33657
  var toRgb = (colorArr) => {
33210
33658
  const [r = 0, g = 0, b = 0] = colorArr;
@@ -33311,17 +33759,17 @@ function createCopperPourTextureForLayer({
33311
33759
  );
33312
33760
  setColorAndDraw(coveredPours, coveredColor);
33313
33761
  setColorAndDraw(uncoveredPours, uncoveredColor);
33314
- const texture = new THREE23.CanvasTexture(canvas);
33762
+ const texture = new THREE27.CanvasTexture(canvas);
33315
33763
  texture.generateMipmaps = true;
33316
- texture.minFilter = THREE23.LinearMipmapLinearFilter;
33317
- texture.magFilter = THREE23.LinearFilter;
33764
+ texture.minFilter = THREE27.LinearMipmapLinearFilter;
33765
+ texture.magFilter = THREE27.LinearFilter;
33318
33766
  texture.anisotropy = 16;
33319
33767
  texture.needsUpdate = true;
33320
33768
  return texture;
33321
33769
  }
33322
33770
 
33323
33771
  // src/textures/create-fabrication-note-texture-for-layer.ts
33324
- import * as THREE24 from "three";
33772
+ import * as THREE28 from "three";
33325
33773
 
33326
33774
  // src/textures/fabrication-note/fabrication-note-drawing.ts
33327
33775
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer5 } from "circuit-to-canvas";
@@ -33548,17 +33996,17 @@ function createFabricationNoteTextureForLayer({
33548
33996
  bounds,
33549
33997
  elements
33550
33998
  });
33551
- const texture = new THREE24.CanvasTexture(canvas);
33999
+ const texture = new THREE28.CanvasTexture(canvas);
33552
34000
  texture.generateMipmaps = true;
33553
- texture.minFilter = THREE24.LinearMipmapLinearFilter;
33554
- texture.magFilter = THREE24.LinearFilter;
34001
+ texture.minFilter = THREE28.LinearMipmapLinearFilter;
34002
+ texture.magFilter = THREE28.LinearFilter;
33555
34003
  texture.anisotropy = 16;
33556
34004
  texture.needsUpdate = true;
33557
34005
  return texture;
33558
34006
  }
33559
34007
 
33560
34008
  // src/textures/create-pcb-note-texture-for-layer.ts
33561
- import * as THREE25 from "three";
34009
+ import * as THREE29 from "three";
33562
34010
 
33563
34011
  // src/textures/pcb-note/pcb-note-drawing.ts
33564
34012
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer6 } from "circuit-to-canvas";
@@ -33709,17 +34157,17 @@ function createPcbNoteTextureForLayer({
33709
34157
  bounds,
33710
34158
  elements
33711
34159
  });
33712
- const texture = new THREE25.CanvasTexture(canvas);
34160
+ const texture = new THREE29.CanvasTexture(canvas);
33713
34161
  texture.generateMipmaps = true;
33714
- texture.minFilter = THREE25.LinearMipmapLinearFilter;
33715
- texture.magFilter = THREE25.LinearFilter;
34162
+ texture.minFilter = THREE29.LinearMipmapLinearFilter;
34163
+ texture.magFilter = THREE29.LinearFilter;
33716
34164
  texture.anisotropy = 16;
33717
34165
  texture.needsUpdate = true;
33718
34166
  return texture;
33719
34167
  }
33720
34168
 
33721
34169
  // src/textures/create-silkscreen-texture-for-layer.ts
33722
- import * as THREE26 from "three";
34170
+ import * as THREE30 from "three";
33723
34171
 
33724
34172
  // src/textures/silkscreen/silkscreen-drawing.ts
33725
34173
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer7 } from "circuit-to-canvas";
@@ -33828,17 +34276,17 @@ function createSilkscreenTextureForLayer({
33828
34276
  elements,
33829
34277
  silkscreenColor
33830
34278
  });
33831
- const texture = new THREE26.CanvasTexture(canvas);
34279
+ const texture = new THREE30.CanvasTexture(canvas);
33832
34280
  texture.generateMipmaps = true;
33833
- texture.minFilter = THREE26.LinearMipmapLinearFilter;
33834
- texture.magFilter = THREE26.LinearFilter;
34281
+ texture.minFilter = THREE30.LinearMipmapLinearFilter;
34282
+ texture.magFilter = THREE30.LinearFilter;
33835
34283
  texture.anisotropy = 16;
33836
34284
  texture.needsUpdate = true;
33837
34285
  return texture;
33838
34286
  }
33839
34287
 
33840
34288
  // src/textures/create-soldermask-texture-for-layer.ts
33841
- import * as THREE27 from "three";
34289
+ import * as THREE31 from "three";
33842
34290
 
33843
34291
  // src/textures/soldermask/soldermask-drawing.ts
33844
34292
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer8 } from "circuit-to-canvas";
@@ -33970,17 +34418,17 @@ function createSoldermaskTextureForLayer({
33970
34418
  elements,
33971
34419
  boardMaterial: boardData.material
33972
34420
  });
33973
- const texture = new THREE27.CanvasTexture(canvas);
34421
+ const texture = new THREE31.CanvasTexture(canvas);
33974
34422
  texture.generateMipmaps = true;
33975
- texture.minFilter = THREE27.LinearMipmapLinearFilter;
33976
- texture.magFilter = THREE27.LinearFilter;
34423
+ texture.minFilter = THREE31.LinearMipmapLinearFilter;
34424
+ texture.magFilter = THREE31.LinearFilter;
33977
34425
  texture.anisotropy = 16;
33978
34426
  texture.needsUpdate = true;
33979
34427
  return texture;
33980
34428
  }
33981
34429
 
33982
34430
  // src/textures/create-through-hole-texture-for-layer.ts
33983
- import * as THREE28 from "three";
34431
+ import * as THREE32 from "three";
33984
34432
 
33985
34433
  // src/textures/through-hole/through-hole-drawing.ts
33986
34434
  import { CircuitToCanvasDrawer as CircuitToCanvasDrawer9 } from "circuit-to-canvas";
@@ -34073,10 +34521,10 @@ function createThroughHoleTextureForLayer({
34073
34521
  elements,
34074
34522
  copperColor
34075
34523
  });
34076
- const texture = new THREE28.CanvasTexture(canvas);
34524
+ const texture = new THREE32.CanvasTexture(canvas);
34077
34525
  texture.generateMipmaps = true;
34078
- texture.minFilter = THREE28.LinearMipmapLinearFilter;
34079
- texture.magFilter = THREE28.LinearFilter;
34526
+ texture.minFilter = THREE32.LinearMipmapLinearFilter;
34527
+ texture.magFilter = THREE32.LinearFilter;
34080
34528
  texture.anisotropy = 16;
34081
34529
  texture.needsUpdate = true;
34082
34530
  return texture;
@@ -34114,10 +34562,10 @@ var createCombinedTexture = ({
34114
34562
  const image = texture.image;
34115
34563
  ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
34116
34564
  });
34117
- const combinedTexture = new THREE29.CanvasTexture(canvas);
34565
+ const combinedTexture = new THREE33.CanvasTexture(canvas);
34118
34566
  combinedTexture.generateMipmaps = false;
34119
- combinedTexture.minFilter = THREE29.LinearFilter;
34120
- combinedTexture.magFilter = THREE29.LinearFilter;
34567
+ combinedTexture.minFilter = THREE33.LinearFilter;
34568
+ combinedTexture.magFilter = THREE33.LinearFilter;
34121
34569
  combinedTexture.premultiplyAlpha = true;
34122
34570
  combinedTexture.anisotropy = 16;
34123
34571
  combinedTexture.needsUpdate = true;
@@ -34229,7 +34677,7 @@ function createCombinedBoardTextures({
34229
34677
  }
34230
34678
 
34231
34679
  // src/textures/create-three-texture-meshes.ts
34232
- import * as THREE30 from "three";
34680
+ import * as THREE34 from "three";
34233
34681
  function createTexturePlane(config, boardData) {
34234
34682
  const {
34235
34683
  texture,
@@ -34241,15 +34689,15 @@ function createTexturePlane(config, boardData) {
34241
34689
  } = config;
34242
34690
  if (!texture) return null;
34243
34691
  const boardOutlineBounds = calculateOutlineBounds(boardData);
34244
- const planeGeom = new THREE30.PlaneGeometry(
34692
+ const planeGeom = new THREE34.PlaneGeometry(
34245
34693
  boardOutlineBounds.width,
34246
34694
  boardOutlineBounds.height
34247
34695
  );
34248
- const material = new THREE30.MeshBasicMaterial({
34696
+ const material = new THREE34.MeshBasicMaterial({
34249
34697
  map: texture,
34250
34698
  transparent: true,
34251
34699
  alphaTest: 0.08,
34252
- side: THREE30.FrontSide,
34700
+ side: THREE34.FrontSide,
34253
34701
  depthWrite: true,
34254
34702
  polygonOffset: usePolygonOffset,
34255
34703
  polygonOffsetFactor: usePolygonOffset ? -4 : 0,
@@ -34257,7 +34705,7 @@ function createTexturePlane(config, boardData) {
34257
34705
  polygonOffsetUnits: usePolygonOffset ? -4 : 0,
34258
34706
  opacity: isFaux ? FAUX_BOARD_OPACITY : 1
34259
34707
  });
34260
- const mesh = new THREE30.Mesh(planeGeom, material);
34708
+ const mesh = new THREE34.Mesh(planeGeom, material);
34261
34709
  mesh.position.set(
34262
34710
  boardOutlineBounds.centerX,
34263
34711
  boardOutlineBounds.centerY,
@@ -34302,7 +34750,7 @@ function createTextureMeshes(textures, boardData, pcbThickness, isFaux = false)
34302
34750
  }
34303
34751
 
34304
34752
  // src/three-components/JscadBoardTextures.tsx
34305
- import * as THREE31 from "three";
34753
+ import * as THREE35 from "three";
34306
34754
 
34307
34755
  // src/utils/layer-texture-resolution.ts
34308
34756
  var DEFAULT_MAX_TEXTURE_PIXELS = 4e6;
@@ -34398,7 +34846,7 @@ function JscadBoardTextures({
34398
34846
  const typedMaterial = material;
34399
34847
  for (const prop of textureProps) {
34400
34848
  const texture = typedMaterial[prop];
34401
- if (texture && texture instanceof THREE31.Texture) {
34849
+ if (texture && texture instanceof THREE35.Texture) {
34402
34850
  texture.dispose();
34403
34851
  typedMaterial[prop] = null;
34404
34852
  }
@@ -34408,22 +34856,22 @@ function JscadBoardTextures({
34408
34856
  const createTexturePlane2 = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false, depthWrite = true, renderOrder = 1) => {
34409
34857
  if (!texture) return null;
34410
34858
  const boardOutlineBounds = calculateOutlineBounds(boardData);
34411
- const planeGeom = new THREE31.PlaneGeometry(
34859
+ const planeGeom = new THREE35.PlaneGeometry(
34412
34860
  boardOutlineBounds.width,
34413
34861
  boardOutlineBounds.height
34414
34862
  );
34415
- const material = new THREE31.MeshBasicMaterial({
34863
+ const material = new THREE35.MeshBasicMaterial({
34416
34864
  map: texture,
34417
34865
  transparent: true,
34418
34866
  alphaTest: 0.08,
34419
- side: THREE31.FrontSide,
34867
+ side: THREE35.FrontSide,
34420
34868
  depthWrite,
34421
34869
  polygonOffset: usePolygonOffset,
34422
34870
  polygonOffsetFactor: usePolygonOffset ? -4 : 0,
34423
34871
  polygonOffsetUnits: usePolygonOffset ? -4 : 0,
34424
34872
  opacity: isFaux ? FAUX_BOARD_OPACITY : 1
34425
34873
  });
34426
- const mesh = new THREE31.Mesh(planeGeom, material);
34874
+ const mesh = new THREE35.Mesh(planeGeom, material);
34427
34875
  mesh.position.set(
34428
34876
  boardOutlineBounds.centerX,
34429
34877
  boardOutlineBounds.centerY,
@@ -34468,7 +34916,7 @@ function JscadBoardTextures({
34468
34916
  mesh.geometry.dispose();
34469
34917
  if (Array.isArray(mesh.material)) {
34470
34918
  mesh.material.forEach((material) => disposeTextureMaterial(material));
34471
- } else if (mesh.material instanceof THREE31.Material) {
34919
+ } else if (mesh.material instanceof THREE35.Material) {
34472
34920
  disposeTextureMaterial(mesh.material);
34473
34921
  }
34474
34922
  });
@@ -34701,12 +35149,12 @@ var CadViewerJscad = forwardRef3(
34701
35149
  // src/CadViewerManifold.tsx
34702
35150
  import { su as su17 } from "@tscircuit/circuit-json-util";
34703
35151
  import { useEffect as useEffect26, useMemo as useMemo22, useState as useState16 } from "react";
34704
- import * as THREE38 from "three";
35152
+ import * as THREE42 from "three";
34705
35153
 
34706
35154
  // src/hooks/useManifoldBoardBuilder.ts
34707
35155
  import { su as su16 } from "@tscircuit/circuit-json-util";
34708
35156
  import { useEffect as useEffect25, useMemo as useMemo21, useRef as useRef9, useState as useState15 } from "react";
34709
- import * as THREE35 from "three";
35157
+ import * as THREE39 from "three";
34710
35158
 
34711
35159
  // src/utils/manifold/create-manifold-board.ts
34712
35160
  var arePointsClockwise2 = (points) => {
@@ -35048,17 +35496,17 @@ function processNonPlatedHolesForManifold(Manifold, CrossSection, circuitJson, p
35048
35496
 
35049
35497
  // src/utils/manifold/process-plated-holes.ts
35050
35498
  import { su as su14 } from "@tscircuit/circuit-json-util";
35051
- import * as THREE33 from "three";
35499
+ import * as THREE37 from "three";
35052
35500
 
35053
35501
  // src/utils/manifold-mesh-to-three-geometry.ts
35054
- import * as THREE32 from "three";
35502
+ import * as THREE36 from "three";
35055
35503
  function manifoldMeshToThreeGeometry(manifoldMesh) {
35056
- const geometry = new THREE32.BufferGeometry();
35504
+ const geometry = new THREE36.BufferGeometry();
35057
35505
  geometry.setAttribute(
35058
35506
  "position",
35059
- new THREE32.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
35507
+ new THREE36.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
35060
35508
  );
35061
- geometry.setIndex(new THREE32.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
35509
+ geometry.setIndex(new THREE36.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
35062
35510
  if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
35063
35511
  for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
35064
35512
  const start = manifoldMesh.runIndex[i];
@@ -35092,7 +35540,7 @@ var createEllipsePoints = (width10, height10, segments) => {
35092
35540
  }
35093
35541
  return points;
35094
35542
  };
35095
- var COPPER_COLOR = new THREE33.Color(...colors.copper);
35543
+ var COPPER_COLOR = new THREE37.Color(...colors.copper);
35096
35544
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
35097
35545
  var PLATED_HOLE_PAD_THICKNESS = 3e-3;
35098
35546
  var PLATED_HOLE_SURFACE_CLEARANCE = 5e-4;
@@ -35723,7 +36171,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
35723
36171
 
35724
36172
  // src/utils/manifold/process-vias.ts
35725
36173
  import { su as su15 } from "@tscircuit/circuit-json-util";
35726
- import * as THREE34 from "three";
36174
+ import * as THREE38 from "three";
35727
36175
 
35728
36176
  // src/utils/via-geoms.ts
35729
36177
  function createViaCopper2({
@@ -35761,7 +36209,7 @@ function createViaCopper2({
35761
36209
  }
35762
36210
 
35763
36211
  // src/utils/manifold/process-vias.ts
35764
- var COPPER_COLOR2 = new THREE34.Color(...colors.copper);
36212
+ var COPPER_COLOR2 = new THREE38.Color(...colors.copper);
35765
36213
  function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
35766
36214
  const viaBoardDrills = [];
35767
36215
  const pcbVias = su15(circuitJson).pcb_via.list();
@@ -35981,7 +36429,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
35981
36429
  {
35982
36430
  key: "plated-holes-union",
35983
36431
  geometry: cutPlatedGeom,
35984
- color: new THREE35.Color(
36432
+ color: new THREE39.Color(
35985
36433
  colors.copper[0],
35986
36434
  colors.copper[1],
35987
36435
  colors.copper[2]
@@ -36011,7 +36459,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
36011
36459
  const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
36012
36460
  currentGeoms.board = {
36013
36461
  geometry: finalBoardGeom,
36014
- color: new THREE35.Color(
36462
+ color: new THREE39.Color(
36015
36463
  matColorArray[0],
36016
36464
  matColorArray[1],
36017
36465
  matColorArray[2]
@@ -36056,11 +36504,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
36056
36504
  };
36057
36505
 
36058
36506
  // src/utils/manifold/create-three-geometry-meshes.ts
36059
- import * as THREE37 from "three";
36507
+ import * as THREE41 from "three";
36060
36508
 
36061
36509
  // src/utils/create-board-material.ts
36062
- import * as THREE36 from "three";
36063
- var DEFAULT_SIDE = THREE36.DoubleSide;
36510
+ import * as THREE40 from "three";
36511
+ var DEFAULT_SIDE = THREE40.DoubleSide;
36064
36512
  var createBoardMaterial = ({
36065
36513
  material,
36066
36514
  color,
@@ -36068,7 +36516,7 @@ var createBoardMaterial = ({
36068
36516
  isFaux = false
36069
36517
  }) => {
36070
36518
  if (material === "fr4") {
36071
- return new THREE36.MeshPhysicalMaterial({
36519
+ return new THREE40.MeshPhysicalMaterial({
36072
36520
  color,
36073
36521
  side,
36074
36522
  metalness: 0,
@@ -36085,7 +36533,7 @@ var createBoardMaterial = ({
36085
36533
  polygonOffsetUnits: 1
36086
36534
  });
36087
36535
  }
36088
- return new THREE36.MeshStandardMaterial({
36536
+ return new THREE40.MeshStandardMaterial({
36089
36537
  color,
36090
36538
  side,
36091
36539
  flatShading: true,
@@ -36104,12 +36552,12 @@ function createGeometryMeshes(geoms) {
36104
36552
  const meshes = [];
36105
36553
  if (!geoms) return meshes;
36106
36554
  if (geoms.board && geoms.board.geometry) {
36107
- const mesh = new THREE37.Mesh(
36555
+ const mesh = new THREE41.Mesh(
36108
36556
  geoms.board.geometry,
36109
36557
  createBoardMaterial({
36110
36558
  material: geoms.board.material,
36111
36559
  color: geoms.board.color,
36112
- side: THREE37.DoubleSide,
36560
+ side: THREE41.DoubleSide,
36113
36561
  isFaux: geoms.board.isFaux
36114
36562
  })
36115
36563
  );
@@ -36119,11 +36567,11 @@ function createGeometryMeshes(geoms) {
36119
36567
  const createMeshesFromArray = (geomArray) => {
36120
36568
  if (geomArray) {
36121
36569
  geomArray.forEach((comp) => {
36122
- const mesh = new THREE37.Mesh(
36570
+ const mesh = new THREE41.Mesh(
36123
36571
  comp.geometry,
36124
- new THREE37.MeshStandardMaterial({
36572
+ new THREE41.MeshStandardMaterial({
36125
36573
  color: comp.color,
36126
- side: THREE37.DoubleSide,
36574
+ side: THREE41.DoubleSide,
36127
36575
  flatShading: true
36128
36576
  // Consistent with board
36129
36577
  })
@@ -36167,7 +36615,7 @@ var BoardMeshes = ({
36167
36615
  const typedMaterial = material;
36168
36616
  for (const prop of textureProps) {
36169
36617
  const texture = typedMaterial[prop];
36170
- if (texture && texture instanceof THREE38.Texture) {
36618
+ if (texture && texture instanceof THREE42.Texture) {
36171
36619
  texture.dispose();
36172
36620
  typedMaterial[prop] = null;
36173
36621
  }
@@ -41941,7 +42389,7 @@ var Root32 = Menu;
41941
42389
  var Anchor2 = MenuAnchor;
41942
42390
  var Portal2 = MenuPortal;
41943
42391
  var Content2 = MenuContent;
41944
- var Group5 = MenuGroup;
42392
+ var Group6 = MenuGroup;
41945
42393
  var Label = MenuLabel;
41946
42394
  var Item2 = MenuItem;
41947
42395
  var CheckboxItem = MenuCheckboxItem;
@@ -42087,7 +42535,7 @@ var DropdownMenuGroup = React43.forwardRef(
42087
42535
  (props, forwardedRef) => {
42088
42536
  const { __scopeDropdownMenu, ...groupProps } = props;
42089
42537
  const menuScope = useMenuScope(__scopeDropdownMenu);
42090
- return /* @__PURE__ */ jsx33(Group5, { ...menuScope, ...groupProps, ref: forwardedRef });
42538
+ return /* @__PURE__ */ jsx33(Group6, { ...menuScope, ...groupProps, ref: forwardedRef });
42091
42539
  }
42092
42540
  );
42093
42541
  DropdownMenuGroup.displayName = GROUP_NAME3;
@@ -43109,7 +43557,7 @@ var KeyboardShortcutsDialog = ({
43109
43557
 
43110
43558
  // src/CadViewer.tsx
43111
43559
  import { jsx as jsx38, jsxs as jsxs11 } from "react/jsx-runtime";
43112
- var DEFAULT_TARGET = new THREE39.Vector3(0, 0, 0);
43560
+ var DEFAULT_TARGET = new THREE43.Vector3(0, 0, 0);
43113
43561
  var INITIAL_CAMERA_POSITION = [5, -5, 5];
43114
43562
  var CadViewerInner = (props) => {
43115
43563
  const [engine, setEngine] = useState36("manifold");
@@ -43376,11 +43824,11 @@ var CadViewer = (props) => {
43376
43824
  // src/convert-circuit-json-to-3d-svg.ts
43377
43825
  var import_debug = __toESM(require_browser(), 1);
43378
43826
  import { su as su18 } from "@tscircuit/circuit-json-util";
43379
- import * as THREE43 from "three";
43827
+ import * as THREE47 from "three";
43380
43828
  import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
43381
43829
 
43382
43830
  // src/utils/create-geometry-from-polygons.ts
43383
- import * as THREE40 from "three";
43831
+ import * as THREE44 from "three";
43384
43832
  import { BufferGeometry as BufferGeometry4, Float32BufferAttribute as Float32BufferAttribute3 } from "three";
43385
43833
  function createGeometryFromPolygons(polygons) {
43386
43834
  const geometry = new BufferGeometry4();
@@ -43394,12 +43842,12 @@ function createGeometryFromPolygons(polygons) {
43394
43842
  ...polygon2.vertices[i + 1]
43395
43843
  // Third vertex
43396
43844
  );
43397
- const v1 = new THREE40.Vector3(...polygon2.vertices[0]);
43398
- const v2 = new THREE40.Vector3(...polygon2.vertices[i]);
43399
- const v3 = new THREE40.Vector3(...polygon2.vertices[i + 1]);
43400
- const normal = new THREE40.Vector3().crossVectors(
43401
- new THREE40.Vector3().subVectors(v2, v1),
43402
- new THREE40.Vector3().subVectors(v3, v1)
43845
+ const v1 = new THREE44.Vector3(...polygon2.vertices[0]);
43846
+ const v2 = new THREE44.Vector3(...polygon2.vertices[i]);
43847
+ const v3 = new THREE44.Vector3(...polygon2.vertices[i + 1]);
43848
+ const normal = new THREE44.Vector3().crossVectors(
43849
+ new THREE44.Vector3().subVectors(v2, v1),
43850
+ new THREE44.Vector3().subVectors(v3, v1)
43403
43851
  ).normalize();
43404
43852
  normals.push(
43405
43853
  normal.x,
@@ -43423,10 +43871,10 @@ function createGeometryFromPolygons(polygons) {
43423
43871
  var import_modeling2 = __toESM(require_src(), 1);
43424
43872
  var import_jscad_planner2 = __toESM(require_dist(), 1);
43425
43873
  var jscadModeling2 = __toESM(require_src(), 1);
43426
- import * as THREE42 from "three";
43874
+ import * as THREE46 from "three";
43427
43875
 
43428
43876
  // src/utils/load-model.ts
43429
- import * as THREE41 from "three";
43877
+ import * as THREE45 from "three";
43430
43878
  import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
43431
43879
  import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
43432
43880
  import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
@@ -43434,12 +43882,12 @@ async function load3DModel(url) {
43434
43882
  if (url.endsWith(".stl")) {
43435
43883
  const loader = new STLLoader2();
43436
43884
  const geometry = await loader.loadAsync(url);
43437
- const material = new THREE41.MeshStandardMaterial({
43885
+ const material = new THREE45.MeshStandardMaterial({
43438
43886
  color: 8947848,
43439
43887
  metalness: 0.5,
43440
43888
  roughness: 0.5
43441
43889
  });
43442
- return new THREE41.Mesh(geometry, material);
43890
+ return new THREE45.Mesh(geometry, material);
43443
43891
  }
43444
43892
  if (url.endsWith(".obj")) {
43445
43893
  const loader = new OBJLoader2();
@@ -43472,9 +43920,9 @@ async function renderComponent(component, scene) {
43472
43920
  }
43473
43921
  if (component.rotation) {
43474
43922
  model.rotation.set(
43475
- THREE42.MathUtils.degToRad(component.rotation.x ?? 0),
43476
- THREE42.MathUtils.degToRad(component.rotation.y ?? 0),
43477
- THREE42.MathUtils.degToRad(component.rotation.z ?? 0)
43923
+ THREE46.MathUtils.degToRad(component.rotation.x ?? 0),
43924
+ THREE46.MathUtils.degToRad(component.rotation.y ?? 0),
43925
+ THREE46.MathUtils.degToRad(component.rotation.z ?? 0)
43478
43926
  );
43479
43927
  }
43480
43928
  scene.add(model);
@@ -43488,13 +43936,13 @@ async function renderComponent(component, scene) {
43488
43936
  );
43489
43937
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
43490
43938
  const threeGeom = convertCSGToThreeGeom(jscadObject);
43491
- const material2 = new THREE42.MeshStandardMaterial({
43939
+ const material2 = new THREE46.MeshStandardMaterial({
43492
43940
  color: 8947848,
43493
43941
  metalness: 0.5,
43494
43942
  roughness: 0.5,
43495
- side: THREE42.DoubleSide
43943
+ side: THREE46.DoubleSide
43496
43944
  });
43497
- const mesh2 = new THREE42.Mesh(threeGeom, material2);
43945
+ const mesh2 = new THREE46.Mesh(threeGeom, material2);
43498
43946
  if (component.position) {
43499
43947
  mesh2.position.set(
43500
43948
  component.position.x ?? 0,
@@ -43504,9 +43952,9 @@ async function renderComponent(component, scene) {
43504
43952
  }
43505
43953
  if (component.rotation) {
43506
43954
  mesh2.rotation.set(
43507
- THREE42.MathUtils.degToRad(component.rotation.x ?? 0),
43508
- THREE42.MathUtils.degToRad(component.rotation.y ?? 0),
43509
- THREE42.MathUtils.degToRad(component.rotation.z ?? 0)
43955
+ THREE46.MathUtils.degToRad(component.rotation.x ?? 0),
43956
+ THREE46.MathUtils.degToRad(component.rotation.y ?? 0),
43957
+ THREE46.MathUtils.degToRad(component.rotation.z ?? 0)
43510
43958
  );
43511
43959
  }
43512
43960
  scene.add(mesh2);
@@ -43523,17 +43971,17 @@ async function renderComponent(component, scene) {
43523
43971
  if (!geom || !geom.polygons && !geom.sides) {
43524
43972
  continue;
43525
43973
  }
43526
- const color = new THREE42.Color(geomInfo.color);
43974
+ const color = new THREE46.Color(geomInfo.color);
43527
43975
  color.convertLinearToSRGB();
43528
43976
  const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
43529
43977
  const threeGeom = convertCSGToThreeGeom(geomWithColor);
43530
- const material2 = new THREE42.MeshStandardMaterial({
43978
+ const material2 = new THREE46.MeshStandardMaterial({
43531
43979
  vertexColors: true,
43532
43980
  metalness: 0.2,
43533
43981
  roughness: 0.8,
43534
- side: THREE42.DoubleSide
43982
+ side: THREE46.DoubleSide
43535
43983
  });
43536
- const mesh2 = new THREE42.Mesh(threeGeom, material2);
43984
+ const mesh2 = new THREE46.Mesh(threeGeom, material2);
43537
43985
  if (component.position) {
43538
43986
  mesh2.position.set(
43539
43987
  component.position.x ?? 0,
@@ -43543,22 +43991,22 @@ async function renderComponent(component, scene) {
43543
43991
  }
43544
43992
  if (component.rotation) {
43545
43993
  mesh2.rotation.set(
43546
- THREE42.MathUtils.degToRad(component.rotation.x ?? 0),
43547
- THREE42.MathUtils.degToRad(component.rotation.y ?? 0),
43548
- THREE42.MathUtils.degToRad(component.rotation.z ?? 0)
43994
+ THREE46.MathUtils.degToRad(component.rotation.x ?? 0),
43995
+ THREE46.MathUtils.degToRad(component.rotation.y ?? 0),
43996
+ THREE46.MathUtils.degToRad(component.rotation.z ?? 0)
43549
43997
  );
43550
43998
  }
43551
43999
  scene.add(mesh2);
43552
44000
  }
43553
44001
  return;
43554
44002
  }
43555
- const geometry = new THREE42.BoxGeometry(0.5, 0.5, 0.5);
43556
- const material = new THREE42.MeshStandardMaterial({
44003
+ const geometry = new THREE46.BoxGeometry(0.5, 0.5, 0.5);
44004
+ const material = new THREE46.MeshStandardMaterial({
43557
44005
  color: 16711680,
43558
44006
  transparent: true,
43559
44007
  opacity: 0.25
43560
44008
  });
43561
- const mesh = new THREE42.Mesh(geometry, material);
44009
+ const mesh = new THREE46.Mesh(geometry, material);
43562
44010
  if (component.position) {
43563
44011
  mesh.position.set(
43564
44012
  component.position.x ?? 0,
@@ -43579,11 +44027,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
43579
44027
  padding = 20,
43580
44028
  zoom = 1.5
43581
44029
  } = options;
43582
- const scene = new THREE43.Scene();
44030
+ const scene = new THREE47.Scene();
43583
44031
  const renderer = new SVGRenderer();
43584
44032
  renderer.setSize(width10, height10);
43585
- renderer.setClearColor(new THREE43.Color(backgroundColor), 1);
43586
- const camera = new THREE43.OrthographicCamera();
44033
+ renderer.setClearColor(new THREE47.Color(backgroundColor), 1);
44034
+ const camera = new THREE47.OrthographicCamera();
43587
44035
  const aspect = width10 / height10;
43588
44036
  const frustumSize = 100;
43589
44037
  const halfFrustumSize = frustumSize / 2 / zoom;
@@ -43597,11 +44045,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
43597
44045
  camera.position.set(position.x, position.y, position.z);
43598
44046
  camera.up.set(0, 1, 0);
43599
44047
  const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
43600
- camera.lookAt(new THREE43.Vector3(lookAt.x, lookAt.y, lookAt.z));
44048
+ camera.lookAt(new THREE47.Vector3(lookAt.x, lookAt.y, lookAt.z));
43601
44049
  camera.updateProjectionMatrix();
43602
- const ambientLight = new THREE43.AmbientLight(16777215, Math.PI / 2);
44050
+ const ambientLight = new THREE47.AmbientLight(16777215, Math.PI / 2);
43603
44051
  scene.add(ambientLight);
43604
- const pointLight = new THREE43.PointLight(16777215, Math.PI / 4);
44052
+ const pointLight = new THREE47.PointLight(16777215, Math.PI / 4);
43605
44053
  pointLight.position.set(-10, -10, 10);
43606
44054
  scene.add(pointLight);
43607
44055
  const components = su18(circuitJson).cad_component.list();
@@ -43612,7 +44060,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
43612
44060
  const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
43613
44061
  if (boardGeom) {
43614
44062
  const solderMaskColor = colors.fr4SolderMaskGreen;
43615
- const baseColor = new THREE43.Color(
44063
+ const baseColor = new THREE47.Color(
43616
44064
  solderMaskColor[0],
43617
44065
  solderMaskColor[1],
43618
44066
  solderMaskColor[2]
@@ -43624,28 +44072,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
43624
44072
  const material = createBoardMaterial({
43625
44073
  material: boardData?.material,
43626
44074
  color: baseColor,
43627
- side: THREE43.DoubleSide
44075
+ side: THREE47.DoubleSide
43628
44076
  });
43629
- const mesh = new THREE43.Mesh(geometry, material);
44077
+ const mesh = new THREE47.Mesh(geometry, material);
43630
44078
  scene.add(mesh);
43631
44079
  }
43632
44080
  }
43633
- const gridColor = new THREE43.Color(8947848);
43634
- const gridHelper = new THREE43.GridHelper(100, 100, gridColor, gridColor);
44081
+ const gridColor = new THREE47.Color(8947848);
44082
+ const gridHelper = new THREE47.GridHelper(100, 100, gridColor, gridColor);
43635
44083
  gridHelper.rotation.x = Math.PI / 2;
43636
44084
  const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
43637
44085
  for (const mat of materials) {
43638
44086
  mat.transparent = true;
43639
44087
  mat.opacity = 0.3;
43640
- if (mat instanceof THREE43.LineBasicMaterial) {
44088
+ if (mat instanceof THREE47.LineBasicMaterial) {
43641
44089
  mat.color = gridColor;
43642
44090
  mat.vertexColors = false;
43643
44091
  }
43644
44092
  }
43645
44093
  scene.add(gridHelper);
43646
- const box = new THREE43.Box3().setFromObject(scene);
43647
- const center = box.getCenter(new THREE43.Vector3());
43648
- const size4 = box.getSize(new THREE43.Vector3());
44094
+ const box = new THREE47.Box3().setFromObject(scene);
44095
+ const center = box.getCenter(new THREE47.Vector3());
44096
+ const size4 = box.getSize(new THREE47.Vector3());
43649
44097
  scene.position.sub(center);
43650
44098
  const maxDim = Math.max(size4.x, size4.y, size4.z);
43651
44099
  if (maxDim > 0) {