@tscircuit/3d-viewer 0.0.431 → 0.0.432

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +111 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14228,7 +14228,7 @@ var require_browser = __commonJS({
14228
14228
  });
14229
14229
 
14230
14230
  // src/CadViewer.tsx
14231
- import { useState as useState33, useCallback as useCallback20, useRef as useRef22, useEffect as useEffect39 } from "react";
14231
+ import { useState as useState33, useCallback as useCallback20, useRef as useRef23, useEffect as useEffect39 } from "react";
14232
14232
 
14233
14233
  // src/CadViewerJscad.tsx
14234
14234
  import { su as su4 } from "@tscircuit/circuit-json-util";
@@ -28168,13 +28168,13 @@ var AnyCadComponent = ({
28168
28168
  };
28169
28169
 
28170
28170
  // src/CadViewerContainer.tsx
28171
- import { forwardRef as forwardRef2, useMemo as useMemo15, useState as useState8 } from "react";
28171
+ import { forwardRef as forwardRef2, useMemo as useMemo15, useRef as useRef6, useState as useState8 } from "react";
28172
28172
  import * as THREE14 from "three";
28173
28173
 
28174
28174
  // package.json
28175
28175
  var package_default = {
28176
28176
  name: "@tscircuit/3d-viewer",
28177
- version: "0.0.430",
28177
+ version: "0.0.431",
28178
28178
  main: "./dist/index.js",
28179
28179
  module: "./dist/index.js",
28180
28180
  type: "module",
@@ -28460,7 +28460,7 @@ var configureRenderer = (renderer) => {
28460
28460
  // src/react-three/Canvas.tsx
28461
28461
  import { jsx as jsx11 } from "react/jsx-runtime";
28462
28462
  var Canvas = forwardRef(
28463
- ({ children, scene: sceneProps, camera: cameraProps, style }, ref) => {
28463
+ ({ children, scene: sceneProps, camera: cameraProps, style, onCreated }, ref) => {
28464
28464
  const mountRef = useRef4(null);
28465
28465
  const [contextState, setContextState] = useState7(
28466
28466
  null
@@ -28468,6 +28468,8 @@ var Canvas = forwardRef(
28468
28468
  const frameListeners = useRef4(
28469
28469
  []
28470
28470
  );
28471
+ const onCreatedRef = useRef4(void 0);
28472
+ onCreatedRef.current = onCreated;
28471
28473
  const addFrameListener = useCallback4(
28472
28474
  (listener) => {
28473
28475
  frameListeners.current.push(listener);
@@ -28526,6 +28528,7 @@ var Canvas = forwardRef(
28526
28528
  addFrameListener,
28527
28529
  removeFrameListener
28528
28530
  });
28531
+ onCreatedRef.current?.({ camera, renderer });
28529
28532
  let animationFrameId;
28530
28533
  const clock = new THREE10.Clock();
28531
28534
  const animate = () => {
@@ -28585,10 +28588,17 @@ var OrbitControls = ({
28585
28588
  return new ThreeOrbitControls(camera, renderer.domElement);
28586
28589
  }, [camera, renderer]);
28587
28590
  useEffect13(() => {
28588
- if (!onControlsChange) return;
28589
- onControlsChange(controls ?? null);
28591
+ onControlsChange?.(controls ?? null);
28592
+ return () => onControlsChange?.(null);
28593
+ }, [controls, onControlsChange]);
28594
+ useEffect13(() => {
28595
+ if (!controls) return;
28596
+ const handleChange = () => {
28597
+ onControlsChange?.(controls);
28598
+ };
28599
+ controls.addEventListener("change", handleChange);
28590
28600
  return () => {
28591
- onControlsChange(null);
28601
+ controls.removeEventListener("change", handleChange);
28592
28602
  };
28593
28603
  }, [controls, onControlsChange]);
28594
28604
  useEffect13(() => {
@@ -28754,6 +28764,45 @@ var Lights = () => {
28754
28764
  return null;
28755
28765
  };
28756
28766
 
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
+
28757
28806
  // src/hooks/useCameraController.ts
28758
28807
  import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo14, useRef as useRef5 } from "react";
28759
28808
  import * as THREE13 from "three";
@@ -29045,6 +29094,10 @@ var CadViewerContainer = forwardRef2(
29045
29094
  const [isInteractionEnabled, setIsInteractionEnabled] = useState8(
29046
29095
  !clickToInteractEnabled
29047
29096
  );
29097
+ const saveTimeoutRef = useRef6(null);
29098
+ const controlsRef = useRef6(null);
29099
+ const cameraRef = useRef6(null);
29100
+ const restoredOnceRef = useRef6(false);
29048
29101
  const gridSectionSize = useMemo15(() => {
29049
29102
  if (!boardDimensions) return 10;
29050
29103
  const width10 = boardDimensions.width ?? 0;
@@ -29098,6 +29151,23 @@ var CadViewerContainer = forwardRef2(
29098
29151
  ref,
29099
29152
  scene: { up: new THREE14.Vector3(0, 0, 1) },
29100
29153
  camera: { up: [0, 0, 1], position: initialCameraPosition },
29154
+ 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
+ }
29170
+ },
29101
29171
  children: [
29102
29172
  /* @__PURE__ */ jsx12(CameraAnimator, { ...cameraAnimatorProps }),
29103
29173
  /* @__PURE__ */ jsx12(RotationTracker, {}),
@@ -29113,7 +29183,26 @@ var CadViewerContainer = forwardRef2(
29113
29183
  enableDamping: true,
29114
29184
  dampingFactor: 0.1,
29115
29185
  target: orbitTarget,
29116
- onControlsChange: handleControlsChange
29186
+ onControlsChange: (controls) => {
29187
+ 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);
29205
+ }
29117
29206
  }
29118
29207
  ),
29119
29208
  /* @__PURE__ */ jsx12(Lights, {}),
@@ -29237,7 +29326,7 @@ var useStlsFromGeom = (geom) => {
29237
29326
  };
29238
29327
 
29239
29328
  // src/hooks/useBoardGeomBuilder.ts
29240
- import { useState as useState10, useEffect as useEffect18, useRef as useRef6 } from "react";
29329
+ import { useState as useState10, useEffect as useEffect18, useRef as useRef7 } from "react";
29241
29330
 
29242
29331
  // src/soup-to-3d/index.ts
29243
29332
  var import_primitives2 = __toESM(require_primitives(), 1);
@@ -31098,7 +31187,7 @@ var BoardGeomBuilder = class {
31098
31187
  // src/hooks/useBoardGeomBuilder.ts
31099
31188
  var useBoardGeomBuilder = (circuitJson) => {
31100
31189
  const [boardGeom, setBoardGeom] = useState10(null);
31101
- const isProcessingRef = useRef6(false);
31190
+ const isProcessingRef = useRef7(false);
31102
31191
  useEffect18(() => {
31103
31192
  let isCancelled = false;
31104
31193
  if (!circuitJson) {
@@ -31476,7 +31565,7 @@ import { su as su13 } from "@tscircuit/circuit-json-util";
31476
31565
  import { useEffect as useEffect22, useMemo as useMemo21, useState as useState15 } from "react";
31477
31566
 
31478
31567
  // src/hooks/useManifoldBoardBuilder.ts
31479
- import { useState as useState14, useEffect as useEffect21, useMemo as useMemo20, useRef as useRef7 } from "react";
31568
+ import { useState as useState14, useEffect as useEffect21, useMemo as useMemo20, useRef as useRef8 } from "react";
31480
31569
  import { su as su12 } from "@tscircuit/circuit-json-util";
31481
31570
  import * as THREE24 from "three";
31482
31571
 
@@ -32821,7 +32910,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
32821
32910
  const [pcbThickness, setPcbThickness] = useState14(null);
32822
32911
  const [error, setError] = useState14(null);
32823
32912
  const [isLoading, setIsLoading] = useState14(true);
32824
- const manifoldInstancesForCleanup = useRef7([]);
32913
+ const manifoldInstancesForCleanup = useRef8([]);
32825
32914
  const boardData = useMemo20(() => {
32826
32915
  const boards = su12(circuitJson).pcb_board.list();
32827
32916
  if (boards.length === 0) {
@@ -33470,17 +33559,17 @@ try {
33470
33559
  var CadViewerManifold_default = CadViewerManifold;
33471
33560
 
33472
33561
  // src/hooks/useContextMenu.ts
33473
- import { useState as useState16, useCallback as useCallback8, useRef as useRef8, useEffect as useEffect23 } from "react";
33562
+ import { useState as useState16, useCallback as useCallback8, useRef as useRef9, useEffect as useEffect23 } from "react";
33474
33563
  var useContextMenu = ({ containerRef }) => {
33475
33564
  const [menuVisible, setMenuVisible] = useState16(false);
33476
33565
  const [menuPos, setMenuPos] = useState16({
33477
33566
  x: 0,
33478
33567
  y: 0
33479
33568
  });
33480
- const menuRef = useRef8(null);
33481
- const interactionOriginPosRef = useRef8(null);
33482
- const longPressTimeoutRef = useRef8(null);
33483
- const ignoreNextContextMenuRef = useRef8(false);
33569
+ const menuRef = useRef9(null);
33570
+ const interactionOriginPosRef = useRef9(null);
33571
+ const longPressTimeoutRef = useRef9(null);
33572
+ const ignoreNextContextMenuRef = useRef9(false);
33484
33573
  const clearLongPressTimeout = () => {
33485
33574
  if (longPressTimeoutRef.current !== null) {
33486
33575
  clearTimeout(longPressTimeoutRef.current);
@@ -39594,7 +39683,7 @@ var ContextMenu = ({
39594
39683
  import { jsx as jsx34, jsxs as jsxs10 } from "react/jsx-runtime";
39595
39684
  var CadViewerInner = (props) => {
39596
39685
  const [engine, setEngine] = useState33("manifold");
39597
- const containerRef = useRef22(null);
39686
+ const containerRef = useRef23(null);
39598
39687
  const [autoRotate, setAutoRotate] = useState33(() => {
39599
39688
  const stored = window.localStorage.getItem("cadViewerAutoRotate");
39600
39689
  return stored === "false" ? false : true;
@@ -39605,7 +39694,7 @@ var CadViewerInner = (props) => {
39605
39694
  });
39606
39695
  const [cameraPreset, setCameraPreset] = useState33("Custom");
39607
39696
  const { visibility, toggleLayer } = useLayerVisibility();
39608
- const cameraControllerRef = useRef22(null);
39697
+ const cameraControllerRef = useRef23(null);
39609
39698
  const externalCameraControllerReady = props.onCameraControllerReady;
39610
39699
  const {
39611
39700
  menuVisible,
@@ -39614,10 +39703,10 @@ var CadViewerInner = (props) => {
39614
39703
  contextMenuEventHandlers,
39615
39704
  setMenuVisible
39616
39705
  } = useContextMenu({ containerRef });
39617
- const autoRotateUserToggledRef = useRef22(autoRotateUserToggled);
39706
+ const autoRotateUserToggledRef = useRef23(autoRotateUserToggled);
39618
39707
  autoRotateUserToggledRef.current = autoRotateUserToggled;
39619
- const isAnimatingRef = useRef22(false);
39620
- const lastPresetSelectTime = useRef22(0);
39708
+ const isAnimatingRef = useRef23(false);
39709
+ const lastPresetSelectTime = useRef23(0);
39621
39710
  const PRESET_COOLDOWN = 1e3;
39622
39711
  const handleUserInteraction = useCallback20(() => {
39623
39712
  if (isAnimatingRef.current || Date.now() - lastPresetSelectTime.current < PRESET_COOLDOWN) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.431",
3
+ "version": "0.0.432",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",