@tscircuit/3d-viewer 0.0.434 → 0.0.435

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 (3) hide show
  1. package/dist/index.d.ts +48 -1
  2. package/dist/index.js +1139 -995
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14228,11 +14228,12 @@ var require_browser = __commonJS({
14228
14228
  });
14229
14229
 
14230
14230
  // src/CadViewer.tsx
14231
- import { useState as useState33, useCallback as useCallback20, useRef as useRef23, useEffect as useEffect39 } from "react";
14231
+ import { useState as useState34, useCallback as useCallback22, useRef as useRef24, useEffect as useEffect40, useMemo as useMemo26 } from "react";
14232
+ import * as THREE29 from "three";
14232
14233
 
14233
14234
  // src/CadViewerJscad.tsx
14234
14235
  import { su as su6 } from "@tscircuit/circuit-json-util";
14235
- import { forwardRef as forwardRef3, useMemo as useMemo19 } from "react";
14236
+ import { forwardRef as forwardRef3, useMemo as useMemo18 } from "react";
14236
14237
 
14237
14238
  // src/AnyCadComponent.tsx
14238
14239
  import { su } from "@tscircuit/circuit-json-util";
@@ -28168,13 +28169,13 @@ var AnyCadComponent = ({
28168
28169
  };
28169
28170
 
28170
28171
  // src/CadViewerContainer.tsx
28171
- import { forwardRef as forwardRef2, useMemo as useMemo15, useRef as useRef6, useState as useState8 } from "react";
28172
- import * as THREE14 from "three";
28172
+ import { forwardRef as forwardRef2, useEffect as useEffect16, useMemo as useMemo13, useState as useState9 } from "react";
28173
+ import * as THREE15 from "three";
28173
28174
 
28174
28175
  // package.json
28175
28176
  var package_default = {
28176
28177
  name: "@tscircuit/3d-viewer",
28177
- version: "0.0.433",
28178
+ version: "0.0.434",
28178
28179
  main: "./dist/index.js",
28179
28180
  module: "./dist/index.js",
28180
28181
  type: "module",
@@ -28253,194 +28254,15 @@ var package_default = {
28253
28254
  }
28254
28255
  };
28255
28256
 
28256
- // src/three-components/cube-with-labeled-sides.tsx
28257
- import { useEffect as useEffect11, useMemo as useMemo9 } from "react";
28258
- import * as THREE8 from "three";
28259
-
28260
- // src/react-three/Text.tsx
28261
- import { useEffect as useEffect10, useMemo as useMemo8 } from "react";
28262
- import { Text as TroikaText } from "troika-three-text";
28263
- var Text = ({
28264
- children,
28265
- parent,
28266
- position,
28267
- rotation: rotation2,
28268
- scale: scale2,
28269
- color,
28270
- fontSize,
28271
- anchorX,
28272
- anchorY,
28273
- depthOffset
28274
- }) => {
28275
- const { rootObject } = useThree();
28276
- const mesh = useMemo8(() => {
28277
- const textMesh = new TroikaText();
28278
- textMesh.text = children;
28279
- if (position) textMesh.position.fromArray(position);
28280
- if (rotation2) textMesh.rotation.fromArray(rotation2);
28281
- if (scale2) textMesh.scale.fromArray(scale2);
28282
- textMesh.color = color || "white";
28283
- textMesh.fontSize = fontSize || 1;
28284
- textMesh.anchorX = anchorX || "center";
28285
- textMesh.anchorY = anchorY || "middle";
28286
- textMesh.depthOffset = depthOffset || 0;
28287
- textMesh.font = null;
28288
- textMesh.sync();
28289
- return textMesh;
28290
- }, [
28291
- children,
28292
- position,
28293
- rotation2,
28294
- scale2,
28295
- color,
28296
- fontSize,
28297
- anchorX,
28298
- anchorY,
28299
- depthOffset
28300
- ]);
28301
- useEffect10(() => {
28302
- const parentObject = parent || rootObject;
28303
- if (!parentObject || !mesh) return;
28304
- parentObject.add(mesh);
28305
- return () => {
28306
- parentObject.remove(mesh);
28307
- mesh.dispose();
28308
- };
28309
- }, [rootObject, parent, mesh]);
28310
- return null;
28311
- };
28312
-
28313
- // src/three-components/cube-with-labeled-sides.tsx
28314
- import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
28315
- if (typeof window !== "undefined") {
28316
- window.TSCI_MAIN_CAMERA_ROTATION = new THREE8.Euler(0, 0, 0);
28317
- }
28318
- function computePointInFront(rotationVector, distance2) {
28319
- const quaternion = new THREE8.Quaternion().setFromEuler(
28320
- new THREE8.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
28321
- );
28322
- const forwardVector = new THREE8.Vector3(0, 0, 1);
28323
- forwardVector.applyQuaternion(quaternion);
28324
- const result = forwardVector.multiplyScalar(distance2);
28325
- return result;
28326
- }
28327
- var CubeWithLabeledSides = ({}) => {
28328
- const { camera, scene } = useThree();
28329
- useEffect11(() => {
28330
- if (!scene) return;
28331
- const ambientLight = new THREE8.AmbientLight(16777215, Math.PI / 2);
28332
- scene.add(ambientLight);
28333
- return () => {
28334
- scene.remove(ambientLight);
28335
- };
28336
- }, [scene]);
28337
- useFrame(() => {
28338
- if (!camera) return;
28339
- const mainRot = window.TSCI_MAIN_CAMERA_ROTATION;
28340
- const cameraPosition = computePointInFront(mainRot, 2);
28341
- camera.position.copy(cameraPosition);
28342
- camera.lookAt(0, 0, 0);
28343
- });
28344
- const group = useMemo9(() => {
28345
- const g = new THREE8.Group();
28346
- g.rotation.fromArray([Math.PI / 2, 0, 0]);
28347
- const box = new THREE8.Mesh(
28348
- new THREE8.BoxGeometry(1, 1, 1),
28349
- new THREE8.MeshStandardMaterial({ color: "white" })
28350
- );
28351
- g.add(box);
28352
- const edges = new THREE8.LineSegments(
28353
- new THREE8.EdgesGeometry(new THREE8.BoxGeometry(1, 1, 1)),
28354
- new THREE8.LineBasicMaterial({ color: 0, linewidth: 2 })
28355
- );
28356
- g.add(edges);
28357
- return g;
28358
- }, []);
28359
- useEffect11(() => {
28360
- if (!scene) return;
28361
- scene.add(group);
28362
- return () => {
28363
- scene.remove(group);
28364
- };
28365
- }, [scene, group]);
28366
- return /* @__PURE__ */ jsxs3(Fragment4, { children: [
28367
- /* @__PURE__ */ jsx10(
28368
- Text,
28369
- {
28370
- parent: group,
28371
- position: [0, 0, 0.51],
28372
- fontSize: 0.25,
28373
- color: "black",
28374
- children: "Front"
28375
- }
28376
- ),
28377
- /* @__PURE__ */ jsx10(
28378
- Text,
28379
- {
28380
- parent: group,
28381
- position: [0, 0, -0.51],
28382
- fontSize: 0.25,
28383
- color: "black",
28384
- rotation: [0, Math.PI, 0],
28385
- children: "Back"
28386
- }
28387
- ),
28388
- /* @__PURE__ */ jsx10(
28389
- Text,
28390
- {
28391
- parent: group,
28392
- position: [0.51, 0, 0],
28393
- fontSize: 0.25,
28394
- color: "black",
28395
- rotation: [0, Math.PI / 2, 0],
28396
- children: "Right"
28397
- }
28398
- ),
28399
- /* @__PURE__ */ jsx10(
28400
- Text,
28401
- {
28402
- parent: group,
28403
- position: [-0.51, 0, 0],
28404
- fontSize: 0.25,
28405
- color: "black",
28406
- rotation: [0, -Math.PI / 2, 0],
28407
- children: "Left"
28408
- }
28409
- ),
28410
- /* @__PURE__ */ jsx10(
28411
- Text,
28412
- {
28413
- parent: group,
28414
- position: [0, 0.51, 0],
28415
- fontSize: 0.25,
28416
- color: "black",
28417
- rotation: [-Math.PI / 2, 0, 0],
28418
- children: "Top"
28419
- }
28420
- ),
28421
- /* @__PURE__ */ jsx10(
28422
- Text,
28423
- {
28424
- parent: group,
28425
- position: [0, -0.51, 0],
28426
- fontSize: 0.25,
28427
- color: "black",
28428
- rotation: [Math.PI / 2, 0, 0],
28429
- children: "Bottom"
28430
- }
28431
- )
28432
- ] });
28433
- };
28434
-
28435
28257
  // src/react-three/Canvas.tsx
28436
28258
  import {
28437
28259
  useRef as useRef4,
28438
- useEffect as useEffect12,
28439
- useState as useState7,
28440
- useCallback as useCallback4,
28260
+ useEffect as useEffect10,
28261
+ useState as useState8,
28262
+ useCallback as useCallback5,
28441
28263
  forwardRef,
28442
28264
  useImperativeHandle,
28443
- useMemo as useMemo10
28265
+ useMemo as useMemo9
28444
28266
  } from "react";
28445
28267
  import * as THREE10 from "three";
28446
28268
 
@@ -28450,158 +28272,388 @@ function removeExistingCanvases(container) {
28450
28272
  }
28451
28273
 
28452
28274
  // src/react-three/configure-renderer.ts
28453
- import * as THREE9 from "three";
28275
+ import * as THREE8 from "three";
28454
28276
  var configureRenderer = (renderer) => {
28455
- renderer.outputColorSpace = THREE9.SRGBColorSpace;
28456
- renderer.toneMapping = THREE9.ACESFilmicToneMapping;
28277
+ renderer.outputColorSpace = THREE8.SRGBColorSpace;
28278
+ renderer.toneMapping = THREE8.ACESFilmicToneMapping;
28457
28279
  renderer.toneMappingExposure = 1;
28458
28280
  };
28459
28281
 
28460
- // src/react-three/Canvas.tsx
28461
- import { jsx as jsx11 } from "react/jsx-runtime";
28462
- var Canvas = forwardRef(
28463
- ({ children, scene: sceneProps, camera: cameraProps, style, onCreated }, ref) => {
28464
- const mountRef = useRef4(null);
28465
- const [contextState, setContextState] = useState7(
28466
- null
28467
- );
28468
- const frameListeners = useRef4(
28469
- []
28470
- );
28471
- const onCreatedRef = useRef4(void 0);
28472
- onCreatedRef.current = onCreated;
28473
- const addFrameListener = useCallback4(
28474
- (listener) => {
28475
- frameListeners.current.push(listener);
28476
- },
28477
- []
28478
- );
28479
- const removeFrameListener = useCallback4(
28480
- (listener) => {
28481
- frameListeners.current = frameListeners.current.filter(
28482
- (l) => l !== listener
28483
- );
28484
- },
28485
- []
28486
- );
28487
- const scene = useMemo10(() => new THREE10.Scene(), []);
28488
- if (sceneProps?.up) {
28489
- scene.up.set(sceneProps.up.x, sceneProps.up.y, sceneProps.up.z);
28282
+ // src/contexts/CameraControllerContext.tsx
28283
+ import {
28284
+ createContext as createContext4,
28285
+ useCallback as useCallback4,
28286
+ useContext as useContext4,
28287
+ useMemo as useMemo8,
28288
+ useRef as useRef3,
28289
+ useState as useState7
28290
+ } from "react";
28291
+ import * as THREE9 from "three";
28292
+ import { jsx as jsx10 } from "react/jsx-runtime";
28293
+ var CAMERA_KEY = "cadViewerCameraStateSession";
28294
+ var saveCameraToSession = (camera, controls) => {
28295
+ try {
28296
+ const savedCameraSession = {
28297
+ position: camera.position.toArray(),
28298
+ quaternion: camera.quaternion.toArray(),
28299
+ up: camera.up.toArray(),
28300
+ fov: camera.fov ?? 50,
28301
+ target: controls.target.toArray()
28302
+ };
28303
+ sessionStorage.setItem(CAMERA_KEY, JSON.stringify(savedCameraSession));
28304
+ } catch (err) {
28305
+ console.warn("Failed to save camera:", err);
28306
+ }
28307
+ };
28308
+ var loadCameraFromSession = (camera, controls) => {
28309
+ try {
28310
+ const raw = sessionStorage.getItem(CAMERA_KEY);
28311
+ if (!raw) return false;
28312
+ const state = JSON.parse(raw);
28313
+ camera.position.fromArray(state.position);
28314
+ camera.quaternion.fromArray(state.quaternion);
28315
+ camera.up.fromArray(state.up);
28316
+ if ("fov" in camera) {
28317
+ const persp = camera;
28318
+ persp.fov = state.fov;
28319
+ persp.updateProjectionMatrix?.();
28490
28320
  }
28491
- const rootObject = useRef4(new THREE10.Object3D());
28492
- useImperativeHandle(ref, () => rootObject.current);
28493
- useEffect12(() => {
28494
- if (!mountRef.current) return;
28495
- removeExistingCanvases(mountRef.current);
28496
- const renderer = new THREE10.WebGLRenderer({ antialias: true, alpha: true });
28497
- configureRenderer(renderer);
28498
- renderer.setSize(
28499
- mountRef.current.clientWidth,
28500
- mountRef.current.clientHeight
28501
- );
28502
- renderer.setPixelRatio(window.devicePixelRatio);
28503
- mountRef.current.appendChild(renderer.domElement);
28504
- const camera = new THREE10.PerspectiveCamera(
28505
- 75,
28506
- mountRef.current.clientWidth / mountRef.current.clientHeight,
28507
- 0.1,
28508
- 1e3
28509
- );
28510
- if (cameraProps?.up) {
28511
- camera.up.set(cameraProps.up[0], cameraProps.up[1], cameraProps.up[2]);
28512
- }
28513
- if (cameraProps?.position) {
28514
- camera.position.set(
28515
- cameraProps.position[0],
28516
- cameraProps.position[1],
28517
- cameraProps.position[2]
28518
- );
28519
- }
28520
- camera.lookAt(0, 0, 0);
28521
- scene.add(rootObject.current);
28522
- window.__TSCIRCUIT_THREE_OBJECT = rootObject.current;
28523
- setContextState({
28524
- scene,
28525
- camera,
28526
- renderer,
28527
- rootObject: rootObject.current,
28528
- addFrameListener,
28529
- removeFrameListener
28530
- });
28531
- onCreatedRef.current?.({ camera, renderer });
28532
- let animationFrameId;
28533
- const clock = new THREE10.Clock();
28534
- const animate = () => {
28535
- const time = clock.getElapsedTime();
28536
- const delta = clock.getDelta();
28537
- frameListeners.current.forEach((listener) => listener(time, delta));
28538
- renderer.render(scene, camera);
28539
- animationFrameId = requestAnimationFrame(animate);
28540
- };
28541
- animate();
28542
- const handleResize = () => {
28543
- if (mountRef.current) {
28544
- camera.aspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
28545
- camera.updateProjectionMatrix();
28546
- renderer.setSize(
28547
- mountRef.current.clientWidth,
28548
- mountRef.current.clientHeight
28549
- );
28550
- }
28551
- };
28552
- window.addEventListener("resize", handleResize);
28553
- return () => {
28554
- window.removeEventListener("resize", handleResize);
28555
- cancelAnimationFrame(animationFrameId);
28556
- if (mountRef.current && renderer.domElement) {
28557
- mountRef.current.removeChild(renderer.domElement);
28558
- }
28559
- renderer.dispose();
28560
- scene.remove(rootObject.current);
28561
- if (window.__TSCIRCUIT_THREE_OBJECT === rootObject.current) {
28562
- window.__TSCIRCUIT_THREE_OBJECT = void 0;
28563
- }
28564
- };
28565
- }, [scene, addFrameListener, removeFrameListener]);
28566
- return /* @__PURE__ */ jsx11("div", { ref: mountRef, style: { width: "100%", height: "100%", ...style }, children: contextState && /* @__PURE__ */ jsx11(ThreeContext.Provider, { value: contextState, children: /* @__PURE__ */ jsx11(HoverProvider, { children }) }) });
28321
+ controls.target.fromArray(state.target);
28322
+ controls.update();
28323
+ camera.updateMatrixWorld();
28324
+ return true;
28325
+ } catch (err) {
28326
+ console.warn("Failed to restore camera:", err);
28327
+ return false;
28567
28328
  }
28568
- );
28569
-
28570
- // src/react-three/OrbitControls.tsx
28571
- import { useEffect as useEffect13, useMemo as useMemo11 } from "react";
28572
- import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
28573
- var OrbitControls = ({
28574
- autoRotate,
28575
- autoRotateSpeed,
28576
- onStart,
28577
- panSpeed,
28578
- rotateSpeed,
28579
- zoomSpeed,
28580
- enableDamping,
28581
- dampingFactor,
28582
- target,
28583
- onControlsChange
28584
- }) => {
28585
- const { camera, renderer } = useThree();
28586
- const controls = useMemo11(() => {
28587
- if (!camera || !renderer) return null;
28588
- return new ThreeOrbitControls(camera, renderer.domElement);
28589
- }, [camera, renderer]);
28590
- useEffect13(() => {
28591
- onControlsChange?.(controls ?? null);
28592
- return () => onControlsChange?.(null);
28593
- }, [controls, onControlsChange]);
28594
- useEffect13(() => {
28595
- if (!controls) return;
28596
- const handleChange = () => {
28597
- onControlsChange?.(controls);
28598
- };
28329
+ };
28330
+ var CameraControllerContext = createContext4(void 0);
28331
+ var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition }) => {
28332
+ const controlsRef = useRef3(null);
28333
+ const mainCameraRef = useRef3(null);
28334
+ const [controller, setController] = useState7(null);
28335
+ const [cameraType, setCameraType] = useState7(
28336
+ "perspective"
28337
+ );
28338
+ const [cameraPosition, setCameraPosition] = useState7(initialCameraPosition ?? null);
28339
+ const [cameraRotation, setCameraRotation] = useState7(
28340
+ new THREE9.Euler(0, 0, 0)
28341
+ );
28342
+ const baseDistance = useMemo8(() => {
28343
+ const [x, y, z133] = initialCameraPosition ?? [5, -5, 5];
28344
+ const distance2 = Math.hypot(
28345
+ x - defaultTarget.x,
28346
+ y - defaultTarget.y,
28347
+ z133 - defaultTarget.z
28348
+ );
28349
+ return distance2 > 0 ? distance2 : 5;
28350
+ }, [initialCameraPosition, defaultTarget]);
28351
+ const getPresetConfig = useCallback4(
28352
+ (preset) => {
28353
+ const targetVector = [
28354
+ defaultTarget.x,
28355
+ defaultTarget.y,
28356
+ defaultTarget.z
28357
+ ];
28358
+ const distance2 = baseDistance;
28359
+ const heightOffset = distance2 * 0.3;
28360
+ switch (preset) {
28361
+ case "Top Center Angled": {
28362
+ const angledOffset = distance2 / Math.sqrt(2);
28363
+ return {
28364
+ position: [
28365
+ defaultTarget.x,
28366
+ defaultTarget.y - angledOffset,
28367
+ defaultTarget.z + angledOffset
28368
+ ],
28369
+ target: targetVector,
28370
+ up: [0, 0, 1]
28371
+ };
28372
+ }
28373
+ case "Top Down":
28374
+ return {
28375
+ position: [
28376
+ defaultTarget.x,
28377
+ defaultTarget.y,
28378
+ defaultTarget.z + distance2
28379
+ ],
28380
+ target: targetVector,
28381
+ up: [0, 0, 1]
28382
+ };
28383
+ case "Top Left Corner":
28384
+ return {
28385
+ position: [
28386
+ defaultTarget.x - distance2 * 0.6,
28387
+ defaultTarget.y - distance2 * 0.6,
28388
+ defaultTarget.z + distance2 * 0.6
28389
+ ],
28390
+ target: targetVector,
28391
+ up: [0, 0, 1]
28392
+ };
28393
+ case "Top Right Corner":
28394
+ return {
28395
+ position: [
28396
+ defaultTarget.x + distance2 * 0.6,
28397
+ defaultTarget.y - distance2 * 0.6,
28398
+ defaultTarget.z + distance2 * 0.6
28399
+ ],
28400
+ target: targetVector,
28401
+ up: [0, 0, 1]
28402
+ };
28403
+ case "Left Sideview":
28404
+ return {
28405
+ position: [
28406
+ defaultTarget.x - distance2,
28407
+ defaultTarget.y,
28408
+ defaultTarget.z
28409
+ ],
28410
+ target: targetVector,
28411
+ up: [0, 0, 1]
28412
+ };
28413
+ case "Right Sideview":
28414
+ return {
28415
+ position: [
28416
+ defaultTarget.x + distance2,
28417
+ defaultTarget.y,
28418
+ defaultTarget.z
28419
+ ],
28420
+ target: targetVector,
28421
+ up: [0, 0, 1]
28422
+ };
28423
+ case "Front":
28424
+ return {
28425
+ position: [
28426
+ defaultTarget.x,
28427
+ defaultTarget.y - distance2,
28428
+ defaultTarget.z
28429
+ ],
28430
+ target: targetVector,
28431
+ up: [0, 0, 1]
28432
+ };
28433
+ case "Custom":
28434
+ default:
28435
+ return null;
28436
+ }
28437
+ },
28438
+ [baseDistance, defaultTarget]
28439
+ );
28440
+ const handleControlsChange = useCallback4(
28441
+ (controls) => {
28442
+ controlsRef.current = controls;
28443
+ },
28444
+ []
28445
+ );
28446
+ const cameraControllerContextValue = useMemo8(
28447
+ () => ({
28448
+ controlsRef,
28449
+ mainCameraRef,
28450
+ defaultTarget,
28451
+ baseDistance,
28452
+ controller,
28453
+ setController,
28454
+ getPresetConfig,
28455
+ handleControlsChange,
28456
+ cameraType,
28457
+ setCameraType,
28458
+ cameraPosition,
28459
+ setCameraPosition,
28460
+ cameraRotation,
28461
+ setCameraRotation,
28462
+ saveCameraToSession,
28463
+ loadCameraFromSession
28464
+ }),
28465
+ [
28466
+ defaultTarget,
28467
+ baseDistance,
28468
+ controller,
28469
+ getPresetConfig,
28470
+ handleControlsChange,
28471
+ cameraType,
28472
+ cameraPosition,
28473
+ cameraRotation
28474
+ ]
28475
+ );
28476
+ return /* @__PURE__ */ jsx10(CameraControllerContext.Provider, { value: cameraControllerContextValue, children });
28477
+ };
28478
+ var useCameraController = () => {
28479
+ const context = useContext4(CameraControllerContext);
28480
+ if (!context) {
28481
+ throw new Error(
28482
+ "useCameraController must be used within a CameraControllerProvider"
28483
+ );
28484
+ }
28485
+ return context;
28486
+ };
28487
+
28488
+ // src/react-three/Canvas.tsx
28489
+ import { jsx as jsx11 } from "react/jsx-runtime";
28490
+ var Canvas = forwardRef(
28491
+ ({ children, scene: sceneProps, camera: cameraProps, style, onCreated }, ref) => {
28492
+ const { cameraType } = useCameraController();
28493
+ const mountRef = useRef4(null);
28494
+ const [contextState, setContextState] = useState8(
28495
+ null
28496
+ );
28497
+ const frameListeners = useRef4(
28498
+ []
28499
+ );
28500
+ const onCreatedRef = useRef4(void 0);
28501
+ onCreatedRef.current = onCreated;
28502
+ const savedCameraStateRef = useRef4(null);
28503
+ const addFrameListener = useCallback5(
28504
+ (listener) => {
28505
+ frameListeners.current.push(listener);
28506
+ },
28507
+ []
28508
+ );
28509
+ const removeFrameListener = useCallback5(
28510
+ (listener) => {
28511
+ frameListeners.current = frameListeners.current.filter(
28512
+ (l) => l !== listener
28513
+ );
28514
+ },
28515
+ []
28516
+ );
28517
+ const scene = useMemo9(() => new THREE10.Scene(), []);
28518
+ if (sceneProps?.up) {
28519
+ scene.up.set(sceneProps.up.x, sceneProps.up.y, sceneProps.up.z);
28520
+ }
28521
+ const rootObject = useRef4(new THREE10.Object3D());
28522
+ useImperativeHandle(ref, () => rootObject.current);
28523
+ useEffect10(() => {
28524
+ if (!mountRef.current) return;
28525
+ removeExistingCanvases(mountRef.current);
28526
+ const renderer = new THREE10.WebGLRenderer({ antialias: true, alpha: true });
28527
+ configureRenderer(renderer);
28528
+ renderer.setSize(
28529
+ mountRef.current.clientWidth,
28530
+ mountRef.current.clientHeight
28531
+ );
28532
+ renderer.setPixelRatio(window.devicePixelRatio);
28533
+ mountRef.current.appendChild(renderer.domElement);
28534
+ const aspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
28535
+ const camera = cameraType === "perspective" ? new THREE10.PerspectiveCamera(75, aspect, 0.1, 1e3) : new THREE10.OrthographicCamera(
28536
+ -10 * aspect,
28537
+ 10 * aspect,
28538
+ 10,
28539
+ -10,
28540
+ -1e3,
28541
+ 1e3
28542
+ );
28543
+ if (savedCameraStateRef.current) {
28544
+ camera.position.copy(savedCameraStateRef.current.position);
28545
+ camera.quaternion.copy(savedCameraStateRef.current.quaternion);
28546
+ camera.up.copy(savedCameraStateRef.current.up);
28547
+ } else {
28548
+ if (cameraProps?.up) {
28549
+ camera.up.set(cameraProps.up[0], cameraProps.up[1], cameraProps.up[2]);
28550
+ }
28551
+ if (cameraProps?.position) {
28552
+ camera.position.set(
28553
+ cameraProps.position[0],
28554
+ cameraProps.position[1],
28555
+ cameraProps.position[2]
28556
+ );
28557
+ }
28558
+ camera.lookAt(0, 0, 0);
28559
+ }
28560
+ scene.add(rootObject.current);
28561
+ window.__TSCIRCUIT_THREE_OBJECT = rootObject.current;
28562
+ setContextState({
28563
+ scene,
28564
+ camera,
28565
+ renderer,
28566
+ rootObject: rootObject.current,
28567
+ addFrameListener,
28568
+ removeFrameListener
28569
+ });
28570
+ onCreatedRef.current?.({ camera, renderer });
28571
+ let animationFrameId;
28572
+ const clock = new THREE10.Clock();
28573
+ const animate = () => {
28574
+ const time = clock.getElapsedTime();
28575
+ const delta = clock.getDelta();
28576
+ frameListeners.current.forEach((listener) => listener(time, delta));
28577
+ renderer.render(scene, camera);
28578
+ animationFrameId = requestAnimationFrame(animate);
28579
+ };
28580
+ animate();
28581
+ const handleResize = () => {
28582
+ if (mountRef.current) {
28583
+ const newAspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
28584
+ if (camera instanceof THREE10.PerspectiveCamera) {
28585
+ camera.aspect = newAspect;
28586
+ } else if (camera instanceof THREE10.OrthographicCamera) {
28587
+ camera.left = -10 * newAspect;
28588
+ camera.right = 10 * newAspect;
28589
+ camera.top = 10;
28590
+ camera.bottom = -10;
28591
+ }
28592
+ camera.updateProjectionMatrix();
28593
+ renderer.setSize(
28594
+ mountRef.current.clientWidth,
28595
+ mountRef.current.clientHeight
28596
+ );
28597
+ }
28598
+ };
28599
+ window.addEventListener("resize", handleResize);
28600
+ return () => {
28601
+ savedCameraStateRef.current = {
28602
+ position: camera.position.clone(),
28603
+ quaternion: camera.quaternion.clone(),
28604
+ up: camera.up.clone()
28605
+ };
28606
+ window.removeEventListener("resize", handleResize);
28607
+ cancelAnimationFrame(animationFrameId);
28608
+ if (mountRef.current && renderer.domElement) {
28609
+ mountRef.current.removeChild(renderer.domElement);
28610
+ }
28611
+ renderer.dispose();
28612
+ scene.remove(rootObject.current);
28613
+ if (window.__TSCIRCUIT_THREE_OBJECT === rootObject.current) {
28614
+ window.__TSCIRCUIT_THREE_OBJECT = void 0;
28615
+ }
28616
+ };
28617
+ }, [scene, addFrameListener, removeFrameListener, cameraType]);
28618
+ return /* @__PURE__ */ jsx11("div", { ref: mountRef, style: { width: "100%", height: "100%", ...style }, children: contextState && /* @__PURE__ */ jsx11(ThreeContext.Provider, { value: contextState, children: /* @__PURE__ */ jsx11(HoverProvider, { children }) }) });
28619
+ }
28620
+ );
28621
+
28622
+ // src/react-three/OrbitControls.tsx
28623
+ import { useEffect as useEffect11, useMemo as useMemo10 } from "react";
28624
+ import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
28625
+ var OrbitControls = ({
28626
+ autoRotate,
28627
+ autoRotateSpeed,
28628
+ onStart,
28629
+ panSpeed,
28630
+ rotateSpeed,
28631
+ zoomSpeed,
28632
+ enableDamping,
28633
+ dampingFactor,
28634
+ target,
28635
+ onControlsChange
28636
+ }) => {
28637
+ const { camera, renderer } = useThree();
28638
+ const controls = useMemo10(() => {
28639
+ if (!camera || !renderer) return null;
28640
+ return new ThreeOrbitControls(camera, renderer.domElement);
28641
+ }, [camera, renderer]);
28642
+ useEffect11(() => {
28643
+ onControlsChange?.(controls ?? null);
28644
+ return () => onControlsChange?.(null);
28645
+ }, [controls, onControlsChange]);
28646
+ useEffect11(() => {
28647
+ if (!controls) return;
28648
+ const handleChange = () => {
28649
+ onControlsChange?.(controls);
28650
+ };
28599
28651
  controls.addEventListener("change", handleChange);
28600
28652
  return () => {
28601
28653
  controls.removeEventListener("change", handleChange);
28602
28654
  };
28603
28655
  }, [controls, onControlsChange]);
28604
- useEffect13(() => {
28656
+ useEffect11(() => {
28605
28657
  if (!controls) return;
28606
28658
  controls.autoRotate = autoRotate || false;
28607
28659
  controls.autoRotateSpeed = autoRotateSpeed || 1;
@@ -28626,14 +28678,14 @@ var OrbitControls = ({
28626
28678
  dampingFactor,
28627
28679
  target
28628
28680
  ]);
28629
- useEffect13(() => {
28681
+ useEffect11(() => {
28630
28682
  if (!controls || !onStart) return;
28631
28683
  controls.addEventListener("start", onStart);
28632
28684
  return () => {
28633
28685
  controls.removeEventListener("start", onStart);
28634
28686
  };
28635
28687
  }, [controls, onStart]);
28636
- useEffect13(() => {
28688
+ useEffect11(() => {
28637
28689
  if (!controls) return;
28638
28690
  return () => {
28639
28691
  controls.dispose();
@@ -28646,7 +28698,7 @@ var OrbitControls = ({
28646
28698
  };
28647
28699
 
28648
28700
  // src/react-three/Grid.tsx
28649
- import { useEffect as useEffect14, useMemo as useMemo12 } from "react";
28701
+ import { useEffect as useEffect12, useMemo as useMemo11 } from "react";
28650
28702
  import * as THREE11 from "three";
28651
28703
  var vertexShader = `
28652
28704
  varying vec3 worldPosition;
@@ -28692,7 +28744,7 @@ var Grid = ({
28692
28744
  }) => {
28693
28745
  const { scene, camera } = useThree();
28694
28746
  const size5 = 1e3;
28695
- const gridMesh = useMemo12(() => {
28747
+ const gridMesh = useMemo11(() => {
28696
28748
  const geometry = new THREE11.PlaneGeometry(size5, size5);
28697
28749
  geometry.rotateX(-Math.PI / 2);
28698
28750
  const material = new THREE11.ShaderMaterial({
@@ -28721,7 +28773,7 @@ var Grid = ({
28721
28773
  gridMesh.position.set(camera.position.x, camera.position.y, 0);
28722
28774
  }
28723
28775
  });
28724
- useEffect14(() => {
28776
+ useEffect12(() => {
28725
28777
  if (!scene || !gridMesh) return;
28726
28778
  scene.add(gridMesh);
28727
28779
  return () => {
@@ -28738,21 +28790,21 @@ var Grid = ({
28738
28790
  };
28739
28791
 
28740
28792
  // src/react-three/Lights.tsx
28741
- import { useEffect as useEffect15, useMemo as useMemo13 } from "react";
28793
+ import { useEffect as useEffect13, useMemo as useMemo12 } from "react";
28742
28794
  import * as THREE12 from "three";
28743
28795
  var Lights = () => {
28744
28796
  const { scene } = useThree();
28745
- const ambientLight = useMemo13(
28797
+ const ambientLight = useMemo12(
28746
28798
  () => new THREE12.AmbientLight(16777215, Math.PI / 2),
28747
28799
  []
28748
28800
  );
28749
- const pointLight = useMemo13(() => {
28801
+ const pointLight = useMemo12(() => {
28750
28802
  const light = new THREE12.PointLight(16777215, Math.PI / 4);
28751
28803
  light.position.set(-10, -10, 10);
28752
28804
  light.decay = 0;
28753
28805
  return light;
28754
28806
  }, []);
28755
- useEffect15(() => {
28807
+ useEffect13(() => {
28756
28808
  if (!scene) return;
28757
28809
  scene.add(ambientLight);
28758
28810
  scene.add(pointLight);
@@ -28764,55 +28816,18 @@ var Lights = () => {
28764
28816
  return null;
28765
28817
  };
28766
28818
 
28767
- // src/hooks/useSessionCamera.ts
28768
- var CAMERA_KEY = "cadViewerCameraStateSession";
28769
- var saveCameraToSession = (camera, controls) => {
28770
- try {
28771
- const savedCameraSession = {
28772
- position: camera.position.toArray(),
28773
- quaternion: camera.quaternion.toArray(),
28774
- up: camera.up.toArray(),
28775
- fov: camera.fov ?? 50,
28776
- target: controls.target.toArray()
28777
- };
28778
- sessionStorage.setItem(CAMERA_KEY, JSON.stringify(savedCameraSession));
28779
- } catch (err) {
28780
- console.warn("Failed to save camera:", err);
28781
- }
28782
- };
28783
- var loadCameraFromSession = (camera, controls) => {
28784
- try {
28785
- const raw = sessionStorage.getItem(CAMERA_KEY);
28786
- if (!raw) return false;
28787
- const state = JSON.parse(raw);
28788
- camera.position.fromArray(state.position);
28789
- camera.quaternion.fromArray(state.quaternion);
28790
- camera.up.fromArray(state.up);
28791
- if ("fov" in camera) {
28792
- const persp = camera;
28793
- persp.fov = state.fov;
28794
- persp.updateProjectionMatrix?.();
28795
- }
28796
- controls.target.fromArray(state.target);
28797
- controls.update();
28798
- camera.updateMatrixWorld();
28799
- return true;
28800
- } catch (err) {
28801
- console.warn("Failed to restore camera:", err);
28802
- return false;
28803
- }
28804
- };
28805
-
28806
- // src/hooks/useCameraController.ts
28807
- import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo14, useRef as useRef5 } from "react";
28819
+ // src/hooks/cameraAnimation.ts
28820
+ import { useCallback as useCallback6, useEffect as useEffect14, useRef as useRef5 } from "react";
28808
28821
  import * as THREE13 from "three";
28809
28822
  var easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
28810
- var CameraAnimator = ({
28811
- defaultTarget,
28812
- controlsRef,
28813
- onReady
28814
- }) => {
28815
- const { camera } = useThree();
28823
+ var CameraAnimatorWithContext = () => {
28824
+ const {
28825
+ controlsRef,
28826
+ mainCameraRef,
28827
+ defaultTarget,
28828
+ setController,
28829
+ getPresetConfig
28830
+ } = useCameraController();
28816
28831
  const animationRef = useRef5(null);
28817
28832
  const tempQuaternion = useRef5(new THREE13.Quaternion());
28818
28833
  const tempTarget = useRef5(new THREE13.Vector3());
@@ -28821,9 +28836,9 @@ var CameraAnimator = ({
28821
28836
  const tempRollTarget = useRef5(new THREE13.Quaternion());
28822
28837
  const baseOrientationHelper = useRef5(new THREE13.Object3D());
28823
28838
  const orientationHelper = useRef5(new THREE13.Object3D());
28824
- const animateTo = useCallback5(
28839
+ const animateTo = useCallback6(
28825
28840
  ({ position, target, up, durationMs = 600 }) => {
28826
- if (!camera) return;
28841
+ if (!mainCameraRef.current) return;
28827
28842
  const currentTarget = controlsRef.current?.target ?? defaultTarget;
28828
28843
  const toPosition = new THREE13.Vector3(
28829
28844
  position[0],
@@ -28837,8 +28852,8 @@ var CameraAnimator = ({
28837
28852
  toOrientationHelper.up.copy(resolvedUp);
28838
28853
  toOrientationHelper.lookAt(resolvedTarget);
28839
28854
  const toQuaternion = toOrientationHelper.quaternion.clone();
28840
- const fromQuaternion = camera.quaternion.clone();
28841
- const fromPosition = camera.position.clone();
28855
+ const fromQuaternion = mainCameraRef.current.quaternion.clone();
28856
+ const fromPosition = mainCameraRef.current.position.clone();
28842
28857
  const fromTarget = currentTarget.clone();
28843
28858
  const baseHelper = baseOrientationHelper.current;
28844
28859
  baseHelper.up.set(0, 0, 1);
@@ -28863,17 +28878,30 @@ var CameraAnimator = ({
28863
28878
  duration: durationMs
28864
28879
  };
28865
28880
  },
28866
- [camera, controlsRef, defaultTarget]
28881
+ [mainCameraRef, controlsRef, defaultTarget]
28882
+ );
28883
+ const animateToPreset = useCallback6(
28884
+ (preset) => {
28885
+ if (preset === "Custom") return;
28886
+ const config = getPresetConfig(preset);
28887
+ if (!config) return;
28888
+ animateTo(config);
28889
+ },
28890
+ [animateTo, getPresetConfig]
28867
28891
  );
28868
- useEffect16(() => {
28869
- if (!onReady || !camera) return;
28870
- onReady({ animateTo });
28892
+ useEffect14(() => {
28893
+ if (!mainCameraRef.current) return;
28894
+ const controller = {
28895
+ animateTo,
28896
+ animateToPreset
28897
+ };
28898
+ setController(controller);
28871
28899
  return () => {
28872
- onReady(null);
28900
+ setController(null);
28873
28901
  };
28874
- }, [animateTo, camera, onReady]);
28902
+ }, [animateTo, animateToPreset, mainCameraRef, setController]);
28875
28903
  useFrame(() => {
28876
- if (!camera || !animationRef.current) return;
28904
+ if (!mainCameraRef.current || !animationRef.current) return;
28877
28905
  const {
28878
28906
  fromPosition,
28879
28907
  toPosition,
@@ -28888,12 +28916,12 @@ var CameraAnimator = ({
28888
28916
  const elapsed = performance.now() - startTime;
28889
28917
  const progress = duration <= 0 ? 1 : Math.min(elapsed / duration, 1);
28890
28918
  const eased = easeInOutCubic(progress);
28891
- camera.position.lerpVectors(fromPosition, toPosition, eased);
28919
+ mainCameraRef.current.position.lerpVectors(fromPosition, toPosition, eased);
28892
28920
  const nextTarget = tempTarget.current;
28893
28921
  nextTarget.copy(fromTarget).lerp(toTarget, eased);
28894
28922
  const baseHelper = baseOrientationHelper.current;
28895
28923
  baseHelper.up.set(0, 0, 1);
28896
- baseHelper.position.copy(camera.position);
28924
+ baseHelper.position.copy(mainCameraRef.current.position);
28897
28925
  baseHelper.lookAt(nextTarget);
28898
28926
  const baseQuaternion = tempQuaternion.current;
28899
28927
  baseQuaternion.copy(baseHelper.quaternion);
@@ -28909,18 +28937,18 @@ var CameraAnimator = ({
28909
28937
  }
28910
28938
  rollTarget.normalize();
28911
28939
  interpolatedRoll.slerp(rollTarget, eased);
28912
- camera.quaternion.copy(baseQuaternion).multiply(interpolatedRoll).normalize();
28940
+ mainCameraRef.current.quaternion.copy(baseQuaternion).multiply(interpolatedRoll).normalize();
28913
28941
  const upVector = tempUp.current;
28914
- upVector.set(0, 1, 0).applyQuaternion(camera.quaternion).normalize();
28915
- camera.up.copy(upVector);
28942
+ upVector.set(0, 1, 0).applyQuaternion(mainCameraRef.current.quaternion).normalize();
28943
+ mainCameraRef.current.up.copy(upVector);
28916
28944
  controlsRef.current?.target.copy(nextTarget);
28917
- camera.updateMatrixWorld();
28945
+ mainCameraRef.current.updateMatrixWorld();
28918
28946
  controlsRef.current?.update();
28919
28947
  if (progress >= 1) {
28920
- camera.position.copy(toPosition);
28921
- camera.quaternion.copy(toQuaternion);
28922
- camera.up.set(0, 0, 1);
28923
- camera.updateMatrixWorld();
28948
+ mainCameraRef.current.position.copy(toPosition);
28949
+ mainCameraRef.current.quaternion.copy(toQuaternion);
28950
+ mainCameraRef.current.up.set(0, 0, 1);
28951
+ mainCameraRef.current.updateMatrixWorld();
28924
28952
  controlsRef.current?.target.copy(toTarget);
28925
28953
  controlsRef.current?.update();
28926
28954
  animationRef.current = null;
@@ -28928,154 +28956,216 @@ var CameraAnimator = ({
28928
28956
  });
28929
28957
  return null;
28930
28958
  };
28931
- var useCameraController = ({
28932
- defaultTarget,
28933
- initialCameraPosition,
28934
- onCameraControllerReady
28935
- }) => {
28936
- const controlsRef = useRef5(null);
28937
- const baseDistance = useMemo14(() => {
28938
- const [x, y, z133] = initialCameraPosition ?? [5, -5, 5];
28939
- const distance2 = Math.hypot(
28940
- x - defaultTarget.x,
28941
- y - defaultTarget.y,
28942
- z133 - defaultTarget.z
28943
- );
28944
- return distance2 > 0 ? distance2 : 5;
28945
- }, [initialCameraPosition, defaultTarget]);
28946
- const getPresetConfig = useCallback5(
28947
- (preset) => {
28948
- const targetVector = [
28949
- defaultTarget.x,
28950
- defaultTarget.y,
28951
- defaultTarget.z
28952
- ];
28953
- const distance2 = baseDistance;
28954
- const heightOffset = distance2 * 0.3;
28955
- switch (preset) {
28956
- case "Top Centered": {
28957
- const angledOffset = distance2 / Math.sqrt(2);
28958
- return {
28959
- position: [
28960
- defaultTarget.x,
28961
- defaultTarget.y - angledOffset,
28962
- defaultTarget.z + angledOffset
28963
- ],
28964
- target: targetVector,
28965
- up: [0, 0, 1]
28966
- };
28967
- }
28968
- case "Top Down":
28969
- return {
28970
- position: [
28971
- defaultTarget.x,
28972
- defaultTarget.y,
28973
- defaultTarget.z + distance2
28974
- ],
28975
- target: targetVector,
28976
- up: [0, 0, 1]
28977
- };
28978
- case "Top Left Corner":
28979
- return {
28980
- position: [
28981
- defaultTarget.x - distance2 * 0.6,
28982
- defaultTarget.y - distance2 * 0.6,
28983
- defaultTarget.z + distance2 * 0.6
28984
- ],
28985
- target: targetVector,
28986
- up: [0, 0, 1]
28987
- };
28988
- case "Top Right Corner":
28989
- return {
28990
- position: [
28991
- defaultTarget.x + distance2 * 0.6,
28992
- defaultTarget.y - distance2 * 0.6,
28993
- defaultTarget.z + distance2 * 0.6
28994
- ],
28995
- target: targetVector,
28996
- up: [0, 0, 1]
28997
- };
28998
- case "Left Sideview":
28999
- return {
29000
- position: [
29001
- defaultTarget.x - distance2,
29002
- defaultTarget.y,
29003
- defaultTarget.z + heightOffset
29004
- ],
29005
- target: targetVector,
29006
- up: [0, 0, 1]
29007
- };
29008
- case "Right Sideview":
29009
- return {
29010
- position: [
29011
- defaultTarget.x + distance2,
29012
- defaultTarget.y,
29013
- defaultTarget.z + heightOffset
29014
- ],
29015
- target: targetVector,
29016
- up: [0, 0, 1]
29017
- };
29018
- case "Front":
29019
- return {
29020
- position: [
29021
- defaultTarget.x,
29022
- defaultTarget.y - distance2,
29023
- defaultTarget.z + heightOffset
29024
- ],
29025
- target: targetVector,
29026
- up: [0, 0, 1]
29027
- };
29028
- case "Custom":
29029
- default:
29030
- return null;
29031
- }
29032
- },
29033
- [baseDistance, defaultTarget]
29034
- );
29035
- const handleControllerReady = useCallback5(
29036
- (controller) => {
29037
- if (!onCameraControllerReady) return;
29038
- if (!controller) {
29039
- onCameraControllerReady(null);
29040
- return;
29041
- }
29042
- const enhancedController = {
29043
- animateTo: controller.animateTo,
29044
- animateToPreset: (preset) => {
29045
- if (preset === "Custom") return;
29046
- const config = getPresetConfig(preset);
29047
- if (!config) return;
29048
- controller.animateTo(config);
28959
+
28960
+ // src/hooks/useCameraSession.ts
28961
+ import { useCallback as useCallback7, useRef as useRef6 } from "react";
28962
+ var useCameraSession = () => {
28963
+ const { controlsRef } = useCameraController();
28964
+ const cameraRef = useRef6(null);
28965
+ const cameraRestoredRef = useRef6(false);
28966
+ const saveTimeoutRef = useRef6(null);
28967
+ const handleCameraCreated = useCallback7(
28968
+ (camera) => {
28969
+ cameraRef.current = camera;
28970
+ if (!cameraRestoredRef.current && controlsRef.current) {
28971
+ const restored = loadCameraFromSession(camera, controlsRef.current);
28972
+ if (restored) {
28973
+ cameraRestoredRef.current = true;
29049
28974
  }
29050
- };
29051
- onCameraControllerReady(enhancedController);
28975
+ }
29052
28976
  },
29053
- [getPresetConfig, onCameraControllerReady]
28977
+ [controlsRef]
29054
28978
  );
29055
- const handleControlsChange = useCallback5(
29056
- (controls) => {
29057
- controlsRef.current = controls;
29058
- },
29059
- []
28979
+ const handleControlsChange = useCallback7(() => {
28980
+ if (!cameraRef.current || !controlsRef.current) return;
28981
+ if (!cameraRestoredRef.current) {
28982
+ const restored = loadCameraFromSession(
28983
+ cameraRef.current,
28984
+ controlsRef.current
28985
+ );
28986
+ if (restored) {
28987
+ cameraRestoredRef.current = true;
28988
+ return;
28989
+ }
28990
+ }
28991
+ clearTimeout(saveTimeoutRef.current);
28992
+ saveTimeoutRef.current = setTimeout(() => {
28993
+ if (cameraRef.current && controlsRef.current) {
28994
+ saveCameraToSession(cameraRef.current, controlsRef.current);
28995
+ }
28996
+ }, 150);
28997
+ }, [controlsRef]);
28998
+ return {
28999
+ handleCameraCreated,
29000
+ handleControlsChange
29001
+ };
29002
+ };
29003
+
29004
+ // src/three-components/OrientationCubeCanvas.tsx
29005
+ import { useEffect as useEffect15, useRef as useRef7 } from "react";
29006
+ import * as THREE14 from "three";
29007
+ import { Text as TroikaText } from "troika-three-text";
29008
+ import { jsx as jsx12 } from "react/jsx-runtime";
29009
+ function computePointInFront(rotationVector, distance2) {
29010
+ const quaternion = new THREE14.Quaternion().setFromEuler(
29011
+ new THREE14.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
29060
29012
  );
29061
- const cameraAnimatorProps = useMemo14(
29062
- () => ({
29063
- defaultTarget,
29064
- controlsRef,
29065
- onReady: handleControllerReady
29066
- }),
29067
- [defaultTarget, handleControllerReady]
29013
+ const forwardVector = new THREE14.Vector3(0, 0, 1);
29014
+ forwardVector.applyQuaternion(quaternion);
29015
+ const result = forwardVector.multiplyScalar(distance2);
29016
+ return result;
29017
+ }
29018
+ var OrientationCubeCanvas = () => {
29019
+ const { mainCameraRef } = useCameraController();
29020
+ const containerRef = useRef7(null);
29021
+ const canvasRef = useRef7(null);
29022
+ const rendererRef = useRef7(null);
29023
+ const sceneRef = useRef7(null);
29024
+ const cameraRef = useRef7(null);
29025
+ const animationFrameRef = useRef7(null);
29026
+ useEffect15(() => {
29027
+ if (!containerRef.current) return;
29028
+ const canvas = document.createElement("canvas");
29029
+ canvasRef.current = canvas;
29030
+ containerRef.current.appendChild(canvas);
29031
+ const renderer = new THREE14.WebGLRenderer({
29032
+ canvas,
29033
+ antialias: true,
29034
+ alpha: true
29035
+ });
29036
+ renderer.setSize(120, 120);
29037
+ renderer.setPixelRatio(window.devicePixelRatio);
29038
+ rendererRef.current = renderer;
29039
+ const scene = new THREE14.Scene();
29040
+ sceneRef.current = scene;
29041
+ const camera = new THREE14.PerspectiveCamera(75, 1, 0.1, 1e3);
29042
+ camera.up.set(0, 0, 1);
29043
+ cameraRef.current = camera;
29044
+ const ambientLight = new THREE14.AmbientLight(16777215, Math.PI / 2);
29045
+ scene.add(ambientLight);
29046
+ const group = new THREE14.Group();
29047
+ group.rotation.fromArray([Math.PI / 2, 0, 0]);
29048
+ const cubeSize = 1;
29049
+ const box = new THREE14.Mesh(
29050
+ new THREE14.BoxGeometry(cubeSize, cubeSize, cubeSize),
29051
+ new THREE14.MeshStandardMaterial({ color: "white" })
29052
+ );
29053
+ group.add(box);
29054
+ const edges = new THREE14.LineSegments(
29055
+ new THREE14.EdgesGeometry(
29056
+ new THREE14.BoxGeometry(cubeSize, cubeSize, cubeSize)
29057
+ ),
29058
+ new THREE14.LineBasicMaterial({ color: 0, linewidth: 2 })
29059
+ );
29060
+ group.add(edges);
29061
+ scene.add(group);
29062
+ const distanceFromCenter = 0.51;
29063
+ const createTextMesh = (text, position, rotation2) => {
29064
+ const textMesh = new TroikaText();
29065
+ textMesh.text = text;
29066
+ textMesh.position.fromArray(position);
29067
+ if (rotation2) textMesh.rotation.fromArray(rotation2);
29068
+ textMesh.color = "black";
29069
+ textMesh.fontSize = 0.25;
29070
+ textMesh.anchorX = "center";
29071
+ textMesh.anchorY = "middle";
29072
+ textMesh.depthOffset = 0;
29073
+ textMesh.font = null;
29074
+ textMesh.sync();
29075
+ return textMesh;
29076
+ };
29077
+ const frontText = createTextMesh("Front", [0, 0, distanceFromCenter]);
29078
+ const backText = createTextMesh(
29079
+ "Back",
29080
+ [0, 0, -distanceFromCenter],
29081
+ [0, Math.PI, 0]
29082
+ );
29083
+ const rightText = createTextMesh(
29084
+ "Right",
29085
+ [distanceFromCenter, 0, 0],
29086
+ [0, Math.PI / 2, 0]
29087
+ );
29088
+ const leftText = createTextMesh(
29089
+ "Left",
29090
+ [-distanceFromCenter, 0, 0],
29091
+ [0, -Math.PI / 2, 0]
29092
+ );
29093
+ const topText = createTextMesh(
29094
+ "Top",
29095
+ [0, distanceFromCenter, 0],
29096
+ [-Math.PI / 2, 0, 0]
29097
+ );
29098
+ const bottomText = createTextMesh(
29099
+ "Bottom",
29100
+ [0, -distanceFromCenter, 0],
29101
+ [Math.PI / 2, 0, 0]
29102
+ );
29103
+ group.add(frontText);
29104
+ group.add(backText);
29105
+ group.add(rightText);
29106
+ group.add(leftText);
29107
+ group.add(topText);
29108
+ group.add(bottomText);
29109
+ const animate = () => {
29110
+ if (mainCameraRef.current) {
29111
+ const cameraPosition = computePointInFront(
29112
+ mainCameraRef.current.rotation ?? new THREE14.Euler(0, 0, 0),
29113
+ 2
29114
+ );
29115
+ if (!cameraPosition.equals(camera.position)) {
29116
+ camera.position.copy(cameraPosition);
29117
+ camera.lookAt(0, 0, 0);
29118
+ }
29119
+ }
29120
+ renderer.render(scene, camera);
29121
+ animationFrameRef.current = requestAnimationFrame(animate);
29122
+ };
29123
+ animate();
29124
+ return () => {
29125
+ if (animationFrameRef.current) {
29126
+ cancelAnimationFrame(animationFrameRef.current);
29127
+ }
29128
+ frontText.dispose();
29129
+ backText.dispose();
29130
+ rightText.dispose();
29131
+ leftText.dispose();
29132
+ topText.dispose();
29133
+ bottomText.dispose();
29134
+ box.geometry.dispose();
29135
+ box.material.dispose();
29136
+ edges.geometry.dispose();
29137
+ edges.material.dispose();
29138
+ scene.clear();
29139
+ renderer.dispose();
29140
+ if (canvasRef.current && containerRef.current) {
29141
+ containerRef.current.removeChild(canvasRef.current);
29142
+ }
29143
+ };
29144
+ }, [mainCameraRef]);
29145
+ return /* @__PURE__ */ jsx12(
29146
+ "div",
29147
+ {
29148
+ ref: containerRef,
29149
+ style: {
29150
+ position: "absolute",
29151
+ top: 0,
29152
+ left: 0,
29153
+ width: 120,
29154
+ height: 120,
29155
+ zIndex: 1e3
29156
+ }
29157
+ }
29068
29158
  );
29069
- return { cameraAnimatorProps, handleControlsChange };
29070
29159
  };
29071
29160
 
29072
29161
  // src/CadViewerContainer.tsx
29073
- import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
29162
+ import { jsx as jsx13, jsxs as jsxs3 } from "react/jsx-runtime";
29074
29163
  var RotationTracker = () => {
29075
29164
  const { camera } = useThree();
29165
+ const { setCameraRotation } = useCameraController();
29076
29166
  useFrame(() => {
29077
29167
  if (camera) {
29078
- window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation;
29168
+ setCameraRotation(camera.rotation);
29079
29169
  }
29080
29170
  });
29081
29171
  return null;
@@ -29091,14 +29181,20 @@ var CadViewerContainer = forwardRef2(
29091
29181
  onUserInteraction,
29092
29182
  onCameraControllerReady
29093
29183
  }, ref) => {
29094
- const [isInteractionEnabled, setIsInteractionEnabled] = useState8(
29184
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState9(
29095
29185
  !clickToInteractEnabled
29096
29186
  );
29097
- const saveTimeoutRef = useRef6(null);
29098
- const controlsRef = useRef6(null);
29099
- const cameraRef = useRef6(null);
29100
- const restoredOnceRef = useRef6(false);
29101
- const gridSectionSize = useMemo15(() => {
29187
+ const { mainCameraRef, handleControlsChange, controller } = useCameraController();
29188
+ const {
29189
+ handleCameraCreated,
29190
+ handleControlsChange: handleSessionControlsChange
29191
+ } = useCameraSession();
29192
+ useEffect16(() => {
29193
+ if (onCameraControllerReady) {
29194
+ onCameraControllerReady(controller);
29195
+ }
29196
+ }, [controller, onCameraControllerReady]);
29197
+ const gridSectionSize = useMemo13(() => {
29102
29198
  if (!boardDimensions) return 10;
29103
29199
  const width10 = boardDimensions.width ?? 0;
29104
29200
  const height10 = boardDimensions.height ?? 0;
@@ -29106,72 +29202,26 @@ var CadViewerContainer = forwardRef2(
29106
29202
  const desired = largest * 1.5;
29107
29203
  return desired > 10 ? desired : 10;
29108
29204
  }, [boardDimensions]);
29109
- const orbitTarget = useMemo15(() => {
29205
+ const orbitTarget = useMemo13(() => {
29110
29206
  if (!boardCenter) return void 0;
29111
29207
  return [boardCenter.x, boardCenter.y, 0];
29112
29208
  }, [boardCenter]);
29113
- const defaultTarget = useMemo15(() => {
29114
- if (orbitTarget) {
29115
- return new THREE14.Vector3(orbitTarget[0], orbitTarget[1], orbitTarget[2]);
29116
- }
29117
- return new THREE14.Vector3(0, 0, 0);
29118
- }, [orbitTarget]);
29119
- const { cameraAnimatorProps, handleControlsChange } = useCameraController({
29120
- defaultTarget,
29121
- initialCameraPosition,
29122
- onCameraControllerReady
29123
- });
29124
- return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
29125
- /* @__PURE__ */ jsx12(
29126
- "div",
29127
- {
29128
- style: {
29129
- position: "absolute",
29130
- top: 0,
29131
- left: 0,
29132
- width: 120,
29133
- height: 120
29134
- },
29135
- children: /* @__PURE__ */ jsx12(
29136
- Canvas,
29137
- {
29138
- camera: {
29139
- up: [0, 0, 1],
29140
- position: [1, 1, 1]
29141
- },
29142
- style: { zIndex: 10 },
29143
- children: /* @__PURE__ */ jsx12(CubeWithLabeledSides, {})
29144
- }
29145
- )
29146
- }
29147
- ),
29148
- /* @__PURE__ */ jsxs4(
29209
+ return /* @__PURE__ */ jsxs3("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
29210
+ /* @__PURE__ */ jsx13(OrientationCubeCanvas, {}),
29211
+ /* @__PURE__ */ jsxs3(
29149
29212
  Canvas,
29150
29213
  {
29151
29214
  ref,
29152
- scene: { up: new THREE14.Vector3(0, 0, 1) },
29215
+ scene: { up: new THREE15.Vector3(0, 0, 1) },
29153
29216
  camera: { up: [0, 0, 1], position: initialCameraPosition },
29154
29217
  onCreated: ({ camera }) => {
29155
- cameraRef.current = camera;
29156
- if (!restoredOnceRef.current && controlsRef.current) {
29157
- const restored = loadCameraFromSession(
29158
- cameraRef.current,
29159
- controlsRef.current
29160
- );
29161
- if (restored) restoredOnceRef.current = true;
29162
- }
29163
- if (controlsRef.current && !restoredOnceRef.current) {
29164
- setTimeout(() => {
29165
- if (cameraRef.current && controlsRef.current) {
29166
- saveCameraToSession(cameraRef.current, controlsRef.current);
29167
- }
29168
- }, 0);
29169
- }
29218
+ mainCameraRef.current = camera;
29219
+ handleCameraCreated(camera);
29170
29220
  },
29171
29221
  children: [
29172
- /* @__PURE__ */ jsx12(CameraAnimator, { ...cameraAnimatorProps }),
29173
- /* @__PURE__ */ jsx12(RotationTracker, {}),
29174
- isInteractionEnabled && /* @__PURE__ */ jsx12(
29222
+ /* @__PURE__ */ jsx13(CameraAnimatorWithContext, {}),
29223
+ /* @__PURE__ */ jsx13(RotationTracker, {}),
29224
+ isInteractionEnabled && /* @__PURE__ */ jsx13(
29175
29225
  OrbitControls,
29176
29226
  {
29177
29227
  autoRotate: !autoRotateDisabled,
@@ -29185,28 +29235,12 @@ var CadViewerContainer = forwardRef2(
29185
29235
  target: orbitTarget,
29186
29236
  onControlsChange: (controls) => {
29187
29237
  handleControlsChange(controls);
29188
- controlsRef.current = controls;
29189
- if (cameraRef.current && controlsRef.current && !restoredOnceRef.current) {
29190
- const restored = loadCameraFromSession(
29191
- cameraRef.current,
29192
- controlsRef.current
29193
- );
29194
- if (restored) {
29195
- restoredOnceRef.current = true;
29196
- return;
29197
- }
29198
- }
29199
- clearTimeout(saveTimeoutRef.current);
29200
- saveTimeoutRef.current = setTimeout(() => {
29201
- if (cameraRef.current && controlsRef.current) {
29202
- saveCameraToSession(cameraRef.current, controlsRef.current);
29203
- }
29204
- }, 150);
29238
+ handleSessionControlsChange();
29205
29239
  }
29206
29240
  }
29207
29241
  ),
29208
- /* @__PURE__ */ jsx12(Lights, {}),
29209
- /* @__PURE__ */ jsx12(
29242
+ /* @__PURE__ */ jsx13(Lights, {}),
29243
+ /* @__PURE__ */ jsx13(
29210
29244
  Grid,
29211
29245
  {
29212
29246
  rotation: [Math.PI / 2, 0, 0],
@@ -29220,7 +29254,7 @@ var CadViewerContainer = forwardRef2(
29220
29254
  ]
29221
29255
  }
29222
29256
  ),
29223
- /* @__PURE__ */ jsxs4(
29257
+ /* @__PURE__ */ jsxs3(
29224
29258
  "div",
29225
29259
  {
29226
29260
  style: {
@@ -29238,7 +29272,7 @@ var CadViewerContainer = forwardRef2(
29238
29272
  ]
29239
29273
  }
29240
29274
  ),
29241
- clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx12(
29275
+ clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx13(
29242
29276
  "button",
29243
29277
  {
29244
29278
  type: "button",
@@ -29257,7 +29291,7 @@ var CadViewerContainer = forwardRef2(
29257
29291
  alignItems: "center",
29258
29292
  justifyContent: "center"
29259
29293
  },
29260
- children: /* @__PURE__ */ jsx12(
29294
+ children: /* @__PURE__ */ jsx13(
29261
29295
  "div",
29262
29296
  {
29263
29297
  style: {
@@ -29280,9 +29314,9 @@ var CadViewerContainer = forwardRef2(
29280
29314
 
29281
29315
  // src/hooks/use-convert-children-to-soup.ts
29282
29316
  import { Circuit } from "@tscircuit/core";
29283
- import { useMemo as useMemo16 } from "react";
29317
+ import { useMemo as useMemo14 } from "react";
29284
29318
  var useConvertChildrenToCircuitJson = (children) => {
29285
- return useMemo16(() => {
29319
+ return useMemo14(() => {
29286
29320
  if (!children) return [];
29287
29321
  const circuit = new Circuit();
29288
29322
  circuit.add(children);
@@ -29292,11 +29326,11 @@ var useConvertChildrenToCircuitJson = (children) => {
29292
29326
  };
29293
29327
 
29294
29328
  // src/hooks/use-stls-from-geom.ts
29295
- import { useState as useState9, useEffect as useEffect17 } from "react";
29329
+ import { useState as useState10, useEffect as useEffect17 } from "react";
29296
29330
  import stlSerializer from "@jscad/stl-serializer";
29297
29331
  var useStlsFromGeom = (geom) => {
29298
- const [stls, setStls] = useState9([]);
29299
- const [loading, setLoading] = useState9(true);
29332
+ const [stls, setStls] = useState10([]);
29333
+ const [loading, setLoading] = useState10(true);
29300
29334
  useEffect17(() => {
29301
29335
  if (!geom) return;
29302
29336
  const generateStls = async () => {
@@ -29326,7 +29360,7 @@ var useStlsFromGeom = (geom) => {
29326
29360
  };
29327
29361
 
29328
29362
  // src/hooks/useBoardGeomBuilder.ts
29329
- import { useState as useState10, useEffect as useEffect18, useRef as useRef7 } from "react";
29363
+ import { useState as useState11, useEffect as useEffect18, useRef as useRef8 } from "react";
29330
29364
 
29331
29365
  // src/soup-to-3d/index.ts
29332
29366
  var import_primitives2 = __toESM(require_primitives(), 1);
@@ -31186,8 +31220,8 @@ var BoardGeomBuilder = class {
31186
31220
 
31187
31221
  // src/hooks/useBoardGeomBuilder.ts
31188
31222
  var useBoardGeomBuilder = (circuitJson) => {
31189
- const [boardGeom, setBoardGeom] = useState10(null);
31190
- const isProcessingRef = useRef7(false);
31223
+ const [boardGeom, setBoardGeom] = useState11(null);
31224
+ const isProcessingRef = useRef8(false);
31191
31225
  useEffect18(() => {
31192
31226
  let isCancelled = false;
31193
31227
  if (!circuitJson) {
@@ -31231,17 +31265,72 @@ var useBoardGeomBuilder = (circuitJson) => {
31231
31265
  };
31232
31266
 
31233
31267
  // src/three-components/Error3d.tsx
31234
- import { useState as useState11, useCallback as useCallback6, useEffect as useEffect19, useMemo as useMemo17 } from "react";
31235
- import * as THREE15 from "three";
31236
- import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
31268
+ import { useState as useState12, useCallback as useCallback8, useEffect as useEffect20, useMemo as useMemo16 } from "react";
31269
+
31270
+ // src/react-three/Text.tsx
31271
+ import { useEffect as useEffect19, useMemo as useMemo15 } from "react";
31272
+ import { Text as TroikaText2 } from "troika-three-text";
31273
+ var Text = ({
31274
+ children,
31275
+ parent,
31276
+ position,
31277
+ rotation: rotation2,
31278
+ scale: scale2,
31279
+ color,
31280
+ fontSize,
31281
+ anchorX,
31282
+ anchorY,
31283
+ depthOffset
31284
+ }) => {
31285
+ const { rootObject } = useThree();
31286
+ const mesh = useMemo15(() => {
31287
+ const textMesh = new TroikaText2();
31288
+ textMesh.text = children;
31289
+ if (position) textMesh.position.fromArray(position);
31290
+ if (rotation2) textMesh.rotation.fromArray(rotation2);
31291
+ if (scale2) textMesh.scale.fromArray(scale2);
31292
+ textMesh.color = color || "white";
31293
+ textMesh.fontSize = fontSize || 1;
31294
+ textMesh.anchorX = anchorX || "center";
31295
+ textMesh.anchorY = anchorY || "middle";
31296
+ textMesh.depthOffset = depthOffset || 0;
31297
+ textMesh.font = null;
31298
+ textMesh.sync();
31299
+ return textMesh;
31300
+ }, [
31301
+ children,
31302
+ position,
31303
+ rotation2,
31304
+ scale2,
31305
+ color,
31306
+ fontSize,
31307
+ anchorX,
31308
+ anchorY,
31309
+ depthOffset
31310
+ ]);
31311
+ useEffect19(() => {
31312
+ const parentObject = parent || rootObject;
31313
+ if (!parentObject || !mesh) return;
31314
+ parentObject.add(mesh);
31315
+ return () => {
31316
+ parentObject.remove(mesh);
31317
+ mesh.dispose();
31318
+ };
31319
+ }, [rootObject, parent, mesh]);
31320
+ return null;
31321
+ };
31322
+
31323
+ // src/three-components/Error3d.tsx
31324
+ import * as THREE16 from "three";
31325
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs4 } from "react/jsx-runtime";
31237
31326
  var Error3d = ({
31238
31327
  error,
31239
31328
  cad_component: cad_component2
31240
31329
  }) => {
31241
31330
  const { rootObject } = useThree();
31242
- const [isHovered, setIsHovered] = useState11(false);
31243
- const [hoverPosition, setHoverPosition] = useState11(null);
31244
- const handleHover = useCallback6((e) => {
31331
+ const [isHovered, setIsHovered] = useState12(false);
31332
+ const [hoverPosition, setHoverPosition] = useState12(null);
31333
+ const handleHover = useCallback8((e) => {
31245
31334
  if (e?.mousePosition) {
31246
31335
  setIsHovered(true);
31247
31336
  setHoverPosition(e.mousePosition);
@@ -31250,11 +31339,11 @@ var Error3d = ({
31250
31339
  setHoverPosition(null);
31251
31340
  }
31252
31341
  }, []);
31253
- const handleUnhover = useCallback6(() => {
31342
+ const handleUnhover = useCallback8(() => {
31254
31343
  setIsHovered(false);
31255
31344
  setHoverPosition(null);
31256
31345
  }, []);
31257
- const position = useMemo17(() => {
31346
+ const position = useMemo16(() => {
31258
31347
  if (cad_component2?.position) {
31259
31348
  const p = [
31260
31349
  cad_component2.position.x,
@@ -31265,20 +31354,20 @@ var Error3d = ({
31265
31354
  }
31266
31355
  return [0, 0, 0];
31267
31356
  }, [cad_component2]);
31268
- const group = useMemo17(() => {
31269
- const g = new THREE15.Group();
31357
+ const group = useMemo16(() => {
31358
+ const g = new THREE16.Group();
31270
31359
  g.position.fromArray(position);
31271
31360
  return g;
31272
31361
  }, [position]);
31273
- useEffect19(() => {
31362
+ useEffect20(() => {
31274
31363
  if (!rootObject) return;
31275
31364
  rootObject.add(group);
31276
31365
  return () => {
31277
31366
  rootObject.remove(group);
31278
31367
  };
31279
31368
  }, [rootObject, group]);
31280
- return /* @__PURE__ */ jsxs5(Fragment5, { children: [
31281
- /* @__PURE__ */ jsxs5(
31369
+ return /* @__PURE__ */ jsxs4(Fragment4, { children: [
31370
+ /* @__PURE__ */ jsxs4(
31282
31371
  ContainerWithTooltip_default,
31283
31372
  {
31284
31373
  isHovered,
@@ -31286,8 +31375,8 @@ var Error3d = ({
31286
31375
  onUnhover: handleUnhover,
31287
31376
  object: group,
31288
31377
  children: [
31289
- /* @__PURE__ */ jsx13(ErrorBox, { parent: group }),
31290
- /* @__PURE__ */ jsx13(
31378
+ /* @__PURE__ */ jsx14(ErrorBox, { parent: group }),
31379
+ /* @__PURE__ */ jsx14(
31291
31380
  Text,
31292
31381
  {
31293
31382
  parent: group,
@@ -31302,7 +31391,7 @@ var Error3d = ({
31302
31391
  ]
31303
31392
  }
31304
31393
  ),
31305
- isHovered && hoverPosition ? /* @__PURE__ */ jsx13(
31394
+ isHovered && hoverPosition ? /* @__PURE__ */ jsx14(
31306
31395
  Html,
31307
31396
  {
31308
31397
  position: hoverPosition,
@@ -31325,10 +31414,10 @@ var Error3d = ({
31325
31414
  ] });
31326
31415
  };
31327
31416
  var ErrorBox = ({ parent }) => {
31328
- const mesh = useMemo17(() => {
31329
- const m = new THREE15.Mesh(
31330
- new THREE15.BoxGeometry(0.5, 0.5, 0.5),
31331
- new THREE15.MeshStandardMaterial({
31417
+ const mesh = useMemo16(() => {
31418
+ const m = new THREE16.Mesh(
31419
+ new THREE16.BoxGeometry(0.5, 0.5, 0.5),
31420
+ new THREE16.MeshStandardMaterial({
31332
31421
  depthTest: false,
31333
31422
  transparent: true,
31334
31423
  color: "red",
@@ -31339,7 +31428,7 @@ var ErrorBox = ({ parent }) => {
31339
31428
  m.rotation.fromArray([Math.PI / 4, Math.PI / 4, 0]);
31340
31429
  return m;
31341
31430
  }, []);
31342
- useEffect19(() => {
31431
+ useEffect20(() => {
31343
31432
  parent.add(mesh);
31344
31433
  return () => {
31345
31434
  parent.remove(mesh);
@@ -31349,8 +31438,8 @@ var ErrorBox = ({ parent }) => {
31349
31438
  };
31350
31439
 
31351
31440
  // src/three-components/STLModel.tsx
31352
- import { useState as useState12, useEffect as useEffect20, useMemo as useMemo18 } from "react";
31353
- import * as THREE16 from "three";
31441
+ import { useState as useState13, useEffect as useEffect21, useMemo as useMemo17 } from "react";
31442
+ import * as THREE17 from "three";
31354
31443
  import { STLLoader } from "three-stdlib";
31355
31444
  function STLModel({
31356
31445
  stlUrl,
@@ -31360,8 +31449,8 @@ function STLModel({
31360
31449
  opacity = 1
31361
31450
  }) {
31362
31451
  const { rootObject } = useThree();
31363
- const [geom, setGeom] = useState12(null);
31364
- useEffect20(() => {
31452
+ const [geom, setGeom] = useState13(null);
31453
+ useEffect21(() => {
31365
31454
  const loader = new STLLoader();
31366
31455
  if (stlData) {
31367
31456
  try {
@@ -31379,16 +31468,16 @@ function STLModel({
31379
31468
  });
31380
31469
  }
31381
31470
  }, [stlUrl, stlData]);
31382
- const mesh = useMemo18(() => {
31471
+ const mesh = useMemo17(() => {
31383
31472
  if (!geom) return null;
31384
- const material = new THREE16.MeshStandardMaterial({
31385
- color: Array.isArray(color) ? new THREE16.Color(color[0], color[1], color[2]) : color,
31473
+ const material = new THREE17.MeshStandardMaterial({
31474
+ color: Array.isArray(color) ? new THREE17.Color(color[0], color[1], color[2]) : color,
31386
31475
  transparent: opacity !== 1,
31387
31476
  opacity
31388
31477
  });
31389
- return new THREE16.Mesh(geom, material);
31478
+ return new THREE17.Mesh(geom, material);
31390
31479
  }, [geom, color, opacity]);
31391
- useEffect20(() => {
31480
+ useEffect21(() => {
31392
31481
  if (!rootObject || !mesh) return;
31393
31482
  rootObject.add(mesh);
31394
31483
  return () => {
@@ -31405,7 +31494,7 @@ function STLModel({
31405
31494
  }
31406
31495
 
31407
31496
  // src/three-components/VisibleSTLModel.tsx
31408
- import { jsx as jsx14 } from "react/jsx-runtime";
31497
+ import { jsx as jsx15 } from "react/jsx-runtime";
31409
31498
  function VisibleSTLModel({
31410
31499
  stlData,
31411
31500
  color,
@@ -31428,7 +31517,7 @@ function VisibleSTLModel({
31428
31517
  if (!shouldShow) {
31429
31518
  return null;
31430
31519
  }
31431
- return /* @__PURE__ */ jsx14(STLModel, { stlData, color, opacity });
31520
+ return /* @__PURE__ */ jsx15(STLModel, { stlData, color, opacity });
31432
31521
  }
31433
31522
 
31434
31523
  // src/three-components/ThreeErrorBoundary.tsx
@@ -31537,7 +31626,7 @@ function addFauxBoardIfNeeded(circuitJson) {
31537
31626
  }
31538
31627
 
31539
31628
  // src/CadViewerJscad.tsx
31540
- import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
31629
+ import { jsx as jsx16, jsxs as jsxs5 } from "react/jsx-runtime";
31541
31630
  var CadViewerJscad = forwardRef3(
31542
31631
  ({
31543
31632
  soup,
@@ -31549,12 +31638,12 @@ var CadViewerJscad = forwardRef3(
31549
31638
  onCameraControllerReady
31550
31639
  }, ref) => {
31551
31640
  const childrenSoup = useConvertChildrenToCircuitJson(children);
31552
- const internalCircuitJson = useMemo19(() => {
31641
+ const internalCircuitJson = useMemo18(() => {
31553
31642
  const cj = soup ?? circuitJson;
31554
31643
  return addFauxBoardIfNeeded(cj ?? childrenSoup);
31555
31644
  }, [soup, circuitJson, childrenSoup]);
31556
31645
  const boardGeom = useBoardGeomBuilder(internalCircuitJson);
31557
- const initialCameraPosition = useMemo19(() => {
31646
+ const initialCameraPosition = useMemo18(() => {
31558
31647
  if (!internalCircuitJson) return [5, -5, 5];
31559
31648
  try {
31560
31649
  const board = su6(internalCircuitJson).pcb_board.list()[0];
@@ -31580,7 +31669,7 @@ var CadViewerJscad = forwardRef3(
31580
31669
  return [5, -5, 5];
31581
31670
  }
31582
31671
  }, [internalCircuitJson]);
31583
- const isFauxBoard = useMemo19(() => {
31672
+ const isFauxBoard = useMemo18(() => {
31584
31673
  if (!internalCircuitJson) return false;
31585
31674
  try {
31586
31675
  const board = su6(internalCircuitJson).pcb_board.list()[0];
@@ -31589,7 +31678,7 @@ var CadViewerJscad = forwardRef3(
31589
31678
  return false;
31590
31679
  }
31591
31680
  }, [internalCircuitJson]);
31592
- const boardDimensions = useMemo19(() => {
31681
+ const boardDimensions = useMemo18(() => {
31593
31682
  if (!internalCircuitJson) return void 0;
31594
31683
  try {
31595
31684
  const board = su6(internalCircuitJson).pcb_board.list()[0];
@@ -31600,7 +31689,7 @@ var CadViewerJscad = forwardRef3(
31600
31689
  return void 0;
31601
31690
  }
31602
31691
  }, [internalCircuitJson]);
31603
- const boardCenter = useMemo19(() => {
31692
+ const boardCenter = useMemo18(() => {
31604
31693
  if (!internalCircuitJson) return void 0;
31605
31694
  try {
31606
31695
  const board = su6(internalCircuitJson).pcb_board.list()[0];
@@ -31613,7 +31702,7 @@ var CadViewerJscad = forwardRef3(
31613
31702
  }, [internalCircuitJson]);
31614
31703
  const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
31615
31704
  const cad_components = su6(internalCircuitJson).cad_component.list();
31616
- return /* @__PURE__ */ jsxs6(
31705
+ return /* @__PURE__ */ jsxs5(
31617
31706
  CadViewerContainer,
31618
31707
  {
31619
31708
  ref,
@@ -31625,7 +31714,7 @@ var CadViewerJscad = forwardRef3(
31625
31714
  onUserInteraction,
31626
31715
  onCameraControllerReady,
31627
31716
  children: [
31628
- boardStls.map(({ stlData, color, layerType }, index2) => /* @__PURE__ */ jsx15(
31717
+ boardStls.map(({ stlData, color, layerType }, index2) => /* @__PURE__ */ jsx16(
31629
31718
  VisibleSTLModel,
31630
31719
  {
31631
31720
  stlData,
@@ -31635,11 +31724,11 @@ var CadViewerJscad = forwardRef3(
31635
31724
  },
31636
31725
  `board-${index2}`
31637
31726
  )),
31638
- cad_components.map((cad_component2) => /* @__PURE__ */ jsx15(
31727
+ cad_components.map((cad_component2) => /* @__PURE__ */ jsx16(
31639
31728
  ThreeErrorBoundary,
31640
31729
  {
31641
- fallback: ({ error }) => /* @__PURE__ */ jsx15(Error3d, { cad_component: cad_component2, error }),
31642
- children: /* @__PURE__ */ jsx15(
31730
+ fallback: ({ error }) => /* @__PURE__ */ jsx16(Error3d, { cad_component: cad_component2, error }),
31731
+ children: /* @__PURE__ */ jsx16(
31643
31732
  AnyCadComponent,
31644
31733
  {
31645
31734
  cad_component: cad_component2,
@@ -31658,22 +31747,22 @@ var CadViewerJscad = forwardRef3(
31658
31747
 
31659
31748
  // src/CadViewerManifold.tsx
31660
31749
  import { su as su15 } from "@tscircuit/circuit-json-util";
31661
- import { useEffect as useEffect22, useMemo as useMemo21, useState as useState15 } from "react";
31750
+ import { useEffect as useEffect23, useMemo as useMemo20, useState as useState16 } from "react";
31662
31751
 
31663
31752
  // src/hooks/useManifoldBoardBuilder.ts
31664
- import { useState as useState14, useEffect as useEffect21, useMemo as useMemo20, useRef as useRef8 } from "react";
31753
+ import { useState as useState15, useEffect as useEffect22, useMemo as useMemo19, useRef as useRef9 } from "react";
31665
31754
  import { su as su14 } from "@tscircuit/circuit-json-util";
31666
- import * as THREE24 from "three";
31755
+ import * as THREE25 from "three";
31667
31756
 
31668
31757
  // src/utils/manifold-mesh-to-three-geometry.ts
31669
- import * as THREE17 from "three";
31758
+ import * as THREE18 from "three";
31670
31759
  function manifoldMeshToThreeGeometry(manifoldMesh) {
31671
- const geometry = new THREE17.BufferGeometry();
31760
+ const geometry = new THREE18.BufferGeometry();
31672
31761
  geometry.setAttribute(
31673
31762
  "position",
31674
- new THREE17.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
31763
+ new THREE18.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
31675
31764
  );
31676
- geometry.setIndex(new THREE17.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
31765
+ geometry.setIndex(new THREE18.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
31677
31766
  if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
31678
31767
  for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
31679
31768
  const start = manifoldMesh.runIndex[i];
@@ -31687,7 +31776,7 @@ function manifoldMeshToThreeGeometry(manifoldMesh) {
31687
31776
  }
31688
31777
 
31689
31778
  // src/utils/trace-texture.ts
31690
- import * as THREE18 from "three";
31779
+ import * as THREE19 from "three";
31691
31780
  import { su as su7 } from "@tscircuit/circuit-json-util";
31692
31781
  function isWireRoutePoint(point2) {
31693
31782
  return point2 && point2.route_type === "wire" && typeof point2.layer === "string" && typeof point2.width === "number";
@@ -31770,10 +31859,10 @@ function createTraceTextureForLayer({
31770
31859
  }
31771
31860
  });
31772
31861
  ctx.globalCompositeOperation = "source-over";
31773
- const texture = new THREE18.CanvasTexture(canvas);
31862
+ const texture = new THREE19.CanvasTexture(canvas);
31774
31863
  texture.generateMipmaps = true;
31775
- texture.minFilter = THREE18.LinearMipmapLinearFilter;
31776
- texture.magFilter = THREE18.LinearFilter;
31864
+ texture.minFilter = THREE19.LinearMipmapLinearFilter;
31865
+ texture.magFilter = THREE19.LinearFilter;
31777
31866
  texture.anisotropy = 16;
31778
31867
  texture.needsUpdate = true;
31779
31868
  return texture;
@@ -31781,7 +31870,7 @@ function createTraceTextureForLayer({
31781
31870
 
31782
31871
  // src/utils/silkscreen-texture.ts
31783
31872
  var import_text2 = __toESM(require_text(), 1);
31784
- import * as THREE19 from "three";
31873
+ import * as THREE20 from "three";
31785
31874
  import { su as su8 } from "@tscircuit/circuit-json-util";
31786
31875
  function createSilkscreenTextureForLayer({
31787
31876
  layer,
@@ -32039,10 +32128,10 @@ function createSilkscreenTextureForLayer({
32039
32128
  ctx.stroke();
32040
32129
  });
32041
32130
  });
32042
- const texture = new THREE19.CanvasTexture(canvas);
32131
+ const texture = new THREE20.CanvasTexture(canvas);
32043
32132
  texture.generateMipmaps = true;
32044
- texture.minFilter = THREE19.LinearMipmapLinearFilter;
32045
- texture.magFilter = THREE19.LinearFilter;
32133
+ texture.minFilter = THREE20.LinearMipmapLinearFilter;
32134
+ texture.magFilter = THREE20.LinearFilter;
32046
32135
  texture.anisotropy = 16;
32047
32136
  texture.needsUpdate = true;
32048
32137
  return texture;
@@ -32226,8 +32315,8 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
32226
32315
 
32227
32316
  // src/utils/manifold/process-plated-holes.ts
32228
32317
  import { su as su10 } from "@tscircuit/circuit-json-util";
32229
- import * as THREE20 from "three";
32230
- var COPPER_COLOR = new THREE20.Color(...colors.copper);
32318
+ import * as THREE21 from "three";
32319
+ var COPPER_COLOR = new THREE21.Color(...colors.copper);
32231
32320
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
32232
32321
  function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
32233
32322
  const platedHoleBoardDrills = [];
@@ -32545,7 +32634,7 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
32545
32634
 
32546
32635
  // src/utils/manifold/process-vias.ts
32547
32636
  import { su as su11 } from "@tscircuit/circuit-json-util";
32548
- import * as THREE21 from "three";
32637
+ import * as THREE22 from "three";
32549
32638
 
32550
32639
  // src/utils/via-geoms.ts
32551
32640
  function createViaCopper({
@@ -32578,7 +32667,7 @@ function createViaCopper({
32578
32667
  }
32579
32668
 
32580
32669
  // src/utils/manifold/process-vias.ts
32581
- var COPPER_COLOR2 = new THREE21.Color(...colors.copper);
32670
+ var COPPER_COLOR2 = new THREE22.Color(...colors.copper);
32582
32671
  function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
32583
32672
  const viaBoardDrills = [];
32584
32673
  const pcbVias = su11(circuitJson).pcb_via.list();
@@ -32631,8 +32720,8 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
32631
32720
 
32632
32721
  // src/utils/manifold/process-smt-pads.ts
32633
32722
  import { su as su12 } from "@tscircuit/circuit-json-util";
32634
- import * as THREE22 from "three";
32635
- var COPPER_COLOR3 = new THREE22.Color(...colors.copper);
32723
+ import * as THREE23 from "three";
32724
+ var COPPER_COLOR3 = new THREE23.Color(...colors.copper);
32636
32725
  function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
32637
32726
  const smtPadGeoms = [];
32638
32727
  const smtPads = su12(circuitJson).pcb_smtpad.list();
@@ -32728,7 +32817,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
32728
32817
  }
32729
32818
 
32730
32819
  // src/utils/manifold/process-copper-pours.ts
32731
- import * as THREE23 from "three";
32820
+ import * as THREE24 from "three";
32732
32821
  var arePointsClockwise4 = (points) => {
32733
32822
  let area = 0;
32734
32823
  for (let i = 0; i < points.length; i++) {
@@ -32888,7 +32977,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
32888
32977
  }
32889
32978
  const covered = pour.covered_with_solder_mask !== false;
32890
32979
  const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4GreenSolderWithMask : colors.copper;
32891
- const pourColor = new THREE23.Color(...pourColorArr);
32980
+ const pourColor = new THREE24.Color(...pourColorArr);
32892
32981
  const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
32893
32982
  copperPourGeoms.push({
32894
32983
  key: `coppour-${pour.pcb_copper_pour_id}`,
@@ -33001,21 +33090,21 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
33001
33090
 
33002
33091
  // src/hooks/useManifoldBoardBuilder.ts
33003
33092
  var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
33004
- const [geoms, setGeoms] = useState14(null);
33005
- const [textures, setTextures] = useState14(null);
33006
- const [pcbThickness, setPcbThickness] = useState14(null);
33007
- const [error, setError] = useState14(null);
33008
- const [isLoading, setIsLoading] = useState14(true);
33009
- const manifoldInstancesForCleanup = useRef8([]);
33010
- const boardData = useMemo20(() => {
33093
+ const [geoms, setGeoms] = useState15(null);
33094
+ const [textures, setTextures] = useState15(null);
33095
+ const [pcbThickness, setPcbThickness] = useState15(null);
33096
+ const [error, setError] = useState15(null);
33097
+ const [isLoading, setIsLoading] = useState15(true);
33098
+ const manifoldInstancesForCleanup = useRef9([]);
33099
+ const boardData = useMemo19(() => {
33011
33100
  const boards = su14(circuitJson).pcb_board.list();
33012
33101
  return boards.length > 0 ? boards[0] : null;
33013
33102
  }, [circuitJson]);
33014
- const isFauxBoard = useMemo20(() => {
33103
+ const isFauxBoard = useMemo19(() => {
33015
33104
  const boards = su14(circuitJson).pcb_board.list();
33016
33105
  return boards.length > 0 && boards[0].pcb_board_id === "faux-board";
33017
33106
  }, [circuitJson]);
33018
- useEffect21(() => {
33107
+ useEffect22(() => {
33019
33108
  if (!manifoldJSModule || !boardData) {
33020
33109
  setGeoms(null);
33021
33110
  setTextures(null);
@@ -33146,7 +33235,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
33146
33235
  {
33147
33236
  key: "plated-holes-union",
33148
33237
  geometry: cutPlatedGeom,
33149
- color: new THREE24.Color(
33238
+ color: new THREE25.Color(
33150
33239
  colors.copper[0],
33151
33240
  colors.copper[1],
33152
33241
  colors.copper[2]
@@ -33176,7 +33265,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
33176
33265
  const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Green;
33177
33266
  currentGeoms.board = {
33178
33267
  geometry: finalBoardGeom,
33179
- color: new THREE24.Color(
33268
+ color: new THREE25.Color(
33180
33269
  matColorArray[0],
33181
33270
  matColorArray[1],
33182
33271
  matColorArray[2]
@@ -33265,11 +33354,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
33265
33354
  };
33266
33355
 
33267
33356
  // src/utils/manifold/create-three-geometry-meshes.ts
33268
- import * as THREE26 from "three";
33357
+ import * as THREE27 from "three";
33269
33358
 
33270
33359
  // src/utils/create-board-material.ts
33271
- import * as THREE25 from "three";
33272
- var DEFAULT_SIDE = THREE25.DoubleSide;
33360
+ import * as THREE26 from "three";
33361
+ var DEFAULT_SIDE = THREE26.DoubleSide;
33273
33362
  var createBoardMaterial = ({
33274
33363
  material,
33275
33364
  color,
@@ -33277,7 +33366,7 @@ var createBoardMaterial = ({
33277
33366
  isFaux = false
33278
33367
  }) => {
33279
33368
  if (material === "fr4") {
33280
- return new THREE25.MeshPhysicalMaterial({
33369
+ return new THREE26.MeshPhysicalMaterial({
33281
33370
  color,
33282
33371
  side,
33283
33372
  metalness: 0,
@@ -33291,7 +33380,7 @@ var createBoardMaterial = ({
33291
33380
  flatShading: true
33292
33381
  });
33293
33382
  }
33294
- return new THREE25.MeshStandardMaterial({
33383
+ return new THREE26.MeshStandardMaterial({
33295
33384
  color,
33296
33385
  side,
33297
33386
  flatShading: true,
@@ -33307,12 +33396,12 @@ function createGeometryMeshes(geoms) {
33307
33396
  const meshes = [];
33308
33397
  if (!geoms) return meshes;
33309
33398
  if (geoms.board && geoms.board.geometry) {
33310
- const mesh = new THREE26.Mesh(
33399
+ const mesh = new THREE27.Mesh(
33311
33400
  geoms.board.geometry,
33312
33401
  createBoardMaterial({
33313
33402
  material: geoms.board.material,
33314
33403
  color: geoms.board.color,
33315
- side: THREE26.DoubleSide,
33404
+ side: THREE27.DoubleSide,
33316
33405
  isFaux: geoms.board.isFaux
33317
33406
  })
33318
33407
  );
@@ -33322,11 +33411,11 @@ function createGeometryMeshes(geoms) {
33322
33411
  const createMeshesFromArray = (geomArray) => {
33323
33412
  if (geomArray) {
33324
33413
  geomArray.forEach((comp) => {
33325
- const mesh = new THREE26.Mesh(
33414
+ const mesh = new THREE27.Mesh(
33326
33415
  comp.geometry,
33327
- new THREE26.MeshStandardMaterial({
33416
+ new THREE27.MeshStandardMaterial({
33328
33417
  color: comp.color,
33329
- side: THREE26.DoubleSide,
33418
+ side: THREE27.DoubleSide,
33330
33419
  flatShading: true
33331
33420
  // Consistent with board
33332
33421
  })
@@ -33344,21 +33433,21 @@ function createGeometryMeshes(geoms) {
33344
33433
  }
33345
33434
 
33346
33435
  // src/utils/manifold/create-three-texture-meshes.ts
33347
- import * as THREE27 from "three";
33436
+ import * as THREE28 from "three";
33348
33437
  function createTextureMeshes(textures, boardData, pcbThickness) {
33349
33438
  const meshes = [];
33350
33439
  if (!textures || !boardData || pcbThickness === null) return meshes;
33351
33440
  const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix) => {
33352
33441
  if (!texture) return null;
33353
- const planeGeom = new THREE27.PlaneGeometry(boardData.width, boardData.height);
33354
- const material = new THREE27.MeshBasicMaterial({
33442
+ const planeGeom = new THREE28.PlaneGeometry(boardData.width, boardData.height);
33443
+ const material = new THREE28.MeshBasicMaterial({
33355
33444
  map: texture,
33356
33445
  transparent: true,
33357
- side: THREE27.DoubleSide,
33446
+ side: THREE28.DoubleSide,
33358
33447
  depthWrite: false
33359
33448
  // Important for layers to avoid z-fighting issues with board itself
33360
33449
  });
33361
- const mesh = new THREE27.Mesh(planeGeom, material);
33450
+ const mesh = new THREE28.Mesh(planeGeom, material);
33362
33451
  mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
33363
33452
  if (isBottomLayer) {
33364
33453
  mesh.rotation.set(Math.PI, 0, 0);
@@ -33401,14 +33490,14 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
33401
33490
  }
33402
33491
 
33403
33492
  // src/CadViewerManifold.tsx
33404
- import { jsx as jsx16, jsxs as jsxs7 } from "react/jsx-runtime";
33493
+ import { jsx as jsx17, jsxs as jsxs6 } from "react/jsx-runtime";
33405
33494
  var BoardMeshes = ({
33406
33495
  geometryMeshes,
33407
33496
  textureMeshes
33408
33497
  }) => {
33409
33498
  const { rootObject } = useThree();
33410
33499
  const { visibility } = useLayerVisibility();
33411
- useEffect22(() => {
33500
+ useEffect23(() => {
33412
33501
  if (!rootObject) return;
33413
33502
  geometryMeshes.forEach((mesh) => {
33414
33503
  let shouldShow = true;
@@ -33471,13 +33560,13 @@ var CadViewerManifold = ({
33471
33560
  onCameraControllerReady
33472
33561
  }) => {
33473
33562
  const childrenCircuitJson = useConvertChildrenToCircuitJson(children);
33474
- const circuitJson = useMemo21(() => {
33563
+ const circuitJson = useMemo20(() => {
33475
33564
  const rawCircuitJson = circuitJsonProp ?? childrenCircuitJson;
33476
33565
  return addFauxBoardIfNeeded(rawCircuitJson);
33477
33566
  }, [circuitJsonProp, childrenCircuitJson]);
33478
- const [manifoldJSModule, setManifoldJSModule] = useState15(null);
33479
- const [manifoldLoadingError, setManifoldLoadingError] = useState15(null);
33480
- useEffect22(() => {
33567
+ const [manifoldJSModule, setManifoldJSModule] = useState16(null);
33568
+ const [manifoldLoadingError, setManifoldLoadingError] = useState16(null);
33569
+ useEffect23(() => {
33481
33570
  if (window.ManifoldModule && typeof window.ManifoldModule === "object" && window.ManifoldModule.setup) {
33482
33571
  setManifoldJSModule(window.ManifoldModule);
33483
33572
  return;
@@ -33547,27 +33636,27 @@ try {
33547
33636
  isLoading: builderIsLoading,
33548
33637
  boardData
33549
33638
  } = useManifoldBoardBuilder(manifoldJSModule, circuitJson);
33550
- const geometryMeshes = useMemo21(() => createGeometryMeshes(geoms), [geoms]);
33551
- const textureMeshes = useMemo21(
33639
+ const geometryMeshes = useMemo20(() => createGeometryMeshes(geoms), [geoms]);
33640
+ const textureMeshes = useMemo20(
33552
33641
  () => createTextureMeshes(textures, boardData, pcbThickness),
33553
33642
  [textures, boardData, pcbThickness]
33554
33643
  );
33555
- const cadComponents = useMemo21(
33644
+ const cadComponents = useMemo20(
33556
33645
  () => su15(circuitJson).cad_component.list(),
33557
33646
  [circuitJson]
33558
33647
  );
33559
- const boardDimensions = useMemo21(() => {
33648
+ const boardDimensions = useMemo20(() => {
33560
33649
  if (!boardData) return void 0;
33561
33650
  const { width: width10 = 0, height: height10 = 0 } = boardData;
33562
33651
  return { width: width10, height: height10 };
33563
33652
  }, [boardData]);
33564
- const boardCenter = useMemo21(() => {
33653
+ const boardCenter = useMemo20(() => {
33565
33654
  if (!boardData) return void 0;
33566
33655
  const { center } = boardData;
33567
33656
  if (!center) return void 0;
33568
33657
  return { x: center.x, y: center.y };
33569
33658
  }, [boardData]);
33570
- const initialCameraPosition = useMemo21(() => {
33659
+ const initialCameraPosition = useMemo20(() => {
33571
33660
  if (!boardData) return [5, -5, 5];
33572
33661
  const { width: width10 = 0, height: height10 = 0 } = boardData;
33573
33662
  const safeWidth = Math.max(width10, 1);
@@ -33583,7 +33672,7 @@ try {
33583
33672
  ];
33584
33673
  }, [boardData]);
33585
33674
  if (manifoldLoadingError) {
33586
- return /* @__PURE__ */ jsxs7(
33675
+ return /* @__PURE__ */ jsxs6(
33587
33676
  "div",
33588
33677
  {
33589
33678
  style: {
@@ -33600,10 +33689,10 @@ try {
33600
33689
  );
33601
33690
  }
33602
33691
  if (!manifoldJSModule) {
33603
- return /* @__PURE__ */ jsx16("div", { style: { padding: "1em" }, children: "Loading Manifold module..." });
33692
+ return /* @__PURE__ */ jsx17("div", { style: { padding: "1em" }, children: "Loading Manifold module..." });
33604
33693
  }
33605
33694
  if (builderError) {
33606
- return /* @__PURE__ */ jsxs7(
33695
+ return /* @__PURE__ */ jsxs6(
33607
33696
  "div",
33608
33697
  {
33609
33698
  style: {
@@ -33620,9 +33709,9 @@ try {
33620
33709
  );
33621
33710
  }
33622
33711
  if (builderIsLoading) {
33623
- return /* @__PURE__ */ jsx16("div", { style: { padding: "1em" }, children: "Processing board geometry..." });
33712
+ return /* @__PURE__ */ jsx17("div", { style: { padding: "1em" }, children: "Processing board geometry..." });
33624
33713
  }
33625
- return /* @__PURE__ */ jsxs7(
33714
+ return /* @__PURE__ */ jsxs6(
33626
33715
  CadViewerContainer,
33627
33716
  {
33628
33717
  initialCameraPosition,
@@ -33633,18 +33722,18 @@ try {
33633
33722
  onUserInteraction,
33634
33723
  onCameraControllerReady,
33635
33724
  children: [
33636
- /* @__PURE__ */ jsx16(
33725
+ /* @__PURE__ */ jsx17(
33637
33726
  BoardMeshes,
33638
33727
  {
33639
33728
  geometryMeshes,
33640
33729
  textureMeshes
33641
33730
  }
33642
33731
  ),
33643
- cadComponents.map((cad_component2) => /* @__PURE__ */ jsx16(
33732
+ cadComponents.map((cad_component2) => /* @__PURE__ */ jsx17(
33644
33733
  ThreeErrorBoundary,
33645
33734
  {
33646
- fallback: ({ error }) => /* @__PURE__ */ jsx16(Error3d, { cad_component: cad_component2, error }),
33647
- children: /* @__PURE__ */ jsx16(
33735
+ fallback: ({ error }) => /* @__PURE__ */ jsx17(Error3d, { cad_component: cad_component2, error }),
33736
+ children: /* @__PURE__ */ jsx17(
33648
33737
  AnyCadComponent,
33649
33738
  {
33650
33739
  cad_component: cad_component2,
@@ -33661,24 +33750,24 @@ try {
33661
33750
  var CadViewerManifold_default = CadViewerManifold;
33662
33751
 
33663
33752
  // src/hooks/useContextMenu.ts
33664
- import { useState as useState16, useCallback as useCallback8, useRef as useRef9, useEffect as useEffect23 } from "react";
33753
+ import { useState as useState17, useCallback as useCallback10, useRef as useRef10, useEffect as useEffect24 } from "react";
33665
33754
  var useContextMenu = ({ containerRef }) => {
33666
- const [menuVisible, setMenuVisible] = useState16(false);
33667
- const [menuPos, setMenuPos] = useState16({
33755
+ const [menuVisible, setMenuVisible] = useState17(false);
33756
+ const [menuPos, setMenuPos] = useState17({
33668
33757
  x: 0,
33669
33758
  y: 0
33670
33759
  });
33671
- const menuRef = useRef9(null);
33672
- const interactionOriginPosRef = useRef9(null);
33673
- const longPressTimeoutRef = useRef9(null);
33674
- const ignoreNextContextMenuRef = useRef9(false);
33760
+ const menuRef = useRef10(null);
33761
+ const interactionOriginPosRef = useRef10(null);
33762
+ const longPressTimeoutRef = useRef10(null);
33763
+ const ignoreNextContextMenuRef = useRef10(false);
33675
33764
  const clearLongPressTimeout = () => {
33676
33765
  if (longPressTimeoutRef.current !== null) {
33677
33766
  clearTimeout(longPressTimeoutRef.current);
33678
33767
  longPressTimeoutRef.current = null;
33679
33768
  }
33680
33769
  };
33681
- const handleContextMenu = useCallback8(
33770
+ const handleContextMenu = useCallback10(
33682
33771
  (e) => {
33683
33772
  e.preventDefault();
33684
33773
  const eventX = typeof e.clientX === "number" ? e.clientX : 0;
@@ -33704,7 +33793,7 @@ var useContextMenu = ({ containerRef }) => {
33704
33793
  },
33705
33794
  [setMenuPos, setMenuVisible]
33706
33795
  );
33707
- const handleTouchStart = useCallback8(
33796
+ const handleTouchStart = useCallback10(
33708
33797
  (e) => {
33709
33798
  if (e.touches.length === 1) {
33710
33799
  const touch = e.touches[0];
@@ -33737,7 +33826,7 @@ var useContextMenu = ({ containerRef }) => {
33737
33826
  },
33738
33827
  [containerRef]
33739
33828
  );
33740
- const handleTouchMove = useCallback8((e) => {
33829
+ const handleTouchMove = useCallback10((e) => {
33741
33830
  if (!interactionOriginPosRef.current || e.touches.length !== 1) {
33742
33831
  return;
33743
33832
  }
@@ -33755,7 +33844,7 @@ var useContextMenu = ({ containerRef }) => {
33755
33844
  clearLongPressTimeout();
33756
33845
  }
33757
33846
  }, []);
33758
- const handleTouchEnd = useCallback8(() => {
33847
+ const handleTouchEnd = useCallback10(() => {
33759
33848
  clearLongPressTimeout();
33760
33849
  setTimeout(() => {
33761
33850
  if (interactionOriginPosRef.current) {
@@ -33763,7 +33852,7 @@ var useContextMenu = ({ containerRef }) => {
33763
33852
  }
33764
33853
  }, 0);
33765
33854
  }, []);
33766
- const handleClickAway = useCallback8((e) => {
33855
+ const handleClickAway = useCallback10((e) => {
33767
33856
  const target = e.target;
33768
33857
  if (menuRef.current && menuRef.current.contains(target)) {
33769
33858
  return;
@@ -33776,7 +33865,7 @@ var useContextMenu = ({ containerRef }) => {
33776
33865
  }
33777
33866
  setMenuVisible(false);
33778
33867
  }, []);
33779
- useEffect23(() => {
33868
+ useEffect24(() => {
33780
33869
  if (menuVisible) {
33781
33870
  document.addEventListener("mousedown", handleClickAway);
33782
33871
  document.addEventListener("touchstart", handleClickAway);
@@ -33810,7 +33899,7 @@ var useContextMenu = ({ containerRef }) => {
33810
33899
  };
33811
33900
 
33812
33901
  // src/hooks/useCameraPreset.ts
33813
- import { useCallback as useCallback9 } from "react";
33902
+ import { useCallback as useCallback11 } from "react";
33814
33903
  function useCameraPreset({
33815
33904
  setAutoRotate,
33816
33905
  setAutoRotateUserToggled,
@@ -33820,7 +33909,7 @@ function useCameraPreset({
33820
33909
  isAnimatingRef,
33821
33910
  lastPresetSelectTime
33822
33911
  }) {
33823
- const handleCameraPresetSelect = useCallback9(
33912
+ const handleCameraPresetSelect = useCallback11(
33824
33913
  (preset) => {
33825
33914
  setAutoRotate(false);
33826
33915
  setAutoRotateUserToggled(true);
@@ -33850,10 +33939,10 @@ function useCameraPreset({
33850
33939
  }
33851
33940
 
33852
33941
  // src/hooks/useGlobalDownloadGltf.ts
33853
- import { useCallback as useCallback10 } from "react";
33942
+ import { useCallback as useCallback12 } from "react";
33854
33943
  import { GLTFExporter } from "three-stdlib";
33855
33944
  var useGlobalDownloadGltf = () => {
33856
- return useCallback10(() => {
33945
+ return useCallback12(() => {
33857
33946
  const root = window.__TSCIRCUIT_THREE_OBJECT;
33858
33947
  if (!root) return;
33859
33948
  const exporter = new GLTFExporter();
@@ -33879,7 +33968,7 @@ var useGlobalDownloadGltf = () => {
33879
33968
  };
33880
33969
 
33881
33970
  // src/components/ContextMenu.tsx
33882
- import { useState as useState32 } from "react";
33971
+ import { useState as useState33 } from "react";
33883
33972
 
33884
33973
  // node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs
33885
33974
  import * as React43 from "react";
@@ -33934,7 +34023,7 @@ function useComposedRefs(...refs) {
33934
34023
 
33935
34024
  // node_modules/@radix-ui/react-context/dist/index.mjs
33936
34025
  import * as React13 from "react";
33937
- import { jsx as jsx17 } from "react/jsx-runtime";
34026
+ import { jsx as jsx18 } from "react/jsx-runtime";
33938
34027
  function createContextScope(scopeName, createContextScopeDeps = []) {
33939
34028
  let defaultContexts = [];
33940
34029
  function createContext32(rootComponentName, defaultContext) {
@@ -33945,7 +34034,7 @@ function createContextScope(scopeName, createContextScopeDeps = []) {
33945
34034
  const { scope, children, ...context } = props;
33946
34035
  const Context = scope?.[scopeName]?.[index2] || BaseContext;
33947
34036
  const value = React13.useMemo(() => context, Object.values(context));
33948
- return /* @__PURE__ */ jsx17(Context.Provider, { value, children });
34037
+ return /* @__PURE__ */ jsx18(Context.Provider, { value, children });
33949
34038
  };
33950
34039
  Provider.displayName = rootComponentName + "Provider";
33951
34040
  function useContext22(consumerName, scope) {
@@ -34075,7 +34164,7 @@ import * as ReactDOM2 from "react-dom";
34075
34164
 
34076
34165
  // node_modules/@radix-ui/react-slot/dist/index.mjs
34077
34166
  import * as React16 from "react";
34078
- import { Fragment as Fragment23, jsx as jsx18 } from "react/jsx-runtime";
34167
+ import { Fragment as Fragment23, jsx as jsx19 } from "react/jsx-runtime";
34079
34168
  // @__NO_SIDE_EFFECTS__
34080
34169
  function createSlot(ownerName) {
34081
34170
  const SlotClone = /* @__PURE__ */ createSlotClone(ownerName);
@@ -34093,9 +34182,9 @@ function createSlot(ownerName) {
34093
34182
  return child;
34094
34183
  }
34095
34184
  });
34096
- return /* @__PURE__ */ jsx18(SlotClone, { ...slotProps, ref: forwardedRef, children: React16.isValidElement(newElement) ? React16.cloneElement(newElement, void 0, newChildren) : null });
34185
+ return /* @__PURE__ */ jsx19(SlotClone, { ...slotProps, ref: forwardedRef, children: React16.isValidElement(newElement) ? React16.cloneElement(newElement, void 0, newChildren) : null });
34097
34186
  }
34098
- return /* @__PURE__ */ jsx18(SlotClone, { ...slotProps, ref: forwardedRef, children });
34187
+ return /* @__PURE__ */ jsx19(SlotClone, { ...slotProps, ref: forwardedRef, children });
34099
34188
  });
34100
34189
  Slot2.displayName = `${ownerName}.Slot`;
34101
34190
  return Slot2;
@@ -34160,7 +34249,7 @@ function getElementRef(element) {
34160
34249
  }
34161
34250
 
34162
34251
  // node_modules/@radix-ui/react-primitive/dist/index.mjs
34163
- import { jsx as jsx19 } from "react/jsx-runtime";
34252
+ import { jsx as jsx20 } from "react/jsx-runtime";
34164
34253
  var NODES = [
34165
34254
  "a",
34166
34255
  "button",
@@ -34188,7 +34277,7 @@ var Primitive = NODES.reduce((primitive, node) => {
34188
34277
  if (typeof window !== "undefined") {
34189
34278
  window[Symbol.for("radix-ui")] = true;
34190
34279
  }
34191
- return /* @__PURE__ */ jsx19(Comp, { ...primitiveProps, ref: forwardedRef });
34280
+ return /* @__PURE__ */ jsx20(Comp, { ...primitiveProps, ref: forwardedRef });
34192
34281
  });
34193
34282
  Node2.displayName = `Primitive.${node}`;
34194
34283
  return { ...primitive, [node]: Node2 };
@@ -34202,7 +34291,7 @@ import * as React42 from "react";
34202
34291
 
34203
34292
  // node_modules/@radix-ui/react-collection/dist/index.mjs
34204
34293
  import React18 from "react";
34205
- import { jsx as jsx20 } from "react/jsx-runtime";
34294
+ import { jsx as jsx21 } from "react/jsx-runtime";
34206
34295
  import React23 from "react";
34207
34296
  import { jsx as jsx22 } from "react/jsx-runtime";
34208
34297
  function createCollection(name) {
@@ -34216,7 +34305,7 @@ function createCollection(name) {
34216
34305
  const { scope, children } = props;
34217
34306
  const ref = React18.useRef(null);
34218
34307
  const itemMap = React18.useRef(/* @__PURE__ */ new Map()).current;
34219
- return /* @__PURE__ */ jsx20(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children });
34308
+ return /* @__PURE__ */ jsx21(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children });
34220
34309
  };
34221
34310
  CollectionProvider.displayName = PROVIDER_NAME;
34222
34311
  const COLLECTION_SLOT_NAME = name + "CollectionSlot";
@@ -34226,7 +34315,7 @@ function createCollection(name) {
34226
34315
  const { scope, children } = props;
34227
34316
  const context = useCollectionContext(COLLECTION_SLOT_NAME, scope);
34228
34317
  const composedRefs = useComposedRefs(forwardedRef, context.collectionRef);
34229
- return /* @__PURE__ */ jsx20(CollectionSlotImpl, { ref: composedRefs, children });
34318
+ return /* @__PURE__ */ jsx21(CollectionSlotImpl, { ref: composedRefs, children });
34230
34319
  }
34231
34320
  );
34232
34321
  CollectionSlot.displayName = COLLECTION_SLOT_NAME;
@@ -34243,7 +34332,7 @@ function createCollection(name) {
34243
34332
  context.itemMap.set(ref, { ref, ...itemData });
34244
34333
  return () => void context.itemMap.delete(ref);
34245
34334
  });
34246
- return /* @__PURE__ */ jsx20(CollectionItemSlotImpl, { ...{ [ITEM_DATA_ATTR]: "" }, ref: composedRefs, children });
34335
+ return /* @__PURE__ */ jsx21(CollectionItemSlotImpl, { ...{ [ITEM_DATA_ATTR]: "" }, ref: composedRefs, children });
34247
34336
  }
34248
34337
  );
34249
34338
  CollectionItemSlot.displayName = ITEM_SLOT_NAME;
@@ -34270,7 +34359,7 @@ function createCollection(name) {
34270
34359
 
34271
34360
  // node_modules/@radix-ui/react-direction/dist/index.mjs
34272
34361
  import * as React19 from "react";
34273
- import { jsx as jsx21 } from "react/jsx-runtime";
34362
+ import { jsx as jsx23 } from "react/jsx-runtime";
34274
34363
  var DirectionContext = React19.createContext(void 0);
34275
34364
  function useDirection(localDir) {
34276
34365
  const globalDir = React19.useContext(DirectionContext);
@@ -34306,7 +34395,7 @@ function useEscapeKeydown(onEscapeKeyDownProp, ownerDocument = globalThis?.docum
34306
34395
  }
34307
34396
 
34308
34397
  // node_modules/@radix-ui/react-dismissable-layer/dist/index.mjs
34309
- import { jsx as jsx23 } from "react/jsx-runtime";
34398
+ import { jsx as jsx24 } from "react/jsx-runtime";
34310
34399
  var DISMISSABLE_LAYER_NAME = "DismissableLayer";
34311
34400
  var CONTEXT_UPDATE = "dismissableLayer.update";
34312
34401
  var POINTER_DOWN_OUTSIDE = "dismissableLayer.pointerDownOutside";
@@ -34394,7 +34483,7 @@ var DismissableLayer = React24.forwardRef(
34394
34483
  document.addEventListener(CONTEXT_UPDATE, handleUpdate);
34395
34484
  return () => document.removeEventListener(CONTEXT_UPDATE, handleUpdate);
34396
34485
  }, []);
34397
- return /* @__PURE__ */ jsx23(
34486
+ return /* @__PURE__ */ jsx24(
34398
34487
  Primitive.div,
34399
34488
  {
34400
34489
  ...layerProps,
@@ -34428,7 +34517,7 @@ var DismissableLayerBranch = React24.forwardRef((props, forwardedRef) => {
34428
34517
  };
34429
34518
  }
34430
34519
  }, [context.branches]);
34431
- return /* @__PURE__ */ jsx23(Primitive.div, { ...props, ref: composedRefs });
34520
+ return /* @__PURE__ */ jsx24(Primitive.div, { ...props, ref: composedRefs });
34432
34521
  });
34433
34522
  DismissableLayerBranch.displayName = BRANCH_NAME;
34434
34523
  function usePointerDownOutside(onPointerDownOutside, ownerDocument = globalThis?.document) {
@@ -34540,7 +34629,7 @@ function createFocusGuard() {
34540
34629
 
34541
34630
  // node_modules/@radix-ui/react-focus-scope/dist/index.mjs
34542
34631
  import * as React26 from "react";
34543
- import { jsx as jsx24 } from "react/jsx-runtime";
34632
+ import { jsx as jsx25 } from "react/jsx-runtime";
34544
34633
  var AUTOFOCUS_ON_MOUNT = "focusScope.autoFocusOnMount";
34545
34634
  var AUTOFOCUS_ON_UNMOUNT = "focusScope.autoFocusOnUnmount";
34546
34635
  var EVENT_OPTIONS = { bubbles: false, cancelable: true };
@@ -34659,7 +34748,7 @@ var FocusScope = React26.forwardRef((props, forwardedRef) => {
34659
34748
  },
34660
34749
  [loop, trapped, focusScope.paused]
34661
34750
  );
34662
- return /* @__PURE__ */ jsx24(Primitive.div, { tabIndex: -1, ...scopeProps, ref: composedRefs, onKeyDown: handleKeyDown });
34751
+ return /* @__PURE__ */ jsx25(Primitive.div, { tabIndex: -1, ...scopeProps, ref: composedRefs, onKeyDown: handleKeyDown });
34663
34752
  });
34664
34753
  FocusScope.displayName = FOCUS_SCOPE_NAME;
34665
34754
  function focusFirst(candidates, { select = false } = {}) {
@@ -36649,11 +36738,11 @@ var arrow3 = (options, deps) => ({
36649
36738
 
36650
36739
  // node_modules/@radix-ui/react-arrow/dist/index.mjs
36651
36740
  import * as React29 from "react";
36652
- import { jsx as jsx25 } from "react/jsx-runtime";
36741
+ import { jsx as jsx26 } from "react/jsx-runtime";
36653
36742
  var NAME = "Arrow";
36654
36743
  var Arrow = React29.forwardRef((props, forwardedRef) => {
36655
36744
  const { children, width: width10 = 10, height: height10 = 5, ...arrowProps } = props;
36656
- return /* @__PURE__ */ jsx25(
36745
+ return /* @__PURE__ */ jsx26(
36657
36746
  Primitive.svg,
36658
36747
  {
36659
36748
  ...arrowProps,
@@ -36662,7 +36751,7 @@ var Arrow = React29.forwardRef((props, forwardedRef) => {
36662
36751
  height: height10,
36663
36752
  viewBox: "0 0 30 10",
36664
36753
  preserveAspectRatio: "none",
36665
- children: props.asChild ? children : /* @__PURE__ */ jsx25("polygon", { points: "0,0 30,0 15,10" })
36754
+ children: props.asChild ? children : /* @__PURE__ */ jsx26("polygon", { points: "0,0 30,0 15,10" })
36666
36755
  }
36667
36756
  );
36668
36757
  });
@@ -36707,14 +36796,14 @@ function useSize(element) {
36707
36796
  }
36708
36797
 
36709
36798
  // node_modules/@radix-ui/react-popper/dist/index.mjs
36710
- import { jsx as jsx26 } from "react/jsx-runtime";
36799
+ import { jsx as jsx27 } from "react/jsx-runtime";
36711
36800
  var POPPER_NAME = "Popper";
36712
36801
  var [createPopperContext, createPopperScope] = createContextScope(POPPER_NAME);
36713
36802
  var [PopperProvider, usePopperContext] = createPopperContext(POPPER_NAME);
36714
36803
  var Popper = (props) => {
36715
36804
  const { __scopePopper, children } = props;
36716
36805
  const [anchor, setAnchor] = React31.useState(null);
36717
- return /* @__PURE__ */ jsx26(PopperProvider, { scope: __scopePopper, anchor, onAnchorChange: setAnchor, children });
36806
+ return /* @__PURE__ */ jsx27(PopperProvider, { scope: __scopePopper, anchor, onAnchorChange: setAnchor, children });
36718
36807
  };
36719
36808
  Popper.displayName = POPPER_NAME;
36720
36809
  var ANCHOR_NAME = "PopperAnchor";
@@ -36732,7 +36821,7 @@ var PopperAnchor = React31.forwardRef(
36732
36821
  context.onAnchorChange(anchorRef.current);
36733
36822
  }
36734
36823
  });
36735
- return virtualRef ? null : /* @__PURE__ */ jsx26(Primitive.div, { ...anchorProps, ref: composedRefs });
36824
+ return virtualRef ? null : /* @__PURE__ */ jsx27(Primitive.div, { ...anchorProps, ref: composedRefs });
36736
36825
  }
36737
36826
  );
36738
36827
  PopperAnchor.displayName = ANCHOR_NAME;
@@ -36825,7 +36914,7 @@ var PopperContent = React31.forwardRef(
36825
36914
  useLayoutEffect2(() => {
36826
36915
  if (content) setContentZIndex(window.getComputedStyle(content).zIndex);
36827
36916
  }, [content]);
36828
- return /* @__PURE__ */ jsx26(
36917
+ return /* @__PURE__ */ jsx27(
36829
36918
  "div",
36830
36919
  {
36831
36920
  ref: refs.setFloating,
@@ -36849,7 +36938,7 @@ var PopperContent = React31.forwardRef(
36849
36938
  }
36850
36939
  },
36851
36940
  dir: props.dir,
36852
- children: /* @__PURE__ */ jsx26(
36941
+ children: /* @__PURE__ */ jsx27(
36853
36942
  PopperContentProvider,
36854
36943
  {
36855
36944
  scope: __scopePopper,
@@ -36858,7 +36947,7 @@ var PopperContent = React31.forwardRef(
36858
36947
  arrowX,
36859
36948
  arrowY,
36860
36949
  shouldHideArrow: cannotCenterArrow,
36861
- children: /* @__PURE__ */ jsx26(
36950
+ children: /* @__PURE__ */ jsx27(
36862
36951
  Primitive.div,
36863
36952
  {
36864
36953
  "data-side": placedSide,
@@ -36895,7 +36984,7 @@ var PopperArrow = React31.forwardRef(function PopperArrow2(props, forwardedRef)
36895
36984
  // we have to use an extra wrapper because `ResizeObserver` (used by `useSize`)
36896
36985
  // doesn't report size as we'd expect on SVG elements.
36897
36986
  // it reports their bounding box which is effectively the largest path inside the SVG.
36898
- /* @__PURE__ */ jsx26(
36987
+ /* @__PURE__ */ jsx27(
36899
36988
  "span",
36900
36989
  {
36901
36990
  ref: contentContext.onArrowChange,
@@ -36918,7 +37007,7 @@ var PopperArrow = React31.forwardRef(function PopperArrow2(props, forwardedRef)
36918
37007
  }[contentContext.placedSide],
36919
37008
  visibility: contentContext.shouldHideArrow ? "hidden" : void 0
36920
37009
  },
36921
- children: /* @__PURE__ */ jsx26(
37010
+ children: /* @__PURE__ */ jsx27(
36922
37011
  Root,
36923
37012
  {
36924
37013
  ...arrowProps,
@@ -36981,14 +37070,14 @@ var Arrow2 = PopperArrow;
36981
37070
  // node_modules/@radix-ui/react-portal/dist/index.mjs
36982
37071
  import * as React32 from "react";
36983
37072
  import ReactDOM4 from "react-dom";
36984
- import { jsx as jsx27 } from "react/jsx-runtime";
37073
+ import { jsx as jsx28 } from "react/jsx-runtime";
36985
37074
  var PORTAL_NAME = "Portal";
36986
37075
  var Portal = React32.forwardRef((props, forwardedRef) => {
36987
37076
  const { container: containerProp, ...portalProps } = props;
36988
37077
  const [mounted, setMounted] = React32.useState(false);
36989
37078
  useLayoutEffect2(() => setMounted(true), []);
36990
37079
  const container = containerProp || mounted && globalThis?.document?.body;
36991
- return container ? ReactDOM4.createPortal(/* @__PURE__ */ jsx27(Primitive.div, { ...portalProps, ref: forwardedRef }), container) : null;
37080
+ return container ? ReactDOM4.createPortal(/* @__PURE__ */ jsx28(Primitive.div, { ...portalProps, ref: forwardedRef }), container) : null;
36992
37081
  });
36993
37082
  Portal.displayName = PORTAL_NAME;
36994
37083
 
@@ -37120,7 +37209,7 @@ function getElementRef2(element) {
37120
37209
 
37121
37210
  // node_modules/@radix-ui/react-roving-focus/dist/index.mjs
37122
37211
  import * as React34 from "react";
37123
- import { jsx as jsx28 } from "react/jsx-runtime";
37212
+ import { jsx as jsx29 } from "react/jsx-runtime";
37124
37213
  var ENTRY_FOCUS = "rovingFocusGroup.onEntryFocus";
37125
37214
  var EVENT_OPTIONS2 = { bubbles: false, cancelable: true };
37126
37215
  var GROUP_NAME = "RovingFocusGroup";
@@ -37132,7 +37221,7 @@ var [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContext
37132
37221
  var [RovingFocusProvider, useRovingFocusContext] = createRovingFocusGroupContext(GROUP_NAME);
37133
37222
  var RovingFocusGroup = React34.forwardRef(
37134
37223
  (props, forwardedRef) => {
37135
- return /* @__PURE__ */ jsx28(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx28(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx28(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) });
37224
+ return /* @__PURE__ */ jsx29(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx29(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx29(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) });
37136
37225
  }
37137
37226
  );
37138
37227
  RovingFocusGroup.displayName = GROUP_NAME;
@@ -37170,7 +37259,7 @@ var RovingFocusGroupImpl = React34.forwardRef((props, forwardedRef) => {
37170
37259
  return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);
37171
37260
  }
37172
37261
  }, [handleEntryFocus]);
37173
- return /* @__PURE__ */ jsx28(
37262
+ return /* @__PURE__ */ jsx29(
37174
37263
  RovingFocusProvider,
37175
37264
  {
37176
37265
  scope: __scopeRovingFocusGroup,
@@ -37191,7 +37280,7 @@ var RovingFocusGroupImpl = React34.forwardRef((props, forwardedRef) => {
37191
37280
  () => setFocusableItemsCount((prevCount) => prevCount - 1),
37192
37281
  []
37193
37282
  ),
37194
- children: /* @__PURE__ */ jsx28(
37283
+ children: /* @__PURE__ */ jsx29(
37195
37284
  Primitive.div,
37196
37285
  {
37197
37286
  tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,
@@ -37249,14 +37338,14 @@ var RovingFocusGroupItem = React34.forwardRef(
37249
37338
  return () => onFocusableItemRemove();
37250
37339
  }
37251
37340
  }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);
37252
- return /* @__PURE__ */ jsx28(
37341
+ return /* @__PURE__ */ jsx29(
37253
37342
  Collection.ItemSlot,
37254
37343
  {
37255
37344
  scope: __scopeRovingFocusGroup,
37256
37345
  id,
37257
37346
  focusable,
37258
37347
  active,
37259
- children: /* @__PURE__ */ jsx28(
37348
+ children: /* @__PURE__ */ jsx29(
37260
37349
  Primitive.span,
37261
37350
  {
37262
37351
  tabIndex: isCurrentTabStop ? 0 : -1,
@@ -37507,9 +37596,9 @@ function assignRef(ref, value) {
37507
37596
  }
37508
37597
 
37509
37598
  // node_modules/use-callback-ref/dist/es2015/useRef.js
37510
- import { useState as useState27 } from "react";
37599
+ import { useState as useState28 } from "react";
37511
37600
  function useCallbackRef2(initialValue, callback) {
37512
- var ref = useState27(function() {
37601
+ var ref = useState28(function() {
37513
37602
  return {
37514
37603
  // value
37515
37604
  value: initialValue,
@@ -38167,7 +38256,7 @@ ReactRemoveScroll.classNames = RemoveScroll.classNames;
38167
38256
  var Combination_default = ReactRemoveScroll;
38168
38257
 
38169
38258
  // node_modules/@radix-ui/react-menu/dist/index.mjs
38170
- import { jsx as jsx29 } from "react/jsx-runtime";
38259
+ import { jsx as jsx30 } from "react/jsx-runtime";
38171
38260
  var SELECTION_KEYS = ["Enter", " "];
38172
38261
  var FIRST_KEYS = ["ArrowDown", "PageUp", "Home"];
38173
38262
  var LAST_KEYS = ["ArrowUp", "PageDown", "End"];
@@ -38212,7 +38301,7 @@ var Menu = (props) => {
38212
38301
  document.removeEventListener("pointermove", handlePointer, { capture: true });
38213
38302
  };
38214
38303
  }, []);
38215
- return /* @__PURE__ */ jsx29(Root2, { ...popperScope, children: /* @__PURE__ */ jsx29(
38304
+ return /* @__PURE__ */ jsx30(Root2, { ...popperScope, children: /* @__PURE__ */ jsx30(
38216
38305
  MenuProvider,
38217
38306
  {
38218
38307
  scope: __scopeMenu,
@@ -38220,7 +38309,7 @@ var Menu = (props) => {
38220
38309
  onOpenChange: handleOpenChange,
38221
38310
  content,
38222
38311
  onContentChange: setContent,
38223
- children: /* @__PURE__ */ jsx29(
38312
+ children: /* @__PURE__ */ jsx30(
38224
38313
  MenuRootProvider,
38225
38314
  {
38226
38315
  scope: __scopeMenu,
@@ -38240,7 +38329,7 @@ var MenuAnchor = React42.forwardRef(
38240
38329
  (props, forwardedRef) => {
38241
38330
  const { __scopeMenu, ...anchorProps } = props;
38242
38331
  const popperScope = usePopperScope(__scopeMenu);
38243
- return /* @__PURE__ */ jsx29(Anchor, { ...popperScope, ...anchorProps, ref: forwardedRef });
38332
+ return /* @__PURE__ */ jsx30(Anchor, { ...popperScope, ...anchorProps, ref: forwardedRef });
38244
38333
  }
38245
38334
  );
38246
38335
  MenuAnchor.displayName = ANCHOR_NAME2;
@@ -38251,7 +38340,7 @@ var [PortalProvider, usePortalContext] = createMenuContext(PORTAL_NAME2, {
38251
38340
  var MenuPortal = (props) => {
38252
38341
  const { __scopeMenu, forceMount, children, container } = props;
38253
38342
  const context = useMenuContext(PORTAL_NAME2, __scopeMenu);
38254
- return /* @__PURE__ */ jsx29(PortalProvider, { scope: __scopeMenu, forceMount, children: /* @__PURE__ */ jsx29(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx29(Portal, { asChild: true, container, children }) }) });
38343
+ return /* @__PURE__ */ jsx30(PortalProvider, { scope: __scopeMenu, forceMount, children: /* @__PURE__ */ jsx30(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx30(Portal, { asChild: true, container, children }) }) });
38255
38344
  };
38256
38345
  MenuPortal.displayName = PORTAL_NAME2;
38257
38346
  var CONTENT_NAME2 = "MenuContent";
@@ -38262,7 +38351,7 @@ var MenuContent = React42.forwardRef(
38262
38351
  const { forceMount = portalContext.forceMount, ...contentProps } = props;
38263
38352
  const context = useMenuContext(CONTENT_NAME2, props.__scopeMenu);
38264
38353
  const rootContext = useMenuRootContext(CONTENT_NAME2, props.__scopeMenu);
38265
- return /* @__PURE__ */ jsx29(Collection2.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx29(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx29(Collection2.Slot, { scope: props.__scopeMenu, children: rootContext.modal ? /* @__PURE__ */ jsx29(MenuRootContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx29(MenuRootContentNonModal, { ...contentProps, ref: forwardedRef }) }) }) });
38354
+ return /* @__PURE__ */ jsx30(Collection2.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx30(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx30(Collection2.Slot, { scope: props.__scopeMenu, children: rootContext.modal ? /* @__PURE__ */ jsx30(MenuRootContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx30(MenuRootContentNonModal, { ...contentProps, ref: forwardedRef }) }) }) });
38266
38355
  }
38267
38356
  );
38268
38357
  var MenuRootContentModal = React42.forwardRef(
@@ -38274,7 +38363,7 @@ var MenuRootContentModal = React42.forwardRef(
38274
38363
  const content = ref.current;
38275
38364
  if (content) return hideOthers(content);
38276
38365
  }, []);
38277
- return /* @__PURE__ */ jsx29(
38366
+ return /* @__PURE__ */ jsx30(
38278
38367
  MenuContentImpl,
38279
38368
  {
38280
38369
  ...props,
@@ -38294,7 +38383,7 @@ var MenuRootContentModal = React42.forwardRef(
38294
38383
  );
38295
38384
  var MenuRootContentNonModal = React42.forwardRef((props, forwardedRef) => {
38296
38385
  const context = useMenuContext(CONTENT_NAME2, props.__scopeMenu);
38297
- return /* @__PURE__ */ jsx29(
38386
+ return /* @__PURE__ */ jsx30(
38298
38387
  MenuContentImpl,
38299
38388
  {
38300
38389
  ...props,
@@ -38366,7 +38455,7 @@ var MenuContentImpl = React42.forwardRef(
38366
38455
  const isMovingTowards = pointerDirRef.current === pointerGraceIntentRef.current?.side;
38367
38456
  return isMovingTowards && isPointerInGraceArea(event, pointerGraceIntentRef.current?.area);
38368
38457
  }, []);
38369
- return /* @__PURE__ */ jsx29(
38458
+ return /* @__PURE__ */ jsx30(
38370
38459
  MenuContentProvider,
38371
38460
  {
38372
38461
  scope: __scopeMenu,
@@ -38395,7 +38484,7 @@ var MenuContentImpl = React42.forwardRef(
38395
38484
  onPointerGraceIntentChange: React42.useCallback((intent) => {
38396
38485
  pointerGraceIntentRef.current = intent;
38397
38486
  }, []),
38398
- children: /* @__PURE__ */ jsx29(ScrollLockWrapper, { ...scrollLockWrapperProps, children: /* @__PURE__ */ jsx29(
38487
+ children: /* @__PURE__ */ jsx30(ScrollLockWrapper, { ...scrollLockWrapperProps, children: /* @__PURE__ */ jsx30(
38399
38488
  FocusScope,
38400
38489
  {
38401
38490
  asChild: true,
@@ -38405,7 +38494,7 @@ var MenuContentImpl = React42.forwardRef(
38405
38494
  contentRef.current?.focus({ preventScroll: true });
38406
38495
  }),
38407
38496
  onUnmountAutoFocus: onCloseAutoFocus,
38408
- children: /* @__PURE__ */ jsx29(
38497
+ children: /* @__PURE__ */ jsx30(
38409
38498
  DismissableLayer,
38410
38499
  {
38411
38500
  asChild: true,
@@ -38415,7 +38504,7 @@ var MenuContentImpl = React42.forwardRef(
38415
38504
  onFocusOutside,
38416
38505
  onInteractOutside,
38417
38506
  onDismiss,
38418
- children: /* @__PURE__ */ jsx29(
38507
+ children: /* @__PURE__ */ jsx30(
38419
38508
  Root3,
38420
38509
  {
38421
38510
  asChild: true,
@@ -38429,7 +38518,7 @@ var MenuContentImpl = React42.forwardRef(
38429
38518
  if (!rootContext.isUsingKeyboardRef.current) event.preventDefault();
38430
38519
  }),
38431
38520
  preventScrollOnEntryFocus: true,
38432
- children: /* @__PURE__ */ jsx29(
38521
+ children: /* @__PURE__ */ jsx30(
38433
38522
  Content,
38434
38523
  {
38435
38524
  role: "menu",
@@ -38494,7 +38583,7 @@ var GROUP_NAME2 = "MenuGroup";
38494
38583
  var MenuGroup = React42.forwardRef(
38495
38584
  (props, forwardedRef) => {
38496
38585
  const { __scopeMenu, ...groupProps } = props;
38497
- return /* @__PURE__ */ jsx29(Primitive.div, { role: "group", ...groupProps, ref: forwardedRef });
38586
+ return /* @__PURE__ */ jsx30(Primitive.div, { role: "group", ...groupProps, ref: forwardedRef });
38498
38587
  }
38499
38588
  );
38500
38589
  MenuGroup.displayName = GROUP_NAME2;
@@ -38502,7 +38591,7 @@ var LABEL_NAME = "MenuLabel";
38502
38591
  var MenuLabel = React42.forwardRef(
38503
38592
  (props, forwardedRef) => {
38504
38593
  const { __scopeMenu, ...labelProps } = props;
38505
- return /* @__PURE__ */ jsx29(Primitive.div, { ...labelProps, ref: forwardedRef });
38594
+ return /* @__PURE__ */ jsx30(Primitive.div, { ...labelProps, ref: forwardedRef });
38506
38595
  }
38507
38596
  );
38508
38597
  MenuLabel.displayName = LABEL_NAME;
@@ -38529,7 +38618,7 @@ var MenuItem = React42.forwardRef(
38529
38618
  }
38530
38619
  }
38531
38620
  };
38532
- return /* @__PURE__ */ jsx29(
38621
+ return /* @__PURE__ */ jsx30(
38533
38622
  MenuItemImpl,
38534
38623
  {
38535
38624
  ...itemProps,
@@ -38571,13 +38660,13 @@ var MenuItemImpl = React42.forwardRef(
38571
38660
  setTextContent((menuItem.textContent ?? "").trim());
38572
38661
  }
38573
38662
  }, [itemProps.children]);
38574
- return /* @__PURE__ */ jsx29(
38663
+ return /* @__PURE__ */ jsx30(
38575
38664
  Collection2.ItemSlot,
38576
38665
  {
38577
38666
  scope: __scopeMenu,
38578
38667
  disabled,
38579
38668
  textValue: textValue ?? textContent,
38580
- children: /* @__PURE__ */ jsx29(Item, { asChild: true, ...rovingFocusGroupScope, focusable: !disabled, children: /* @__PURE__ */ jsx29(
38669
+ children: /* @__PURE__ */ jsx30(Item, { asChild: true, ...rovingFocusGroupScope, focusable: !disabled, children: /* @__PURE__ */ jsx30(
38581
38670
  Primitive.div,
38582
38671
  {
38583
38672
  role: "menuitem",
@@ -38616,7 +38705,7 @@ var CHECKBOX_ITEM_NAME = "MenuCheckboxItem";
38616
38705
  var MenuCheckboxItem = React42.forwardRef(
38617
38706
  (props, forwardedRef) => {
38618
38707
  const { checked = false, onCheckedChange, ...checkboxItemProps } = props;
38619
- return /* @__PURE__ */ jsx29(ItemIndicatorProvider, { scope: props.__scopeMenu, checked, children: /* @__PURE__ */ jsx29(
38708
+ return /* @__PURE__ */ jsx30(ItemIndicatorProvider, { scope: props.__scopeMenu, checked, children: /* @__PURE__ */ jsx30(
38620
38709
  MenuItem,
38621
38710
  {
38622
38711
  role: "menuitemcheckbox",
@@ -38644,7 +38733,7 @@ var MenuRadioGroup = React42.forwardRef(
38644
38733
  (props, forwardedRef) => {
38645
38734
  const { value, onValueChange, ...groupProps } = props;
38646
38735
  const handleValueChange = useCallbackRef(onValueChange);
38647
- return /* @__PURE__ */ jsx29(RadioGroupProvider, { scope: props.__scopeMenu, value, onValueChange: handleValueChange, children: /* @__PURE__ */ jsx29(MenuGroup, { ...groupProps, ref: forwardedRef }) });
38736
+ return /* @__PURE__ */ jsx30(RadioGroupProvider, { scope: props.__scopeMenu, value, onValueChange: handleValueChange, children: /* @__PURE__ */ jsx30(MenuGroup, { ...groupProps, ref: forwardedRef }) });
38648
38737
  }
38649
38738
  );
38650
38739
  MenuRadioGroup.displayName = RADIO_GROUP_NAME;
@@ -38654,7 +38743,7 @@ var MenuRadioItem = React42.forwardRef(
38654
38743
  const { value, ...radioItemProps } = props;
38655
38744
  const context = useRadioGroupContext(RADIO_ITEM_NAME, props.__scopeMenu);
38656
38745
  const checked = value === context.value;
38657
- return /* @__PURE__ */ jsx29(ItemIndicatorProvider, { scope: props.__scopeMenu, checked, children: /* @__PURE__ */ jsx29(
38746
+ return /* @__PURE__ */ jsx30(ItemIndicatorProvider, { scope: props.__scopeMenu, checked, children: /* @__PURE__ */ jsx30(
38658
38747
  MenuItem,
38659
38748
  {
38660
38749
  role: "menuitemradio",
@@ -38681,11 +38770,11 @@ var MenuItemIndicator = React42.forwardRef(
38681
38770
  (props, forwardedRef) => {
38682
38771
  const { __scopeMenu, forceMount, ...itemIndicatorProps } = props;
38683
38772
  const indicatorContext = useItemIndicatorContext(ITEM_INDICATOR_NAME, __scopeMenu);
38684
- return /* @__PURE__ */ jsx29(
38773
+ return /* @__PURE__ */ jsx30(
38685
38774
  Presence,
38686
38775
  {
38687
38776
  present: forceMount || isIndeterminate(indicatorContext.checked) || indicatorContext.checked === true,
38688
- children: /* @__PURE__ */ jsx29(
38777
+ children: /* @__PURE__ */ jsx30(
38689
38778
  Primitive.span,
38690
38779
  {
38691
38780
  ...itemIndicatorProps,
@@ -38702,7 +38791,7 @@ var SEPARATOR_NAME = "MenuSeparator";
38702
38791
  var MenuSeparator = React42.forwardRef(
38703
38792
  (props, forwardedRef) => {
38704
38793
  const { __scopeMenu, ...separatorProps } = props;
38705
- return /* @__PURE__ */ jsx29(
38794
+ return /* @__PURE__ */ jsx30(
38706
38795
  Primitive.div,
38707
38796
  {
38708
38797
  role: "separator",
@@ -38719,7 +38808,7 @@ var MenuArrow = React42.forwardRef(
38719
38808
  (props, forwardedRef) => {
38720
38809
  const { __scopeMenu, ...arrowProps } = props;
38721
38810
  const popperScope = usePopperScope(__scopeMenu);
38722
- return /* @__PURE__ */ jsx29(Arrow2, { ...popperScope, ...arrowProps, ref: forwardedRef });
38811
+ return /* @__PURE__ */ jsx30(Arrow2, { ...popperScope, ...arrowProps, ref: forwardedRef });
38723
38812
  }
38724
38813
  );
38725
38814
  MenuArrow.displayName = ARROW_NAME2;
@@ -38736,7 +38825,7 @@ var MenuSub = (props) => {
38736
38825
  if (parentMenuContext.open === false) handleOpenChange(false);
38737
38826
  return () => handleOpenChange(false);
38738
38827
  }, [parentMenuContext.open, handleOpenChange]);
38739
- return /* @__PURE__ */ jsx29(Root2, { ...popperScope, children: /* @__PURE__ */ jsx29(
38828
+ return /* @__PURE__ */ jsx30(Root2, { ...popperScope, children: /* @__PURE__ */ jsx30(
38740
38829
  MenuProvider,
38741
38830
  {
38742
38831
  scope: __scopeMenu,
@@ -38744,7 +38833,7 @@ var MenuSub = (props) => {
38744
38833
  onOpenChange: handleOpenChange,
38745
38834
  content,
38746
38835
  onContentChange: setContent,
38747
- children: /* @__PURE__ */ jsx29(
38836
+ children: /* @__PURE__ */ jsx30(
38748
38837
  MenuSubProvider,
38749
38838
  {
38750
38839
  scope: __scopeMenu,
@@ -38781,7 +38870,7 @@ var MenuSubTrigger = React42.forwardRef(
38781
38870
  onPointerGraceIntentChange(null);
38782
38871
  };
38783
38872
  }, [pointerGraceTimerRef, onPointerGraceIntentChange]);
38784
- return /* @__PURE__ */ jsx29(MenuAnchor, { asChild: true, ...scope, children: /* @__PURE__ */ jsx29(
38873
+ return /* @__PURE__ */ jsx30(MenuAnchor, { asChild: true, ...scope, children: /* @__PURE__ */ jsx30(
38785
38874
  MenuItemImpl,
38786
38875
  {
38787
38876
  id: subContext.triggerId,
@@ -38870,7 +38959,7 @@ var MenuSubContent = React42.forwardRef(
38870
38959
  const subContext = useMenuSubContext(SUB_CONTENT_NAME, props.__scopeMenu);
38871
38960
  const ref = React42.useRef(null);
38872
38961
  const composedRefs = useComposedRefs(forwardedRef, ref);
38873
- return /* @__PURE__ */ jsx29(Collection2.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx29(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx29(Collection2.Slot, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx29(
38962
+ return /* @__PURE__ */ jsx30(Collection2.Provider, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx30(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx30(Collection2.Slot, { scope: props.__scopeMenu, children: /* @__PURE__ */ jsx30(
38874
38963
  MenuContentImpl,
38875
38964
  {
38876
38965
  id: subContext.contentId,
@@ -38981,7 +39070,7 @@ var SubTrigger = MenuSubTrigger;
38981
39070
  var SubContent = MenuSubContent;
38982
39071
 
38983
39072
  // node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs
38984
- import { jsx as jsx30 } from "react/jsx-runtime";
39073
+ import { jsx as jsx31 } from "react/jsx-runtime";
38985
39074
  var DROPDOWN_MENU_NAME = "DropdownMenu";
38986
39075
  var [createDropdownMenuContext, createDropdownMenuScope] = createContextScope(
38987
39076
  DROPDOWN_MENU_NAME,
@@ -39007,7 +39096,7 @@ var DropdownMenu = (props) => {
39007
39096
  onChange: onOpenChange,
39008
39097
  caller: DROPDOWN_MENU_NAME
39009
39098
  });
39010
- return /* @__PURE__ */ jsx30(
39099
+ return /* @__PURE__ */ jsx31(
39011
39100
  DropdownMenuProvider,
39012
39101
  {
39013
39102
  scope: __scopeDropdownMenu,
@@ -39018,7 +39107,7 @@ var DropdownMenu = (props) => {
39018
39107
  onOpenChange: setOpen,
39019
39108
  onOpenToggle: React43.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
39020
39109
  modal,
39021
- children: /* @__PURE__ */ jsx30(Root32, { ...menuScope, open, onOpenChange: setOpen, dir, modal, children })
39110
+ children: /* @__PURE__ */ jsx31(Root32, { ...menuScope, open, onOpenChange: setOpen, dir, modal, children })
39022
39111
  }
39023
39112
  );
39024
39113
  };
@@ -39029,7 +39118,7 @@ var DropdownMenuTrigger = React43.forwardRef(
39029
39118
  const { __scopeDropdownMenu, disabled = false, ...triggerProps } = props;
39030
39119
  const context = useDropdownMenuContext(TRIGGER_NAME, __scopeDropdownMenu);
39031
39120
  const menuScope = useMenuScope(__scopeDropdownMenu);
39032
- return /* @__PURE__ */ jsx30(Anchor2, { asChild: true, ...menuScope, children: /* @__PURE__ */ jsx30(
39121
+ return /* @__PURE__ */ jsx31(Anchor2, { asChild: true, ...menuScope, children: /* @__PURE__ */ jsx31(
39033
39122
  Primitive.button,
39034
39123
  {
39035
39124
  type: "button",
@@ -39063,7 +39152,7 @@ var PORTAL_NAME3 = "DropdownMenuPortal";
39063
39152
  var DropdownMenuPortal = (props) => {
39064
39153
  const { __scopeDropdownMenu, ...portalProps } = props;
39065
39154
  const menuScope = useMenuScope(__scopeDropdownMenu);
39066
- return /* @__PURE__ */ jsx30(Portal2, { ...menuScope, ...portalProps });
39155
+ return /* @__PURE__ */ jsx31(Portal2, { ...menuScope, ...portalProps });
39067
39156
  };
39068
39157
  DropdownMenuPortal.displayName = PORTAL_NAME3;
39069
39158
  var CONTENT_NAME3 = "DropdownMenuContent";
@@ -39073,7 +39162,7 @@ var DropdownMenuContent = React43.forwardRef(
39073
39162
  const context = useDropdownMenuContext(CONTENT_NAME3, __scopeDropdownMenu);
39074
39163
  const menuScope = useMenuScope(__scopeDropdownMenu);
39075
39164
  const hasInteractedOutsideRef = React43.useRef(false);
39076
- return /* @__PURE__ */ jsx30(
39165
+ return /* @__PURE__ */ jsx31(
39077
39166
  Content2,
39078
39167
  {
39079
39168
  id: context.contentId,
@@ -39113,7 +39202,7 @@ var DropdownMenuGroup = React43.forwardRef(
39113
39202
  (props, forwardedRef) => {
39114
39203
  const { __scopeDropdownMenu, ...groupProps } = props;
39115
39204
  const menuScope = useMenuScope(__scopeDropdownMenu);
39116
- return /* @__PURE__ */ jsx30(Group4, { ...menuScope, ...groupProps, ref: forwardedRef });
39205
+ return /* @__PURE__ */ jsx31(Group4, { ...menuScope, ...groupProps, ref: forwardedRef });
39117
39206
  }
39118
39207
  );
39119
39208
  DropdownMenuGroup.displayName = GROUP_NAME3;
@@ -39122,7 +39211,7 @@ var DropdownMenuLabel = React43.forwardRef(
39122
39211
  (props, forwardedRef) => {
39123
39212
  const { __scopeDropdownMenu, ...labelProps } = props;
39124
39213
  const menuScope = useMenuScope(__scopeDropdownMenu);
39125
- return /* @__PURE__ */ jsx30(Label, { ...menuScope, ...labelProps, ref: forwardedRef });
39214
+ return /* @__PURE__ */ jsx31(Label, { ...menuScope, ...labelProps, ref: forwardedRef });
39126
39215
  }
39127
39216
  );
39128
39217
  DropdownMenuLabel.displayName = LABEL_NAME2;
@@ -39131,7 +39220,7 @@ var DropdownMenuItem = React43.forwardRef(
39131
39220
  (props, forwardedRef) => {
39132
39221
  const { __scopeDropdownMenu, ...itemProps } = props;
39133
39222
  const menuScope = useMenuScope(__scopeDropdownMenu);
39134
- return /* @__PURE__ */ jsx30(Item2, { ...menuScope, ...itemProps, ref: forwardedRef });
39223
+ return /* @__PURE__ */ jsx31(Item2, { ...menuScope, ...itemProps, ref: forwardedRef });
39135
39224
  }
39136
39225
  );
39137
39226
  DropdownMenuItem.displayName = ITEM_NAME3;
@@ -39139,35 +39228,35 @@ var CHECKBOX_ITEM_NAME2 = "DropdownMenuCheckboxItem";
39139
39228
  var DropdownMenuCheckboxItem = React43.forwardRef((props, forwardedRef) => {
39140
39229
  const { __scopeDropdownMenu, ...checkboxItemProps } = props;
39141
39230
  const menuScope = useMenuScope(__scopeDropdownMenu);
39142
- return /* @__PURE__ */ jsx30(CheckboxItem, { ...menuScope, ...checkboxItemProps, ref: forwardedRef });
39231
+ return /* @__PURE__ */ jsx31(CheckboxItem, { ...menuScope, ...checkboxItemProps, ref: forwardedRef });
39143
39232
  });
39144
39233
  DropdownMenuCheckboxItem.displayName = CHECKBOX_ITEM_NAME2;
39145
39234
  var RADIO_GROUP_NAME2 = "DropdownMenuRadioGroup";
39146
39235
  var DropdownMenuRadioGroup = React43.forwardRef((props, forwardedRef) => {
39147
39236
  const { __scopeDropdownMenu, ...radioGroupProps } = props;
39148
39237
  const menuScope = useMenuScope(__scopeDropdownMenu);
39149
- return /* @__PURE__ */ jsx30(RadioGroup, { ...menuScope, ...radioGroupProps, ref: forwardedRef });
39238
+ return /* @__PURE__ */ jsx31(RadioGroup, { ...menuScope, ...radioGroupProps, ref: forwardedRef });
39150
39239
  });
39151
39240
  DropdownMenuRadioGroup.displayName = RADIO_GROUP_NAME2;
39152
39241
  var RADIO_ITEM_NAME2 = "DropdownMenuRadioItem";
39153
39242
  var DropdownMenuRadioItem = React43.forwardRef((props, forwardedRef) => {
39154
39243
  const { __scopeDropdownMenu, ...radioItemProps } = props;
39155
39244
  const menuScope = useMenuScope(__scopeDropdownMenu);
39156
- return /* @__PURE__ */ jsx30(RadioItem, { ...menuScope, ...radioItemProps, ref: forwardedRef });
39245
+ return /* @__PURE__ */ jsx31(RadioItem, { ...menuScope, ...radioItemProps, ref: forwardedRef });
39157
39246
  });
39158
39247
  DropdownMenuRadioItem.displayName = RADIO_ITEM_NAME2;
39159
39248
  var INDICATOR_NAME = "DropdownMenuItemIndicator";
39160
39249
  var DropdownMenuItemIndicator = React43.forwardRef((props, forwardedRef) => {
39161
39250
  const { __scopeDropdownMenu, ...itemIndicatorProps } = props;
39162
39251
  const menuScope = useMenuScope(__scopeDropdownMenu);
39163
- return /* @__PURE__ */ jsx30(ItemIndicator, { ...menuScope, ...itemIndicatorProps, ref: forwardedRef });
39252
+ return /* @__PURE__ */ jsx31(ItemIndicator, { ...menuScope, ...itemIndicatorProps, ref: forwardedRef });
39164
39253
  });
39165
39254
  DropdownMenuItemIndicator.displayName = INDICATOR_NAME;
39166
39255
  var SEPARATOR_NAME2 = "DropdownMenuSeparator";
39167
39256
  var DropdownMenuSeparator = React43.forwardRef((props, forwardedRef) => {
39168
39257
  const { __scopeDropdownMenu, ...separatorProps } = props;
39169
39258
  const menuScope = useMenuScope(__scopeDropdownMenu);
39170
- return /* @__PURE__ */ jsx30(Separator, { ...menuScope, ...separatorProps, ref: forwardedRef });
39259
+ return /* @__PURE__ */ jsx31(Separator, { ...menuScope, ...separatorProps, ref: forwardedRef });
39171
39260
  });
39172
39261
  DropdownMenuSeparator.displayName = SEPARATOR_NAME2;
39173
39262
  var ARROW_NAME3 = "DropdownMenuArrow";
@@ -39175,7 +39264,7 @@ var DropdownMenuArrow = React43.forwardRef(
39175
39264
  (props, forwardedRef) => {
39176
39265
  const { __scopeDropdownMenu, ...arrowProps } = props;
39177
39266
  const menuScope = useMenuScope(__scopeDropdownMenu);
39178
- return /* @__PURE__ */ jsx30(Arrow22, { ...menuScope, ...arrowProps, ref: forwardedRef });
39267
+ return /* @__PURE__ */ jsx31(Arrow22, { ...menuScope, ...arrowProps, ref: forwardedRef });
39179
39268
  }
39180
39269
  );
39181
39270
  DropdownMenuArrow.displayName = ARROW_NAME3;
@@ -39188,20 +39277,20 @@ var DropdownMenuSub = (props) => {
39188
39277
  onChange: onOpenChange,
39189
39278
  caller: "DropdownMenuSub"
39190
39279
  });
39191
- return /* @__PURE__ */ jsx30(Sub, { ...menuScope, open, onOpenChange: setOpen, children });
39280
+ return /* @__PURE__ */ jsx31(Sub, { ...menuScope, open, onOpenChange: setOpen, children });
39192
39281
  };
39193
39282
  var SUB_TRIGGER_NAME2 = "DropdownMenuSubTrigger";
39194
39283
  var DropdownMenuSubTrigger = React43.forwardRef((props, forwardedRef) => {
39195
39284
  const { __scopeDropdownMenu, ...subTriggerProps } = props;
39196
39285
  const menuScope = useMenuScope(__scopeDropdownMenu);
39197
- return /* @__PURE__ */ jsx30(SubTrigger, { ...menuScope, ...subTriggerProps, ref: forwardedRef });
39286
+ return /* @__PURE__ */ jsx31(SubTrigger, { ...menuScope, ...subTriggerProps, ref: forwardedRef });
39198
39287
  });
39199
39288
  DropdownMenuSubTrigger.displayName = SUB_TRIGGER_NAME2;
39200
39289
  var SUB_CONTENT_NAME2 = "DropdownMenuSubContent";
39201
39290
  var DropdownMenuSubContent = React43.forwardRef((props, forwardedRef) => {
39202
39291
  const { __scopeDropdownMenu, ...subContentProps } = props;
39203
39292
  const menuScope = useMenuScope(__scopeDropdownMenu);
39204
- return /* @__PURE__ */ jsx30(
39293
+ return /* @__PURE__ */ jsx31(
39205
39294
  SubContent,
39206
39295
  {
39207
39296
  ...menuScope,
@@ -39233,11 +39322,11 @@ var SubTrigger2 = DropdownMenuSubTrigger;
39233
39322
  var SubContent2 = DropdownMenuSubContent;
39234
39323
 
39235
39324
  // src/components/AppearanceMenu.tsx
39236
- import { useState as useState31 } from "react";
39325
+ import { useState as useState32 } from "react";
39237
39326
 
39238
39327
  // src/components/Icons.tsx
39239
- import { jsx as jsx31 } from "react/jsx-runtime";
39240
- var CheckIcon = () => /* @__PURE__ */ jsx31(
39328
+ import { jsx as jsx32 } from "react/jsx-runtime";
39329
+ var CheckIcon = () => /* @__PURE__ */ jsx32(
39241
39330
  "svg",
39242
39331
  {
39243
39332
  xmlns: "http://www.w3.org/2000/svg",
@@ -39249,10 +39338,10 @@ var CheckIcon = () => /* @__PURE__ */ jsx31(
39249
39338
  strokeWidth: "2",
39250
39339
  strokeLinecap: "round",
39251
39340
  strokeLinejoin: "round",
39252
- children: /* @__PURE__ */ jsx31("path", { d: "M20 6 9 17l-5-5" })
39341
+ children: /* @__PURE__ */ jsx32("path", { d: "M20 6 9 17l-5-5" })
39253
39342
  }
39254
39343
  );
39255
- var ChevronRightIcon = ({ isOpen }) => /* @__PURE__ */ jsx31(
39344
+ var ChevronRightIcon = ({ isOpen }) => /* @__PURE__ */ jsx32(
39256
39345
  "svg",
39257
39346
  {
39258
39347
  xmlns: "http://www.w3.org/2000/svg",
@@ -39269,10 +39358,10 @@ var ChevronRightIcon = ({ isOpen }) => /* @__PURE__ */ jsx31(
39269
39358
  transform: isOpen ? "rotate(90deg)" : "rotate(0deg)",
39270
39359
  opacity: 0.6
39271
39360
  },
39272
- children: /* @__PURE__ */ jsx31("path", { d: "m9 18 6-6-6-6" })
39361
+ children: /* @__PURE__ */ jsx32("path", { d: "m9 18 6-6-6-6" })
39273
39362
  }
39274
39363
  );
39275
- var DotIcon = () => /* @__PURE__ */ jsx31(
39364
+ var DotIcon = () => /* @__PURE__ */ jsx32(
39276
39365
  "svg",
39277
39366
  {
39278
39367
  xmlns: "http://www.w3.org/2000/svg",
@@ -39285,12 +39374,12 @@ var DotIcon = () => /* @__PURE__ */ jsx31(
39285
39374
  strokeLinecap: "round",
39286
39375
  strokeLinejoin: "round",
39287
39376
  className: "lucide lucide-dot-icon lucide-dot",
39288
- children: /* @__PURE__ */ jsx31("circle", { cx: "12.1", cy: "12.1", r: "4.5", fill: "white" })
39377
+ children: /* @__PURE__ */ jsx32("circle", { cx: "12.1", cy: "12.1", r: "4.5", fill: "white" })
39289
39378
  }
39290
39379
  );
39291
39380
 
39292
39381
  // src/components/AppearanceMenu.tsx
39293
- import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs8 } from "react/jsx-runtime";
39382
+ import { Fragment as Fragment9, jsx as jsx33, jsxs as jsxs7 } from "react/jsx-runtime";
39294
39383
  var itemStyles = {
39295
39384
  padding: "6px 8px",
39296
39385
  borderRadius: 6,
@@ -39339,12 +39428,12 @@ var iconContainerStyles = {
39339
39428
  };
39340
39429
  var AppearanceMenu = () => {
39341
39430
  const { visibility, toggleLayer } = useLayerVisibility();
39342
- const [appearanceSubOpen, setAppearanceSubOpen] = useState31(false);
39343
- const [hoveredItem, setHoveredItem] = useState31(null);
39344
- return /* @__PURE__ */ jsxs8(Fragment10, { children: [
39345
- /* @__PURE__ */ jsx32(Separator2, { style: separatorStyles }),
39346
- /* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setAppearanceSubOpen, children: [
39347
- /* @__PURE__ */ jsxs8(
39431
+ const [appearanceSubOpen, setAppearanceSubOpen] = useState32(false);
39432
+ const [hoveredItem, setHoveredItem] = useState32(null);
39433
+ return /* @__PURE__ */ jsxs7(Fragment9, { children: [
39434
+ /* @__PURE__ */ jsx33(Separator2, { style: separatorStyles }),
39435
+ /* @__PURE__ */ jsxs7(Sub2, { onOpenChange: setAppearanceSubOpen, children: [
39436
+ /* @__PURE__ */ jsxs7(
39348
39437
  SubTrigger2,
39349
39438
  {
39350
39439
  style: {
@@ -39356,8 +39445,8 @@ var AppearanceMenu = () => {
39356
39445
  onMouseLeave: () => setHoveredItem(null),
39357
39446
  onTouchStart: () => setHoveredItem("appearance"),
39358
39447
  children: [
39359
- /* @__PURE__ */ jsx32("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Appearance" }),
39360
- /* @__PURE__ */ jsx32(
39448
+ /* @__PURE__ */ jsx33("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Appearance" }),
39449
+ /* @__PURE__ */ jsx33(
39361
39450
  "div",
39362
39451
  {
39363
39452
  style: {
@@ -39366,20 +39455,20 @@ var AppearanceMenu = () => {
39366
39455
  alignItems: "flex-end",
39367
39456
  marginBottom: "-5px"
39368
39457
  },
39369
- children: /* @__PURE__ */ jsx32(ChevronRightIcon, { isOpen: appearanceSubOpen })
39458
+ children: /* @__PURE__ */ jsx33(ChevronRightIcon, { isOpen: appearanceSubOpen })
39370
39459
  }
39371
39460
  )
39372
39461
  ]
39373
39462
  }
39374
39463
  ),
39375
- /* @__PURE__ */ jsx32(Portal22, { children: /* @__PURE__ */ jsxs8(
39464
+ /* @__PURE__ */ jsx33(Portal22, { children: /* @__PURE__ */ jsxs7(
39376
39465
  SubContent2,
39377
39466
  {
39378
39467
  style: { ...contentStyles, marginLeft: -2 },
39379
39468
  collisionPadding: 10,
39380
39469
  avoidCollisions: true,
39381
39470
  children: [
39382
- /* @__PURE__ */ jsxs8(
39471
+ /* @__PURE__ */ jsxs7(
39383
39472
  Item22,
39384
39473
  {
39385
39474
  style: {
@@ -39395,12 +39484,12 @@ var AppearanceMenu = () => {
39395
39484
  onMouseLeave: () => setHoveredItem(null),
39396
39485
  onTouchStart: () => setHoveredItem("boardBody"),
39397
39486
  children: [
39398
- /* @__PURE__ */ jsx32("span", { style: iconContainerStyles, children: visibility.boardBody && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
39399
- /* @__PURE__ */ jsx32("span", { style: { display: "flex", alignItems: "center" }, children: "Board Body" })
39487
+ /* @__PURE__ */ jsx33("span", { style: iconContainerStyles, children: visibility.boardBody && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39488
+ /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Board Body" })
39400
39489
  ]
39401
39490
  }
39402
39491
  ),
39403
- /* @__PURE__ */ jsxs8(
39492
+ /* @__PURE__ */ jsxs7(
39404
39493
  Item22,
39405
39494
  {
39406
39495
  style: {
@@ -39416,12 +39505,12 @@ var AppearanceMenu = () => {
39416
39505
  onMouseLeave: () => setHoveredItem(null),
39417
39506
  onTouchStart: () => setHoveredItem("topCopper"),
39418
39507
  children: [
39419
- /* @__PURE__ */ jsx32("span", { style: iconContainerStyles, children: visibility.topCopper && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
39420
- /* @__PURE__ */ jsx32("span", { style: { display: "flex", alignItems: "center" }, children: "Top Copper" })
39508
+ /* @__PURE__ */ jsx33("span", { style: iconContainerStyles, children: visibility.topCopper && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39509
+ /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Top Copper" })
39421
39510
  ]
39422
39511
  }
39423
39512
  ),
39424
- /* @__PURE__ */ jsxs8(
39513
+ /* @__PURE__ */ jsxs7(
39425
39514
  Item22,
39426
39515
  {
39427
39516
  style: {
@@ -39437,12 +39526,12 @@ var AppearanceMenu = () => {
39437
39526
  onMouseLeave: () => setHoveredItem(null),
39438
39527
  onTouchStart: () => setHoveredItem("bottomCopper"),
39439
39528
  children: [
39440
- /* @__PURE__ */ jsx32("span", { style: iconContainerStyles, children: visibility.bottomCopper && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
39441
- /* @__PURE__ */ jsx32("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Copper" })
39529
+ /* @__PURE__ */ jsx33("span", { style: iconContainerStyles, children: visibility.bottomCopper && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39530
+ /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Copper" })
39442
39531
  ]
39443
39532
  }
39444
39533
  ),
39445
- /* @__PURE__ */ jsxs8(
39534
+ /* @__PURE__ */ jsxs7(
39446
39535
  Item22,
39447
39536
  {
39448
39537
  style: {
@@ -39458,12 +39547,12 @@ var AppearanceMenu = () => {
39458
39547
  onMouseLeave: () => setHoveredItem(null),
39459
39548
  onTouchStart: () => setHoveredItem("topSilkscreen"),
39460
39549
  children: [
39461
- /* @__PURE__ */ jsx32("span", { style: iconContainerStyles, children: visibility.topSilkscreen && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
39462
- /* @__PURE__ */ jsx32("span", { style: { display: "flex", alignItems: "center" }, children: "Top Silkscreen" })
39550
+ /* @__PURE__ */ jsx33("span", { style: iconContainerStyles, children: visibility.topSilkscreen && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39551
+ /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Top Silkscreen" })
39463
39552
  ]
39464
39553
  }
39465
39554
  ),
39466
- /* @__PURE__ */ jsxs8(
39555
+ /* @__PURE__ */ jsxs7(
39467
39556
  Item22,
39468
39557
  {
39469
39558
  style: {
@@ -39479,12 +39568,12 @@ var AppearanceMenu = () => {
39479
39568
  onMouseLeave: () => setHoveredItem(null),
39480
39569
  onTouchStart: () => setHoveredItem("bottomSilkscreen"),
39481
39570
  children: [
39482
- /* @__PURE__ */ jsx32("span", { style: iconContainerStyles, children: visibility.bottomSilkscreen && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
39483
- /* @__PURE__ */ jsx32("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Silkscreen" })
39571
+ /* @__PURE__ */ jsx33("span", { style: iconContainerStyles, children: visibility.bottomSilkscreen && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39572
+ /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Silkscreen" })
39484
39573
  ]
39485
39574
  }
39486
39575
  ),
39487
- /* @__PURE__ */ jsxs8(
39576
+ /* @__PURE__ */ jsxs7(
39488
39577
  Item22,
39489
39578
  {
39490
39579
  style: {
@@ -39500,8 +39589,8 @@ var AppearanceMenu = () => {
39500
39589
  onMouseLeave: () => setHoveredItem(null),
39501
39590
  onTouchStart: () => setHoveredItem("smtModels"),
39502
39591
  children: [
39503
- /* @__PURE__ */ jsx32("span", { style: iconContainerStyles, children: visibility.smtModels && /* @__PURE__ */ jsx32(CheckIcon, {}) }),
39504
- /* @__PURE__ */ jsx32("span", { style: { display: "flex", alignItems: "center" }, children: "CAD Models" })
39592
+ /* @__PURE__ */ jsx33("span", { style: iconContainerStyles, children: visibility.smtModels && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39593
+ /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "CAD Models" })
39505
39594
  ]
39506
39595
  }
39507
39596
  )
@@ -39513,10 +39602,10 @@ var AppearanceMenu = () => {
39513
39602
  };
39514
39603
 
39515
39604
  // src/components/ContextMenu.tsx
39516
- import { jsx as jsx33, jsxs as jsxs9 } from "react/jsx-runtime";
39605
+ import { jsx as jsx34, jsxs as jsxs8 } from "react/jsx-runtime";
39517
39606
  var cameraOptions = [
39518
39607
  "Custom",
39519
- "Top Centered",
39608
+ "Top Center Angled",
39520
39609
  "Top Down",
39521
39610
  "Top Left Corner",
39522
39611
  "Top Right Corner",
@@ -39593,9 +39682,10 @@ var ContextMenu = ({
39593
39682
  onAutoRotateToggle,
39594
39683
  onDownloadGltf
39595
39684
  }) => {
39596
- const [cameraSubOpen, setCameraSubOpen] = useState32(false);
39597
- const [hoveredItem, setHoveredItem] = useState32(null);
39598
- return /* @__PURE__ */ jsx33(
39685
+ const { cameraType, setCameraType } = useCameraController();
39686
+ const [cameraSubOpen, setCameraSubOpen] = useState33(false);
39687
+ const [hoveredItem, setHoveredItem] = useState33(null);
39688
+ return /* @__PURE__ */ jsx34(
39599
39689
  "div",
39600
39690
  {
39601
39691
  ref: menuRef,
@@ -39606,9 +39696,9 @@ var ContextMenu = ({
39606
39696
  width: 0,
39607
39697
  height: 0
39608
39698
  },
39609
- children: /* @__PURE__ */ jsxs9(Root22, { open: true, modal: false, children: [
39610
- /* @__PURE__ */ jsx33(Trigger, { asChild: true, children: /* @__PURE__ */ jsx33("div", { style: { position: "absolute", width: 1, height: 1 } }) }),
39611
- /* @__PURE__ */ jsx33(Portal22, { children: /* @__PURE__ */ jsxs9(
39699
+ children: /* @__PURE__ */ jsxs8(Root22, { open: true, modal: false, children: [
39700
+ /* @__PURE__ */ jsx34(Trigger, { asChild: true, children: /* @__PURE__ */ jsx34("div", { style: { position: "absolute", width: 1, height: 1 } }) }),
39701
+ /* @__PURE__ */ jsx34(Portal22, { children: /* @__PURE__ */ jsxs8(
39612
39702
  Content22,
39613
39703
  {
39614
39704
  style: contentStyles2,
@@ -39617,8 +39707,8 @@ var ContextMenu = ({
39617
39707
  sideOffset: 0,
39618
39708
  align: "start",
39619
39709
  children: [
39620
- /* @__PURE__ */ jsxs9(Sub2, { onOpenChange: setCameraSubOpen, children: [
39621
- /* @__PURE__ */ jsxs9(
39710
+ /* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setCameraSubOpen, children: [
39711
+ /* @__PURE__ */ jsxs8(
39622
39712
  SubTrigger2,
39623
39713
  {
39624
39714
  style: {
@@ -39630,14 +39720,14 @@ var ContextMenu = ({
39630
39720
  onMouseLeave: () => setHoveredItem(null),
39631
39721
  onTouchStart: () => setHoveredItem("camera"),
39632
39722
  children: [
39633
- /* @__PURE__ */ jsx33(
39723
+ /* @__PURE__ */ jsx34(
39634
39724
  "span",
39635
39725
  {
39636
39726
  style: { flex: 1, display: "flex", alignItems: "center" },
39637
39727
  children: "Camera Position"
39638
39728
  }
39639
39729
  ),
39640
- /* @__PURE__ */ jsxs9(
39730
+ /* @__PURE__ */ jsxs8(
39641
39731
  "div",
39642
39732
  {
39643
39733
  style: {
@@ -39647,21 +39737,21 @@ var ContextMenu = ({
39647
39737
  marginLeft: "auto"
39648
39738
  },
39649
39739
  children: [
39650
- /* @__PURE__ */ jsx33("span", { style: { opacity: 0.55, fontSize: 13 }, children: cameraPreset }),
39651
- /* @__PURE__ */ jsx33(ChevronRightIcon, { isOpen: cameraSubOpen })
39740
+ /* @__PURE__ */ jsx34("span", { style: { opacity: 0.55, fontSize: 13 }, children: cameraPreset }),
39741
+ /* @__PURE__ */ jsx34(ChevronRightIcon, { isOpen: cameraSubOpen })
39652
39742
  ]
39653
39743
  }
39654
39744
  )
39655
39745
  ]
39656
39746
  }
39657
39747
  ),
39658
- /* @__PURE__ */ jsx33(Portal22, { children: /* @__PURE__ */ jsx33(
39748
+ /* @__PURE__ */ jsx34(Portal22, { children: /* @__PURE__ */ jsx34(
39659
39749
  SubContent2,
39660
39750
  {
39661
39751
  style: { ...contentStyles2, marginLeft: -2 },
39662
39752
  collisionPadding: 10,
39663
39753
  avoidCollisions: true,
39664
- children: cameraOptions.map((option) => /* @__PURE__ */ jsxs9(
39754
+ children: cameraOptions.map((option) => /* @__PURE__ */ jsxs8(
39665
39755
  Item22,
39666
39756
  {
39667
39757
  style: {
@@ -39677,8 +39767,8 @@ var ContextMenu = ({
39677
39767
  onMouseLeave: () => setHoveredItem(null),
39678
39768
  onTouchStart: () => setHoveredItem(option),
39679
39769
  children: [
39680
- /* @__PURE__ */ jsx33("span", { style: iconContainerStyles2, children: cameraPreset === option && /* @__PURE__ */ jsx33(DotIcon, {}) }),
39681
- /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: option })
39770
+ /* @__PURE__ */ jsx34("span", { style: iconContainerStyles2, children: cameraPreset === option && /* @__PURE__ */ jsx34(DotIcon, {}) }),
39771
+ /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: option })
39682
39772
  ]
39683
39773
  },
39684
39774
  option
@@ -39686,7 +39776,7 @@ var ContextMenu = ({
39686
39776
  }
39687
39777
  ) })
39688
39778
  ] }),
39689
- /* @__PURE__ */ jsxs9(
39779
+ /* @__PURE__ */ jsxs8(
39690
39780
  Item22,
39691
39781
  {
39692
39782
  style: {
@@ -39703,14 +39793,38 @@ var ContextMenu = ({
39703
39793
  onMouseLeave: () => setHoveredItem(null),
39704
39794
  onTouchStart: () => setHoveredItem("autorotate"),
39705
39795
  children: [
39706
- /* @__PURE__ */ jsx33("span", { style: iconContainerStyles2, children: autoRotate && /* @__PURE__ */ jsx33(CheckIcon, {}) }),
39707
- /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Auto rotate" })
39796
+ /* @__PURE__ */ jsx34("span", { style: iconContainerStyles2, children: autoRotate && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
39797
+ /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Auto rotate" })
39798
+ ]
39799
+ }
39800
+ ),
39801
+ /* @__PURE__ */ jsxs8(
39802
+ Item22,
39803
+ {
39804
+ style: {
39805
+ ...itemStyles2,
39806
+ ...itemPaddingStyles2,
39807
+ backgroundColor: hoveredItem === "cameratype" ? "#404040" : "transparent"
39808
+ },
39809
+ onSelect: (e) => e.preventDefault(),
39810
+ onPointerDown: (e) => {
39811
+ e.preventDefault();
39812
+ setCameraType(
39813
+ cameraType === "perspective" ? "orthographic" : "perspective"
39814
+ );
39815
+ },
39816
+ onMouseEnter: () => setHoveredItem("cameratype"),
39817
+ onMouseLeave: () => setHoveredItem(null),
39818
+ onTouchStart: () => setHoveredItem("cameratype"),
39819
+ children: [
39820
+ /* @__PURE__ */ jsx34("span", { style: iconContainerStyles2, children: cameraType === "orthographic" && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
39821
+ /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Orthographic Camera" })
39708
39822
  ]
39709
39823
  }
39710
39824
  ),
39711
- /* @__PURE__ */ jsx33(AppearanceMenu, {}),
39712
- /* @__PURE__ */ jsx33(Separator2, { style: separatorStyles2 }),
39713
- /* @__PURE__ */ jsx33(
39825
+ /* @__PURE__ */ jsx34(AppearanceMenu, {}),
39826
+ /* @__PURE__ */ jsx34(Separator2, { style: separatorStyles2 }),
39827
+ /* @__PURE__ */ jsx34(
39714
39828
  Item22,
39715
39829
  {
39716
39830
  style: {
@@ -39722,11 +39836,11 @@ var ContextMenu = ({
39722
39836
  onMouseEnter: () => setHoveredItem("download"),
39723
39837
  onMouseLeave: () => setHoveredItem(null),
39724
39838
  onTouchStart: () => setHoveredItem("download"),
39725
- children: /* @__PURE__ */ jsx33("span", { style: { display: "flex", alignItems: "center" }, children: "Download GLTF" })
39839
+ children: /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Download GLTF" })
39726
39840
  }
39727
39841
  ),
39728
- /* @__PURE__ */ jsx33(Separator2, { style: separatorStyles2 }),
39729
- /* @__PURE__ */ jsxs9(
39842
+ /* @__PURE__ */ jsx34(Separator2, { style: separatorStyles2 }),
39843
+ /* @__PURE__ */ jsxs8(
39730
39844
  Item22,
39731
39845
  {
39732
39846
  style: {
@@ -39743,12 +39857,12 @@ var ContextMenu = ({
39743
39857
  onMouseLeave: () => setHoveredItem(null),
39744
39858
  onTouchStart: () => setHoveredItem("engine"),
39745
39859
  children: [
39746
- /* @__PURE__ */ jsxs9("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: [
39860
+ /* @__PURE__ */ jsxs8("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: [
39747
39861
  "Switch to ",
39748
39862
  engine === "jscad" ? "Manifold" : "JSCAD",
39749
39863
  " Engine"
39750
39864
  ] }),
39751
- /* @__PURE__ */ jsx33(
39865
+ /* @__PURE__ */ jsx34(
39752
39866
  "div",
39753
39867
  {
39754
39868
  style: {
@@ -39762,8 +39876,8 @@ var ContextMenu = ({
39762
39876
  ]
39763
39877
  }
39764
39878
  ),
39765
- /* @__PURE__ */ jsx33(Separator2, { style: separatorStyles2 }),
39766
- /* @__PURE__ */ jsx33(
39879
+ /* @__PURE__ */ jsx34(Separator2, { style: separatorStyles2 }),
39880
+ /* @__PURE__ */ jsx34(
39767
39881
  "div",
39768
39882
  {
39769
39883
  style: {
@@ -39774,7 +39888,7 @@ var ContextMenu = ({
39774
39888
  paddingTop: 4,
39775
39889
  paddingBottom: 4
39776
39890
  },
39777
- children: /* @__PURE__ */ jsxs9(
39891
+ children: /* @__PURE__ */ jsxs8(
39778
39892
  "span",
39779
39893
  {
39780
39894
  style: {
@@ -39801,21 +39915,22 @@ var ContextMenu = ({
39801
39915
  };
39802
39916
 
39803
39917
  // src/CadViewer.tsx
39804
- import { jsx as jsx34, jsxs as jsxs10 } from "react/jsx-runtime";
39918
+ import { jsx as jsx35, jsxs as jsxs9 } from "react/jsx-runtime";
39805
39919
  var CadViewerInner = (props) => {
39806
- const [engine, setEngine] = useState33("manifold");
39807
- const containerRef = useRef23(null);
39808
- const [autoRotate, setAutoRotate] = useState33(() => {
39920
+ const [engine, setEngine] = useState34("manifold");
39921
+ const containerRef = useRef24(null);
39922
+ const [autoRotate, setAutoRotate] = useState34(() => {
39809
39923
  const stored = window.localStorage.getItem("cadViewerAutoRotate");
39810
39924
  return stored === "false" ? false : true;
39811
39925
  });
39812
- const [autoRotateUserToggled, setAutoRotateUserToggled] = useState33(() => {
39926
+ const [autoRotateUserToggled, setAutoRotateUserToggled] = useState34(() => {
39813
39927
  const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled");
39814
39928
  return stored === "true";
39815
39929
  });
39816
- const [cameraPreset, setCameraPreset] = useState33("Custom");
39930
+ const [cameraPreset, setCameraPreset] = useState34("Custom");
39931
+ const { cameraType, setCameraType } = useCameraController();
39817
39932
  const { visibility, toggleLayer } = useLayerVisibility();
39818
- const cameraControllerRef = useRef23(null);
39933
+ const cameraControllerRef = useRef24(null);
39819
39934
  const externalCameraControllerReady = props.onCameraControllerReady;
39820
39935
  const {
39821
39936
  menuVisible,
@@ -39824,12 +39939,12 @@ var CadViewerInner = (props) => {
39824
39939
  contextMenuEventHandlers,
39825
39940
  setMenuVisible
39826
39941
  } = useContextMenu({ containerRef });
39827
- const autoRotateUserToggledRef = useRef23(autoRotateUserToggled);
39942
+ const autoRotateUserToggledRef = useRef24(autoRotateUserToggled);
39828
39943
  autoRotateUserToggledRef.current = autoRotateUserToggled;
39829
- const isAnimatingRef = useRef23(false);
39830
- const lastPresetSelectTime = useRef23(0);
39944
+ const isAnimatingRef = useRef24(false);
39945
+ const lastPresetSelectTime = useRef24(0);
39831
39946
  const PRESET_COOLDOWN = 1e3;
39832
- const handleUserInteraction = useCallback20(() => {
39947
+ const handleUserInteraction = useCallback22(() => {
39833
39948
  if (isAnimatingRef.current || Date.now() - lastPresetSelectTime.current < PRESET_COOLDOWN) {
39834
39949
  return;
39835
39950
  }
@@ -39840,15 +39955,15 @@ var CadViewerInner = (props) => {
39840
39955
  setCameraPreset("Custom");
39841
39956
  }
39842
39957
  }, [menuVisible]);
39843
- const toggleAutoRotate = useCallback20(() => {
39958
+ const toggleAutoRotate = useCallback22(() => {
39844
39959
  setAutoRotate((prev) => !prev);
39845
39960
  setAutoRotateUserToggled(true);
39846
39961
  }, []);
39847
39962
  const downloadGltf = useGlobalDownloadGltf();
39848
- const closeMenu = useCallback20(() => {
39963
+ const closeMenu = useCallback22(() => {
39849
39964
  setMenuVisible(false);
39850
39965
  }, [setMenuVisible]);
39851
- const handleCameraControllerReady = useCallback20(
39966
+ const handleCameraControllerReady = useCallback22(
39852
39967
  (controller) => {
39853
39968
  cameraControllerRef.current = controller;
39854
39969
  externalCameraControllerReady?.(controller);
@@ -39867,26 +39982,35 @@ var CadViewerInner = (props) => {
39867
39982
  isAnimatingRef,
39868
39983
  lastPresetSelectTime
39869
39984
  });
39870
- useEffect39(() => {
39985
+ useEffect40(() => {
39871
39986
  const stored = window.localStorage.getItem("cadViewerEngine");
39872
39987
  if (stored === "jscad" || stored === "manifold") {
39873
39988
  setEngine(stored);
39874
39989
  }
39875
39990
  }, []);
39876
- useEffect39(() => {
39991
+ useEffect40(() => {
39877
39992
  window.localStorage.setItem("cadViewerEngine", engine);
39878
39993
  }, [engine]);
39879
- useEffect39(() => {
39994
+ useEffect40(() => {
39880
39995
  window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
39881
39996
  }, [autoRotate]);
39882
- useEffect39(() => {
39997
+ useEffect40(() => {
39883
39998
  window.localStorage.setItem(
39884
39999
  "cadViewerAutoRotateUserToggled",
39885
40000
  String(autoRotateUserToggled)
39886
40001
  );
39887
40002
  }, [autoRotateUserToggled]);
40003
+ useEffect40(() => {
40004
+ const stored = window.localStorage.getItem("cadViewerCameraType");
40005
+ if (stored === "orthographic" || stored === "perspective") {
40006
+ setCameraType(stored);
40007
+ }
40008
+ }, [setCameraType]);
40009
+ useEffect40(() => {
40010
+ window.localStorage.setItem("cadViewerCameraType", cameraType);
40011
+ }, [cameraType]);
39888
40012
  const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
39889
- return /* @__PURE__ */ jsxs10(
40013
+ return /* @__PURE__ */ jsxs9(
39890
40014
  "div",
39891
40015
  {
39892
40016
  ref: containerRef,
@@ -39902,24 +40026,26 @@ var CadViewerInner = (props) => {
39902
40026
  },
39903
40027
  ...contextMenuEventHandlers,
39904
40028
  children: [
39905
- engine === "jscad" ? /* @__PURE__ */ jsx34(
40029
+ engine === "jscad" ? /* @__PURE__ */ jsx35(
39906
40030
  CadViewerJscad,
39907
40031
  {
39908
40032
  ...props,
39909
40033
  autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
40034
+ cameraType,
39910
40035
  onUserInteraction: handleUserInteraction,
39911
40036
  onCameraControllerReady: handleCameraControllerReady
39912
40037
  }
39913
- ) : /* @__PURE__ */ jsx34(
40038
+ ) : /* @__PURE__ */ jsx35(
39914
40039
  CadViewerManifold_default,
39915
40040
  {
39916
40041
  ...props,
39917
40042
  autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
40043
+ cameraType,
39918
40044
  onUserInteraction: handleUserInteraction,
39919
40045
  onCameraControllerReady: handleCameraControllerReady
39920
40046
  }
39921
40047
  ),
39922
- /* @__PURE__ */ jsxs10(
40048
+ /* @__PURE__ */ jsxs9(
39923
40049
  "div",
39924
40050
  {
39925
40051
  style: {
@@ -39936,11 +40062,11 @@ var CadViewerInner = (props) => {
39936
40062
  },
39937
40063
  children: [
39938
40064
  "Engine: ",
39939
- /* @__PURE__ */ jsx34("b", { children: engine === "jscad" ? "JSCAD" : "Manifold" })
40065
+ /* @__PURE__ */ jsx35("b", { children: engine === "jscad" ? "JSCAD" : "Manifold" })
39940
40066
  ]
39941
40067
  }
39942
40068
  ),
39943
- menuVisible && /* @__PURE__ */ jsx34(
40069
+ menuVisible && /* @__PURE__ */ jsx35(
39944
40070
  ContextMenu,
39945
40071
  {
39946
40072
  menuRef,
@@ -39969,17 +40095,29 @@ var CadViewerInner = (props) => {
39969
40095
  );
39970
40096
  };
39971
40097
  var CadViewer = (props) => {
39972
- return /* @__PURE__ */ jsx34(LayerVisibilityProvider, { children: /* @__PURE__ */ jsx34(CadViewerInner, { ...props }) });
40098
+ const defaultTarget = useMemo26(() => new THREE29.Vector3(0, 0, 0), []);
40099
+ const initialCameraPosition = useMemo26(
40100
+ () => [5, -5, 5],
40101
+ []
40102
+ );
40103
+ return /* @__PURE__ */ jsx35(
40104
+ CameraControllerProvider,
40105
+ {
40106
+ defaultTarget,
40107
+ initialCameraPosition,
40108
+ children: /* @__PURE__ */ jsx35(LayerVisibilityProvider, { children: /* @__PURE__ */ jsx35(CadViewerInner, { ...props }) })
40109
+ }
40110
+ );
39973
40111
  };
39974
40112
 
39975
40113
  // src/convert-circuit-json-to-3d-svg.ts
39976
40114
  var import_debug = __toESM(require_browser(), 1);
39977
40115
  import { su as su16 } from "@tscircuit/circuit-json-util";
39978
- import * as THREE31 from "three";
40116
+ import * as THREE33 from "three";
39979
40117
  import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
39980
40118
 
39981
40119
  // src/utils/create-geometry-from-polygons.ts
39982
- import * as THREE28 from "three";
40120
+ import * as THREE30 from "three";
39983
40121
  import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
39984
40122
  function createGeometryFromPolygons(polygons) {
39985
40123
  const geometry = new BufferGeometry3();
@@ -39993,12 +40131,12 @@ function createGeometryFromPolygons(polygons) {
39993
40131
  ...polygon3.vertices[i + 1]
39994
40132
  // Third vertex
39995
40133
  );
39996
- const v1 = new THREE28.Vector3(...polygon3.vertices[0]);
39997
- const v2 = new THREE28.Vector3(...polygon3.vertices[i]);
39998
- const v3 = new THREE28.Vector3(...polygon3.vertices[i + 1]);
39999
- const normal = new THREE28.Vector3().crossVectors(
40000
- new THREE28.Vector3().subVectors(v2, v1),
40001
- new THREE28.Vector3().subVectors(v3, v1)
40134
+ const v1 = new THREE30.Vector3(...polygon3.vertices[0]);
40135
+ const v2 = new THREE30.Vector3(...polygon3.vertices[i]);
40136
+ const v3 = new THREE30.Vector3(...polygon3.vertices[i + 1]);
40137
+ const normal = new THREE30.Vector3().crossVectors(
40138
+ new THREE30.Vector3().subVectors(v2, v1),
40139
+ new THREE30.Vector3().subVectors(v3, v1)
40002
40140
  ).normalize();
40003
40141
  normals.push(
40004
40142
  normal.x,
@@ -40022,10 +40160,10 @@ function createGeometryFromPolygons(polygons) {
40022
40160
  var import_modeling2 = __toESM(require_src(), 1);
40023
40161
  var import_jscad_planner2 = __toESM(require_dist(), 1);
40024
40162
  var jscadModeling2 = __toESM(require_src(), 1);
40025
- import * as THREE30 from "three";
40163
+ import * as THREE32 from "three";
40026
40164
 
40027
40165
  // src/utils/load-model.ts
40028
- import * as THREE29 from "three";
40166
+ import * as THREE31 from "three";
40029
40167
  import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
40030
40168
  import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
40031
40169
  import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
@@ -40033,12 +40171,12 @@ async function load3DModel(url) {
40033
40171
  if (url.endsWith(".stl")) {
40034
40172
  const loader = new STLLoader2();
40035
40173
  const geometry = await loader.loadAsync(url);
40036
- const material = new THREE29.MeshStandardMaterial({
40174
+ const material = new THREE31.MeshStandardMaterial({
40037
40175
  color: 8947848,
40038
40176
  metalness: 0.5,
40039
40177
  roughness: 0.5
40040
40178
  });
40041
- return new THREE29.Mesh(geometry, material);
40179
+ return new THREE31.Mesh(geometry, material);
40042
40180
  }
40043
40181
  if (url.endsWith(".obj")) {
40044
40182
  const loader = new OBJLoader2();
@@ -40071,9 +40209,9 @@ async function renderComponent(component, scene) {
40071
40209
  }
40072
40210
  if (component.rotation) {
40073
40211
  model.rotation.set(
40074
- THREE30.MathUtils.degToRad(component.rotation.x ?? 0),
40075
- THREE30.MathUtils.degToRad(component.rotation.y ?? 0),
40076
- THREE30.MathUtils.degToRad(component.rotation.z ?? 0)
40212
+ THREE32.MathUtils.degToRad(component.rotation.x ?? 0),
40213
+ THREE32.MathUtils.degToRad(component.rotation.y ?? 0),
40214
+ THREE32.MathUtils.degToRad(component.rotation.z ?? 0)
40077
40215
  );
40078
40216
  }
40079
40217
  scene.add(model);
@@ -40087,13 +40225,13 @@ async function renderComponent(component, scene) {
40087
40225
  );
40088
40226
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
40089
40227
  const threeGeom = convertCSGToThreeGeom(jscadObject);
40090
- const material2 = new THREE30.MeshStandardMaterial({
40228
+ const material2 = new THREE32.MeshStandardMaterial({
40091
40229
  color: 8947848,
40092
40230
  metalness: 0.5,
40093
40231
  roughness: 0.5,
40094
- side: THREE30.DoubleSide
40232
+ side: THREE32.DoubleSide
40095
40233
  });
40096
- const mesh2 = new THREE30.Mesh(threeGeom, material2);
40234
+ const mesh2 = new THREE32.Mesh(threeGeom, material2);
40097
40235
  if (component.position) {
40098
40236
  mesh2.position.set(
40099
40237
  component.position.x ?? 0,
@@ -40103,9 +40241,9 @@ async function renderComponent(component, scene) {
40103
40241
  }
40104
40242
  if (component.rotation) {
40105
40243
  mesh2.rotation.set(
40106
- THREE30.MathUtils.degToRad(component.rotation.x ?? 0),
40107
- THREE30.MathUtils.degToRad(component.rotation.y ?? 0),
40108
- THREE30.MathUtils.degToRad(component.rotation.z ?? 0)
40244
+ THREE32.MathUtils.degToRad(component.rotation.x ?? 0),
40245
+ THREE32.MathUtils.degToRad(component.rotation.y ?? 0),
40246
+ THREE32.MathUtils.degToRad(component.rotation.z ?? 0)
40109
40247
  );
40110
40248
  }
40111
40249
  scene.add(mesh2);
@@ -40122,17 +40260,17 @@ async function renderComponent(component, scene) {
40122
40260
  if (!geom || !geom.polygons && !geom.sides) {
40123
40261
  continue;
40124
40262
  }
40125
- const color = new THREE30.Color(geomInfo.color);
40263
+ const color = new THREE32.Color(geomInfo.color);
40126
40264
  color.convertLinearToSRGB();
40127
40265
  const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
40128
40266
  const threeGeom = convertCSGToThreeGeom(geomWithColor);
40129
- const material2 = new THREE30.MeshStandardMaterial({
40267
+ const material2 = new THREE32.MeshStandardMaterial({
40130
40268
  vertexColors: true,
40131
40269
  metalness: 0.2,
40132
40270
  roughness: 0.8,
40133
- side: THREE30.DoubleSide
40271
+ side: THREE32.DoubleSide
40134
40272
  });
40135
- const mesh2 = new THREE30.Mesh(threeGeom, material2);
40273
+ const mesh2 = new THREE32.Mesh(threeGeom, material2);
40136
40274
  if (component.position) {
40137
40275
  mesh2.position.set(
40138
40276
  component.position.x ?? 0,
@@ -40142,22 +40280,22 @@ async function renderComponent(component, scene) {
40142
40280
  }
40143
40281
  if (component.rotation) {
40144
40282
  mesh2.rotation.set(
40145
- THREE30.MathUtils.degToRad(component.rotation.x ?? 0),
40146
- THREE30.MathUtils.degToRad(component.rotation.y ?? 0),
40147
- THREE30.MathUtils.degToRad(component.rotation.z ?? 0)
40283
+ THREE32.MathUtils.degToRad(component.rotation.x ?? 0),
40284
+ THREE32.MathUtils.degToRad(component.rotation.y ?? 0),
40285
+ THREE32.MathUtils.degToRad(component.rotation.z ?? 0)
40148
40286
  );
40149
40287
  }
40150
40288
  scene.add(mesh2);
40151
40289
  }
40152
40290
  return;
40153
40291
  }
40154
- const geometry = new THREE30.BoxGeometry(0.5, 0.5, 0.5);
40155
- const material = new THREE30.MeshStandardMaterial({
40292
+ const geometry = new THREE32.BoxGeometry(0.5, 0.5, 0.5);
40293
+ const material = new THREE32.MeshStandardMaterial({
40156
40294
  color: 16711680,
40157
40295
  transparent: true,
40158
40296
  opacity: 0.25
40159
40297
  });
40160
- const mesh = new THREE30.Mesh(geometry, material);
40298
+ const mesh = new THREE32.Mesh(geometry, material);
40161
40299
  if (component.position) {
40162
40300
  mesh.position.set(
40163
40301
  component.position.x ?? 0,
@@ -40178,11 +40316,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
40178
40316
  padding = 20,
40179
40317
  zoom = 1.5
40180
40318
  } = options;
40181
- const scene = new THREE31.Scene();
40319
+ const scene = new THREE33.Scene();
40182
40320
  const renderer = new SVGRenderer();
40183
40321
  renderer.setSize(width10, height10);
40184
- renderer.setClearColor(new THREE31.Color(backgroundColor), 1);
40185
- const camera = new THREE31.OrthographicCamera();
40322
+ renderer.setClearColor(new THREE33.Color(backgroundColor), 1);
40323
+ const camera = new THREE33.OrthographicCamera();
40186
40324
  const aspect = width10 / height10;
40187
40325
  const frustumSize = 100;
40188
40326
  const halfFrustumSize = frustumSize / 2 / zoom;
@@ -40196,11 +40334,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
40196
40334
  camera.position.set(position.x, position.y, position.z);
40197
40335
  camera.up.set(0, 1, 0);
40198
40336
  const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
40199
- camera.lookAt(new THREE31.Vector3(lookAt.x, lookAt.y, lookAt.z));
40337
+ camera.lookAt(new THREE33.Vector3(lookAt.x, lookAt.y, lookAt.z));
40200
40338
  camera.updateProjectionMatrix();
40201
- const ambientLight = new THREE31.AmbientLight(16777215, Math.PI / 2);
40339
+ const ambientLight = new THREE33.AmbientLight(16777215, Math.PI / 2);
40202
40340
  scene.add(ambientLight);
40203
- const pointLight = new THREE31.PointLight(16777215, Math.PI / 4);
40341
+ const pointLight = new THREE33.PointLight(16777215, Math.PI / 4);
40204
40342
  pointLight.position.set(-10, -10, 10);
40205
40343
  scene.add(pointLight);
40206
40344
  const components = su16(circuitJson).cad_component.list();
@@ -40214,7 +40352,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
40214
40352
  const g = geom;
40215
40353
  if (!g.polygons || g.polygons.length === 0) continue;
40216
40354
  const geometry = createGeometryFromPolygons(g.polygons);
40217
- const baseColor = new THREE31.Color(
40355
+ const baseColor = new THREE33.Color(
40218
40356
  g.color?.[0] ?? 0,
40219
40357
  g.color?.[1] ?? 0,
40220
40358
  g.color?.[2] ?? 0
@@ -40222,18 +40360,18 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
40222
40360
  const material = createBoardMaterial({
40223
40361
  material: boardData?.material,
40224
40362
  color: baseColor,
40225
- side: THREE31.DoubleSide
40363
+ side: THREE33.DoubleSide
40226
40364
  });
40227
- const mesh = new THREE31.Mesh(geometry, material);
40365
+ const mesh = new THREE33.Mesh(geometry, material);
40228
40366
  scene.add(mesh);
40229
40367
  }
40230
40368
  }
40231
- const gridHelper = new THREE31.GridHelper(100, 100);
40369
+ const gridHelper = new THREE33.GridHelper(100, 100);
40232
40370
  gridHelper.rotation.x = Math.PI / 2;
40233
40371
  scene.add(gridHelper);
40234
- const box = new THREE31.Box3().setFromObject(scene);
40235
- const center = box.getCenter(new THREE31.Vector3());
40236
- const size5 = box.getSize(new THREE31.Vector3());
40372
+ const box = new THREE33.Box3().setFromObject(scene);
40373
+ const center = box.getCenter(new THREE33.Vector3());
40374
+ const size5 = box.getSize(new THREE33.Vector3());
40237
40375
  scene.position.sub(center);
40238
40376
  const maxDim = Math.max(size5.x, size5.y, size5.z);
40239
40377
  if (maxDim > 0) {
@@ -40251,7 +40389,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
40251
40389
 
40252
40390
  // src/hooks/exporter/gltf.ts
40253
40391
  import { GLTFExporter as GLTFExporter2 } from "three-stdlib";
40254
- import { useEffect as useEffect40, useState as useState34, useMemo as useMemo27, useCallback as useCallback21 } from "react";
40392
+ import { useEffect as useEffect41, useState as useState35, useMemo as useMemo27, useCallback as useCallback23 } from "react";
40255
40393
  function useSaveGltfAs(options = {}) {
40256
40394
  const parse2 = useParser(options);
40257
40395
  const link = useMemo27(() => document.createElement("a"), []);
@@ -40264,7 +40402,7 @@ function useSaveGltfAs(options = {}) {
40264
40402
  link.dispatchEvent(new MouseEvent("click"));
40265
40403
  URL.revokeObjectURL(url);
40266
40404
  };
40267
- useEffect40(
40405
+ useEffect41(
40268
40406
  () => () => {
40269
40407
  link.remove();
40270
40408
  instance = null;
@@ -40272,20 +40410,20 @@ function useSaveGltfAs(options = {}) {
40272
40410
  []
40273
40411
  );
40274
40412
  let instance;
40275
- const ref = useCallback21((obj3D) => {
40413
+ const ref = useCallback23((obj3D) => {
40276
40414
  instance = obj3D;
40277
40415
  }, []);
40278
40416
  return [ref, saveAs];
40279
40417
  }
40280
40418
  function useExportGltfUrl(options = {}) {
40281
40419
  const parse2 = useParser(options);
40282
- const [url, setUrl] = useState34();
40283
- const [error, setError] = useState34();
40284
- const ref = useCallback21(
40420
+ const [url, setUrl] = useState35();
40421
+ const [error, setError] = useState35();
40422
+ const ref = useCallback23(
40285
40423
  (instance) => parse2(instance).then(setUrl).catch(setError),
40286
40424
  []
40287
40425
  );
40288
- useEffect40(() => () => URL.revokeObjectURL(url), [url]);
40426
+ useEffect41(() => () => URL.revokeObjectURL(url), [url]);
40289
40427
  return [ref, url, error];
40290
40428
  }
40291
40429
  function useParser(options = {}) {
@@ -40316,8 +40454,14 @@ function applyJsdomShim(jsdom) {
40316
40454
  }
40317
40455
  export {
40318
40456
  CadViewer,
40457
+ CameraAnimatorWithContext,
40458
+ CameraControllerProvider,
40319
40459
  applyJsdomShim,
40320
40460
  convertCircuitJsonTo3dSvg,
40461
+ loadCameraFromSession,
40462
+ saveCameraToSession,
40463
+ useCameraController,
40464
+ useCameraSession,
40321
40465
  useExportGltfUrl,
40322
40466
  useManifoldBoardBuilder,
40323
40467
  useSaveGltfAs