@tscircuit/3d-viewer 0.0.609 → 0.0.610

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -41,12 +41,13 @@ interface Props {
41
41
  onCameraControllerReady?: (controller: CameraController | null) => void;
42
42
  resolveStaticAsset?: (modelUrl: string) => string;
43
43
  referenceObject?: ReferenceObjectType | null;
44
+ hiddenCadComponentIds?: ReadonlySet<string>;
44
45
  }
45
46
  declare const CadViewerJscad: React$1.ForwardRefExoticComponent<Props & {
46
47
  children?: React$1.ReactNode | undefined;
47
48
  } & React$1.RefAttributes<THREE.Object3D<THREE.Object3DEventMap>>>;
48
49
 
49
- type CadViewerProps = Omit<React.ComponentProps<typeof CadViewerJscad>, "circuitJson"> & {
50
+ type CadViewerProps = Omit<React.ComponentProps<typeof CadViewerJscad>, "circuitJson" | "hiddenCadComponentIds"> & {
50
51
  circuitJson?: any[];
51
52
  foldPcbs?: boolean;
52
53
  /** Enable right-click navigation using the same identity as the PCB viewer. */
package/dist/index.js CHANGED
@@ -14479,6 +14479,7 @@ var CadComponentGroup = ({
14479
14479
  }) => {
14480
14480
  const scene = useThree();
14481
14481
  const group = useMemo(() => new THREE.Group(), []);
14482
+ group.userData.cad_component_id = cadComponent.cad_component_id;
14482
14483
  group.userData.pcb_component_id = cadComponent.pcb_component_id;
14483
14484
  useEffect(() => {
14484
14485
  scene.rootObject.add(group);
@@ -14493,9 +14494,9 @@ var CadComponentGroup = ({
14493
14494
  return /* @__PURE__ */ jsx(ThreeContext.Provider, { value: context, children });
14494
14495
  };
14495
14496
 
14496
- // src/utils/pick-schematic-component.ts
14497
+ // src/utils/pick-visible-mesh.ts
14497
14498
  import * as THREE2 from "three";
14498
- var pickSchematicComponent = (scene, position, circuitJson) => {
14499
+ var pickVisibleMesh = (scene, position) => {
14499
14500
  if (!scene) return;
14500
14501
  const { camera, rootObject, renderer } = scene;
14501
14502
  const rect = renderer.domElement.getBoundingClientRect();
@@ -14515,31 +14516,39 @@ var pickSchematicComponent = (scene, position, circuitJson) => {
14515
14516
  for (const hit of raycaster.intersectObject(rootObject, true)) {
14516
14517
  if (!(hit.object instanceof THREE2.Mesh)) continue;
14517
14518
  let object = hit.object;
14518
- let pcbComponentId;
14519
14519
  let visible = true;
14520
14520
  while (object) {
14521
14521
  if (!object.visible) visible = false;
14522
- pcbComponentId ??= object.userData.pcb_component_id;
14523
14522
  object = object.parent;
14524
14523
  }
14525
- if (!visible) continue;
14526
- if (!pcbComponentId) return;
14527
- const pcb = circuitJson.find(
14528
- (e) => e.type === "pcb_component" && e.pcb_component_id === pcbComponentId
14529
- );
14530
- if (pcb?.type !== "pcb_component") return;
14531
- const source = circuitJson.find(
14532
- (e) => e.type === "source_component" && e.source_component_id === pcb.source_component_id
14533
- );
14534
- if (source?.type !== "source_component") return;
14535
- return {
14536
- source_component_id: source.source_component_id,
14537
- pcb_component_id: pcb.pcb_component_id,
14538
- refdes: source.name
14539
- };
14524
+ if (visible) return hit.object;
14540
14525
  }
14541
14526
  };
14542
14527
 
14528
+ // src/utils/pick-schematic-component.ts
14529
+ var pickSchematicComponent = (scene, position, circuitJson) => {
14530
+ let object = pickVisibleMesh(scene, position) ?? null;
14531
+ let pcbComponentId;
14532
+ while (object) {
14533
+ pcbComponentId ??= object.userData.pcb_component_id;
14534
+ object = object.parent;
14535
+ }
14536
+ if (!pcbComponentId) return;
14537
+ const pcb = circuitJson.find(
14538
+ (e) => e.type === "pcb_component" && e.pcb_component_id === pcbComponentId
14539
+ );
14540
+ if (pcb?.type !== "pcb_component") return;
14541
+ const source = circuitJson.find(
14542
+ (e) => e.type === "source_component" && e.source_component_id === pcb.source_component_id
14543
+ );
14544
+ if (source?.type !== "source_component") return;
14545
+ return {
14546
+ source_component_id: source.source_component_id,
14547
+ pcb_component_id: pcb.pcb_component_id,
14548
+ refdes: source.name
14549
+ };
14550
+ };
14551
+
14543
14552
  // src/utils/resolve-fold-pcbs.ts
14544
14553
  function resolveFoldPcbs(circuitJson, foldPcbs) {
14545
14554
  return foldPcbs ?? circuitJson.some(
@@ -14547,8 +14556,59 @@ function resolveFoldPcbs(circuitJson, foldPcbs) {
14547
14556
  );
14548
14557
  }
14549
14558
 
14559
+ // src/utils/pick-cad-component.ts
14560
+ var pickCadComponent = (scene, position, circuitJson) => {
14561
+ let object = pickVisibleMesh(scene, position) ?? null;
14562
+ while (object) {
14563
+ const cadComponentId = object.userData.cad_component_id;
14564
+ if (cadComponentId) {
14565
+ const cad = circuitJson.find(
14566
+ (e) => e.type === "cad_component" && e.cad_component_id === cadComponentId
14567
+ );
14568
+ if (cad?.type !== "cad_component") return;
14569
+ const source = circuitJson.find(
14570
+ (e) => e.type === "source_component" && e.source_component_id === cad.source_component_id
14571
+ );
14572
+ return {
14573
+ cad_component_id: cad.cad_component_id,
14574
+ componentName: source?.type === "source_component" ? source.name : cad.cad_component_id
14575
+ };
14576
+ }
14577
+ object = object.parent;
14578
+ }
14579
+ };
14580
+
14581
+ // src/hooks/useHiddenCadComponents.ts
14582
+ import { useState } from "react";
14583
+ var NO_HIDDEN_COMPONENTS = /* @__PURE__ */ new Set();
14584
+ var useHiddenCadComponents = (circuitKey) => {
14585
+ const [state, setState] = useState({
14586
+ circuitKey,
14587
+ ids: NO_HIDDEN_COMPONENTS
14588
+ });
14589
+ const hiddenCadComponentIds = state.circuitKey === circuitKey ? state.ids : NO_HIDDEN_COMPONENTS;
14590
+ if (state.circuitKey !== circuitKey) {
14591
+ setState({ circuitKey, ids: NO_HIDDEN_COMPONENTS });
14592
+ }
14593
+ return {
14594
+ hiddenCadComponentIds,
14595
+ hideComponent: (id) => {
14596
+ setState((current) => ({
14597
+ circuitKey,
14598
+ ids: /* @__PURE__ */ new Set([
14599
+ ...current.circuitKey === circuitKey ? current.ids : [],
14600
+ id
14601
+ ])
14602
+ }));
14603
+ },
14604
+ unhideAllComponents: () => {
14605
+ setState({ circuitKey, ids: NO_HIDDEN_COMPONENTS });
14606
+ }
14607
+ };
14608
+ };
14609
+
14550
14610
  // src/CadViewer.tsx
14551
- import { useCallback as useCallback24, useContext as useContext10, useEffect as useEffect50, useRef as useRef29, useState as useState40 } from "react";
14611
+ import { useCallback as useCallback24, useContext as useContext10, useEffect as useEffect50, useRef as useRef29, useState as useState41 } from "react";
14552
14612
  import * as THREE54 from "three";
14553
14613
 
14554
14614
  // src/hooks/use-convert-children-to-soup.ts
@@ -14586,13 +14646,13 @@ var getCadPcbContext = (cad, circuitJson) => {
14586
14646
 
14587
14647
  // src/AnyCadComponent.tsx
14588
14648
  import { su as su2 } from "@tscircuit/circuit-json-util";
14589
- import { useCallback as useCallback3, useEffect as useEffect12, useMemo as useMemo10, useState as useState7 } from "react";
14649
+ import { useCallback as useCallback3, useEffect as useEffect12, useMemo as useMemo10, useState as useState8 } from "react";
14590
14650
 
14591
14651
  // src/contexts/LayerVisibilityContext.tsx
14592
14652
  import {
14593
14653
  createContext as createContext3,
14594
14654
  useContext as useContext3,
14595
- useState,
14655
+ useState as useState2,
14596
14656
  useCallback,
14597
14657
  useMemo as useMemo3
14598
14658
  } from "react";
@@ -14628,7 +14688,7 @@ var defaultVisibility = {
14628
14688
  };
14629
14689
  var LayerVisibilityContext = createContext3(void 0);
14630
14690
  var LayerVisibilityProvider = ({ children }) => {
14631
- const [visibility, setVisibility] = useState(defaultVisibility);
14691
+ const [visibility, setVisibility] = useState2(defaultVisibility);
14632
14692
  const setLayerVisibility = useCallback(
14633
14693
  (layer, visible) => {
14634
14694
  setVisibility((prev) => ({
@@ -14678,7 +14738,7 @@ function usePcbThickness(circuitJson) {
14678
14738
  }
14679
14739
 
14680
14740
  // src/react-three/Html.tsx
14681
- import { useRef, useEffect as useEffect3, useState as useState2 } from "react";
14741
+ import { useRef, useEffect as useEffect3, useState as useState3 } from "react";
14682
14742
  import ReactDOM from "react-dom";
14683
14743
  import * as THREE3 from "three";
14684
14744
 
@@ -14695,7 +14755,7 @@ var zIndexMap = {
14695
14755
  var Html = ({ children, position, style }) => {
14696
14756
  const { camera, renderer } = useThree();
14697
14757
  const el = useRef(document.createElement("div"));
14698
- const [portal, setPortal] = useState2(null);
14758
+ const [portal, setPortal] = useState3(null);
14699
14759
  useEffect3(() => {
14700
14760
  const rendererNode = renderer?.domElement.parentNode;
14701
14761
  if (!rendererNode) return;
@@ -37549,7 +37609,7 @@ import { useEffect as useEffect5 } from "react";
37549
37609
  import {
37550
37610
  createContext as createContext4,
37551
37611
  useContext as useContext4,
37552
- useState as useState3,
37612
+ useState as useState4,
37553
37613
  useCallback as useCallback2,
37554
37614
  useMemo as useMemo5,
37555
37615
  useEffect as useEffect4,
@@ -37567,7 +37627,7 @@ var useHover = () => {
37567
37627
  };
37568
37628
  var HoverProvider = ({ children }) => {
37569
37629
  const { camera, renderer } = useThree();
37570
- const [hoverables, setHoverables] = useState3([]);
37630
+ const [hoverables, setHoverables] = useState4([]);
37571
37631
  const raycaster = useMemo5(() => new THREE4.Raycaster(), []);
37572
37632
  const mouse = useMemo5(() => new THREE4.Vector2(), []);
37573
37633
  const hoverablesRef = useRef2(hoverables);
@@ -37799,7 +37859,7 @@ var FootprinterModel = ({
37799
37859
  };
37800
37860
 
37801
37861
  // src/three-components/GltfModel.tsx
37802
- import { useState as useState4, useEffect as useEffect8 } from "react";
37862
+ import { useState as useState5, useEffect as useEffect8 } from "react";
37803
37863
  import * as THREE10 from "three";
37804
37864
  import { GLTFLoader } from "three-stdlib";
37805
37865
 
@@ -38013,8 +38073,8 @@ function GltfModel({
38013
38073
  isTranslucent = false
38014
38074
  }) {
38015
38075
  const { renderer } = useThree();
38016
- const [model, setModel] = useState4(null);
38017
- const [loadError, setLoadError] = useState4(null);
38076
+ const [model, setModel] = useState5(null);
38077
+ const [loadError, setLoadError] = useState5(null);
38018
38078
  const { boardTransformGroup } = useCadModelTransformGraph({
38019
38079
  model,
38020
38080
  position,
@@ -38216,7 +38276,7 @@ var JscadModel = ({
38216
38276
  };
38217
38277
 
38218
38278
  // src/hooks/use-global-obj-loader.ts
38219
- import { useEffect as useEffect10, useState as useState5 } from "react";
38279
+ import { useEffect as useEffect10, useState as useState6 } from "react";
38220
38280
 
38221
38281
  // src/utils/vrml.ts
38222
38282
  import { VRMLLoader } from "three-stdlib";
@@ -38243,7 +38303,7 @@ if (typeof window !== "undefined" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {
38243
38303
  window.TSCIRCUIT_OBJ_LOADER_CACHE = /* @__PURE__ */ new Map();
38244
38304
  }
38245
38305
  function useGlobalObjLoader(url) {
38246
- const [obj, setObj] = useState5(null);
38306
+ const [obj, setObj] = useState6(null);
38247
38307
  useEffect10(() => {
38248
38308
  if (!url) return;
38249
38309
  const cleanUrl = url.replace(/&cachebust_origin=$/, "");
@@ -38397,7 +38457,7 @@ function MixedStlModel({
38397
38457
  }
38398
38458
 
38399
38459
  // src/three-components/StepModel.tsx
38400
- import { useEffect as useEffect11, useState as useState6 } from "react";
38460
+ import { useEffect as useEffect11, useState as useState7 } from "react";
38401
38461
  import { GLTFExporter } from "three-stdlib";
38402
38462
 
38403
38463
  // src/three-components/step-mesh-to-group.ts
@@ -38611,7 +38671,7 @@ var StepModel = ({
38611
38671
  isHovered,
38612
38672
  isTranslucent
38613
38673
  }) => {
38614
- const [stepGltfUrl, setStepGltfUrl] = useState6(null);
38674
+ const [stepGltfUrl, setStepGltfUrl] = useState7(null);
38615
38675
  useEffect11(() => {
38616
38676
  let isActive = true;
38617
38677
  let objectUrl = null;
@@ -39049,9 +39109,9 @@ var AnyCadComponent = ({
39049
39109
  resolveStaticAsset
39050
39110
  }) => {
39051
39111
  const pcbThickness = usePcbThickness(circuitJson);
39052
- const [isHovered, setIsHovered] = useState7(false);
39112
+ const [isHovered, setIsHovered] = useState8(false);
39053
39113
  const { visibility } = useLayerVisibility();
39054
- const [hoverPosition, setHoverPosition] = useState7(null);
39114
+ const [hoverPosition, setHoverPosition] = useState8(null);
39055
39115
  const handleHover = useCallback3((e) => {
39056
39116
  if (e?.mousePosition) {
39057
39117
  setIsHovered(true);
@@ -39087,8 +39147,8 @@ var AnyCadComponent = ({
39087
39147
  const stepUrl = resolveModelUrlWithStaticResolver(
39088
39148
  cad_component.model_step_url
39089
39149
  );
39090
- const [fallbackModelIndex, setFallbackModelIndex] = useState7(0);
39091
- const [lastModelError, setLastModelError] = useState7(null);
39150
+ const [fallbackModelIndex, setFallbackModelIndex] = useState8(0);
39151
+ const [lastModelError, setLastModelError] = useState8(null);
39092
39152
  useEffect12(() => {
39093
39153
  setFallbackModelIndex(0);
39094
39154
  setLastModelError(null);
@@ -39309,13 +39369,13 @@ var AnyCadComponent = ({
39309
39369
  };
39310
39370
 
39311
39371
  // src/CadViewerContainer.tsx
39312
- import { forwardRef as forwardRef2, useEffect as useEffect21, useMemo as useMemo18, useState as useState11 } from "react";
39372
+ import { forwardRef as forwardRef2, useEffect as useEffect21, useMemo as useMemo18, useState as useState12 } from "react";
39313
39373
  import * as THREE25 from "three";
39314
39374
 
39315
39375
  // package.json
39316
39376
  var package_default = {
39317
39377
  name: "@tscircuit/3d-viewer",
39318
- version: "0.0.608",
39378
+ version: "0.0.609",
39319
39379
  repository: {
39320
39380
  type: "git",
39321
39381
  url: "https://github.com/tscircuit/3d-viewer"
@@ -39413,7 +39473,7 @@ var package_default = {
39413
39473
  };
39414
39474
 
39415
39475
  // src/contexts/appearance-context.tsx
39416
- import { createContext as createContext5, useContext as useContext5, useEffect as useEffect13, useMemo as useMemo11, useState as useState8 } from "react";
39476
+ import { createContext as createContext5, useContext as useContext5, useEffect as useEffect13, useMemo as useMemo11, useState as useState9 } from "react";
39417
39477
  import { jsx as jsx12 } from "react/jsx-runtime";
39418
39478
  var LIGHTING_STORAGE_KEY = "cadViewerLightingEnabled";
39419
39479
  var readStoredLightingEnabled = () => {
@@ -39426,9 +39486,9 @@ var AppearanceContext = createContext5(
39426
39486
  var AppearanceProvider = ({
39427
39487
  children
39428
39488
  }) => {
39429
- const [darkBackgroundEnabled, setDarkBackgroundEnabled] = useState8(false);
39430
- const [gridEnabled, setGridEnabled] = useState8(false);
39431
- const [lightingEnabled, setLightingEnabled] = useState8(
39489
+ const [darkBackgroundEnabled, setDarkBackgroundEnabled] = useState9(false);
39490
+ const [gridEnabled, setGridEnabled] = useState9(false);
39491
+ const [lightingEnabled, setLightingEnabled] = useState9(
39432
39492
  readStoredLightingEnabled
39433
39493
  );
39434
39494
  useEffect13(() => {
@@ -39465,7 +39525,7 @@ import {
39465
39525
  useContext as useContext6,
39466
39526
  useMemo as useMemo12,
39467
39527
  useRef as useRef3,
39468
- useState as useState9
39528
+ useState as useState10
39469
39529
  } from "react";
39470
39530
  import * as THREE15 from "three";
39471
39531
  import { jsx as jsx13 } from "react/jsx-runtime";
@@ -39510,12 +39570,12 @@ var CameraControllerContext = createContext6(void 0);
39510
39570
  var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition, initialCameraType }) => {
39511
39571
  const controlsRef = useRef3(null);
39512
39572
  const mainCameraRef = useRef3(null);
39513
- const [controller, setController] = useState9(null);
39514
- const [cameraType, setCameraType] = useState9(
39573
+ const [controller, setController] = useState10(null);
39574
+ const [cameraType, setCameraType] = useState10(
39515
39575
  initialCameraType ?? "perspective"
39516
39576
  );
39517
- const [cameraPosition, setCameraPosition] = useState9(initialCameraPosition ?? null);
39518
- const [cameraRotation, setCameraRotation] = useState9(
39577
+ const [cameraPosition, setCameraPosition] = useState10(initialCameraPosition ?? null);
39578
+ const [cameraRotation, setCameraRotation] = useState10(
39519
39579
  new THREE15.Euler(0, 0, 0)
39520
39580
  );
39521
39581
  const baseDistance = useMemo12(() => {
@@ -39857,7 +39917,7 @@ var useCameraSession = () => {
39857
39917
  import {
39858
39918
  useRef as useRef6,
39859
39919
  useEffect as useEffect15,
39860
- useState as useState10,
39920
+ useState as useState11,
39861
39921
  useCallback as useCallback7,
39862
39922
  forwardRef,
39863
39923
  useImperativeHandle,
@@ -39886,7 +39946,7 @@ var Canvas = forwardRef(
39886
39946
  ({ children, scene: sceneProps, camera: cameraProps, style, onCreated }, ref) => {
39887
39947
  const { cameraType } = useCameraController();
39888
39948
  const mountRef = useRef6(null);
39889
- const [contextState, setContextState] = useState10(
39949
+ const [contextState, setContextState] = useState11(
39890
39950
  null
39891
39951
  );
39892
39952
  const frameListeners = useRef6(
@@ -41002,7 +41062,7 @@ var CadViewerContainer = forwardRef2(
41002
41062
  onUserInteraction,
41003
41063
  onCameraControllerReady
41004
41064
  }, ref) => {
41005
- const [isInteractionEnabled, setIsInteractionEnabled] = useState11(
41065
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState12(
41006
41066
  !clickToInteractEnabled
41007
41067
  );
41008
41068
  const { mainCameraRef, handleControlsChange, controller } = useCameraController();
@@ -41161,11 +41221,11 @@ var CadViewerContainer = forwardRef2(
41161
41221
  );
41162
41222
 
41163
41223
  // src/hooks/use-stls-from-geom.ts
41164
- import { useState as useState12, useEffect as useEffect22 } from "react";
41224
+ import { useState as useState13, useEffect as useEffect22 } from "react";
41165
41225
  import stlSerializer from "@jscad/stl-serializer";
41166
41226
  var useStlsFromGeom = (geom) => {
41167
- const [stls, setStls] = useState12([]);
41168
- const [loading, setLoading] = useState12(true);
41227
+ const [stls, setStls] = useState13([]);
41228
+ const [loading, setLoading] = useState13(true);
41169
41229
  useEffect22(() => {
41170
41230
  if (!geom) return;
41171
41231
  const generateStls = async () => {
@@ -41195,7 +41255,7 @@ var useStlsFromGeom = (geom) => {
41195
41255
  };
41196
41256
 
41197
41257
  // src/hooks/useBoardGeomBuilder.ts
41198
- import { useState as useState13, useEffect as useEffect23, useRef as useRef8 } from "react";
41258
+ import { useState as useState14, useEffect as useEffect23, useRef as useRef8 } from "react";
41199
41259
 
41200
41260
  // src/soup-to-3d/index.ts
41201
41261
  var import_colors = __toESM(require_colors(), 1);
@@ -42637,7 +42697,7 @@ var BoardGeomBuilder = class {
42637
42697
 
42638
42698
  // src/hooks/useBoardGeomBuilder.ts
42639
42699
  var useBoardGeomBuilder = (circuitJson) => {
42640
- const [boardGeom, setBoardGeom] = useState13(null);
42700
+ const [boardGeom, setBoardGeom] = useState14(null);
42641
42701
  const isProcessingRef = useRef8(false);
42642
42702
  useEffect23(() => {
42643
42703
  let isCancelled = false;
@@ -42685,7 +42745,7 @@ var useBoardGeomBuilder = (circuitJson) => {
42685
42745
  };
42686
42746
 
42687
42747
  // src/three-components/Error3d.tsx
42688
- import { useState as useState14, useCallback as useCallback8, useEffect as useEffect25, useMemo as useMemo20 } from "react";
42748
+ import { useState as useState15, useCallback as useCallback8, useEffect as useEffect25, useMemo as useMemo20 } from "react";
42689
42749
 
42690
42750
  // src/react-three/Text.tsx
42691
42751
  import { useEffect as useEffect24, useMemo as useMemo19 } from "react";
@@ -42748,8 +42808,8 @@ var Error3d = ({
42748
42808
  cad_component
42749
42809
  }) => {
42750
42810
  const { rootObject } = useThree();
42751
- const [isHovered, setIsHovered] = useState14(false);
42752
- const [hoverPosition, setHoverPosition] = useState14(null);
42811
+ const [isHovered, setIsHovered] = useState15(false);
42812
+ const [hoverPosition, setHoverPosition] = useState15(null);
42753
42813
  const handleHover = useCallback8((e) => {
42754
42814
  if (e?.mousePosition) {
42755
42815
  setIsHovered(true);
@@ -42779,6 +42839,8 @@ var Error3d = ({
42779
42839
  g.position.fromArray(position);
42780
42840
  return g;
42781
42841
  }, [position]);
42842
+ group.userData.cad_component_id = cad_component?.cad_component_id;
42843
+ group.userData.pcb_component_id = cad_component?.pcb_component_id;
42782
42844
  useEffect25(() => {
42783
42845
  if (!rootObject) return;
42784
42846
  rootObject.add(group);
@@ -45183,7 +45245,7 @@ function JscadBoardTextures({
45183
45245
  }
45184
45246
 
45185
45247
  // src/three-components/STLModel.tsx
45186
- import { useState as useState15, useEffect as useEffect27, useMemo as useMemo22 } from "react";
45248
+ import { useState as useState16, useEffect as useEffect27, useMemo as useMemo22 } from "react";
45187
45249
  import * as THREE45 from "three";
45188
45250
  import { STLLoader } from "three-stdlib";
45189
45251
  function STLModel({
@@ -45195,7 +45257,7 @@ function STLModel({
45195
45257
  layerType
45196
45258
  }) {
45197
45259
  const { rootObject } = useThree();
45198
- const [geom, setGeom] = useState15(null);
45260
+ const [geom, setGeom] = useState16(null);
45199
45261
  useEffect27(() => {
45200
45262
  const loader = new STLLoader();
45201
45263
  if (stlData) {
@@ -45383,7 +45445,8 @@ var CadViewerJscad = forwardRef3(
45383
45445
  onUserInteraction,
45384
45446
  onCameraControllerReady,
45385
45447
  resolveStaticAsset,
45386
- referenceObject
45448
+ referenceObject,
45449
+ hiddenCadComponentIds
45387
45450
  }, ref) => {
45388
45451
  const childrenSoup = useConvertChildrenToCircuitJson(children);
45389
45452
  const internalCircuitJson = useMemo23(() => {
@@ -45453,7 +45516,7 @@ var CadViewerJscad = forwardRef3(
45453
45516
  }, [internalCircuitJson]);
45454
45517
  const pcbThickness = usePcbThickness(internalCircuitJson);
45455
45518
  const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
45456
- const cad_components = su12(internalCircuitJson).cad_component.list();
45519
+ const cad_components = su12(internalCircuitJson).cad_component.list().filter((cad) => !hiddenCadComponentIds?.has(cad.cad_component_id));
45457
45520
  return /* @__PURE__ */ jsxs5(
45458
45521
  CadViewerContainer,
45459
45522
  {
@@ -45710,15 +45773,11 @@ function indexSegment(head, stop) {
45710
45773
  do {
45711
45774
  const b = numBlocks++;
45712
45775
  blockHead[b] = p;
45713
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
45776
+ let minX = p.x, minY = p.y, maxX = p.x, maxY = p.y;
45714
45777
  let k = 0;
45715
45778
  do {
45716
45779
  const c = p.next;
45717
45780
  p.z = b;
45718
- if (p.x < minX) minX = p.x;
45719
- if (p.x > maxX) maxX = p.x;
45720
- if (p.y < minY) minY = p.y;
45721
- if (p.y > maxY) maxY = p.y;
45722
45781
  if (c.x < minX) minX = c.x;
45723
45782
  if (c.x > maxX) maxX = c.x;
45724
45783
  if (c.y < minY) minY = c.y;
@@ -45827,6 +45886,20 @@ function indexCurve(start, minX, minY, invSize) {
45827
45886
  prev = node;
45828
45887
  }
45829
45888
  prev.nextZ = null;
45889
+ sortArr.fill(
45890
+ /** @type {Node} */
45891
+ /** @type {unknown} */
45892
+ null,
45893
+ 0,
45894
+ n
45895
+ );
45896
+ sortBuf.fill(
45897
+ /** @type {Node} */
45898
+ /** @type {unknown} */
45899
+ null,
45900
+ 0,
45901
+ n
45902
+ );
45830
45903
  }
45831
45904
  function sortNodes(n) {
45832
45905
  if (n <= 32) {
@@ -46630,12 +46703,12 @@ function createFlexMeshes(geometryMeshes, textureMeshes, json, foldPcbs) {
46630
46703
 
46631
46704
  // src/CadViewerManifold.tsx
46632
46705
  import { su as su17 } from "@tscircuit/circuit-json-util";
46633
- import { useEffect as useEffect29, useMemo as useMemo25, useState as useState17 } from "react";
46706
+ import { useEffect as useEffect29, useMemo as useMemo25, useState as useState18 } from "react";
46634
46707
  import * as THREE53 from "three";
46635
46708
 
46636
46709
  // src/hooks/useManifoldBoardBuilder.ts
46637
46710
  import { su as su16 } from "@tscircuit/circuit-json-util";
46638
- import { useEffect as useEffect28, useMemo as useMemo24, useRef as useRef9, useState as useState16 } from "react";
46711
+ import { useEffect as useEffect28, useMemo as useMemo24, useRef as useRef9, useState as useState17 } from "react";
46639
46712
  import * as THREE50 from "three";
46640
46713
 
46641
46714
  // src/utils/manifold/create-manifold-board.ts
@@ -47750,10 +47823,10 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
47750
47823
 
47751
47824
  // src/hooks/useManifoldBoardBuilder.ts
47752
47825
  var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
47753
- const [geoms, setGeoms] = useState16(null);
47754
- const [pcbThickness, setPcbThickness] = useState16(null);
47755
- const [error, setError] = useState16(null);
47756
- const [isLoading, setIsLoading] = useState16(true);
47826
+ const [geoms, setGeoms] = useState17(null);
47827
+ const [pcbThickness, setPcbThickness] = useState17(null);
47828
+ const [error, setError] = useState17(null);
47829
+ const [isLoading, setIsLoading] = useState17(true);
47757
47830
  const manifoldInstancesForCleanup = useRef9([]);
47758
47831
  const boardData = useMemo24(() => {
47759
47832
  const panels = circuitJson.filter(
@@ -48157,15 +48230,16 @@ var CadViewerManifold = ({
48157
48230
  children,
48158
48231
  onCameraControllerReady,
48159
48232
  resolveStaticAsset,
48160
- referenceObject
48233
+ referenceObject,
48234
+ hiddenCadComponentIds
48161
48235
  }) => {
48162
48236
  const childrenCircuitJson = useConvertChildrenToCircuitJson(children);
48163
48237
  const circuitJson = useMemo25(() => {
48164
48238
  const rawCircuitJson = circuitJsonProp ?? childrenCircuitJson;
48165
48239
  return addFauxBoardIfNeeded(rawCircuitJson);
48166
48240
  }, [circuitJsonProp, childrenCircuitJson]);
48167
- const [manifoldJSModule, setManifoldJSModule] = useState17(null);
48168
- const [manifoldLoadingError, setManifoldLoadingError] = useState17(null);
48241
+ const [manifoldJSModule, setManifoldJSModule] = useState18(null);
48242
+ const [manifoldLoadingError, setManifoldLoadingError] = useState18(null);
48169
48243
  const { visibility } = useLayerVisibility();
48170
48244
  useEffect29(() => {
48171
48245
  if (window.ManifoldModule && typeof window.ManifoldModule === "object" && window.ManifoldModule.setup) {
@@ -48270,8 +48344,8 @@ try {
48270
48344
  foldPcbs
48271
48345
  ]);
48272
48346
  const cadComponents = useMemo25(
48273
- () => su17(flex.posedJson).cad_component.list(),
48274
- [flex.posedJson]
48347
+ () => su17(flex.posedJson).cad_component.list().filter((cad) => !hiddenCadComponentIds?.has(cad.cad_component_id)),
48348
+ [flex.posedJson, hiddenCadComponentIds]
48275
48349
  );
48276
48350
  const boardDimensions = useMemo25(() => {
48277
48351
  if (!boardData) return void 0;
@@ -52970,9 +53044,9 @@ function assignRef(ref, value) {
52970
53044
  }
52971
53045
 
52972
53046
  // node_modules/use-callback-ref/dist/es2015/useRef.js
52973
- import { useState as useState30 } from "react";
53047
+ import { useState as useState31 } from "react";
52974
53048
  function useCallbackRef2(initialValue, callback) {
52975
- var ref = useState30(function() {
53049
+ var ref = useState31(function() {
52976
53050
  return {
52977
53051
  // value
52978
53052
  value: initialValue,
@@ -54583,11 +54657,11 @@ var SubTrigger2 = DropdownMenuSubTrigger;
54583
54657
  var SubContent2 = DropdownMenuSubContent;
54584
54658
 
54585
54659
  // src/components/ViewportSubContent.tsx
54586
- import { useLayoutEffect as useLayoutEffect5, useState as useState34 } from "react";
54660
+ import { useLayoutEffect as useLayoutEffect5, useState as useState35 } from "react";
54587
54661
  import { jsx as jsx33 } from "react/jsx-runtime";
54588
54662
  var ViewportSubContent = (props) => {
54589
- const [content, setContent] = useState34(null);
54590
- const [overlapWidth, setOverlapWidth] = useState34();
54663
+ const [content, setContent] = useState35(null);
54664
+ const [overlapWidth, setOverlapWidth] = useState35();
54591
54665
  useLayoutEffect5(() => {
54592
54666
  if (!content) return;
54593
54667
  const trigger = document.getElementById(
@@ -54642,10 +54716,10 @@ var menuViewportStyles = {
54642
54716
  };
54643
54717
 
54644
54718
  // src/components/ContextMenu.tsx
54645
- import { useState as useState36 } from "react";
54719
+ import { useState as useState37 } from "react";
54646
54720
 
54647
54721
  // src/components/AppearanceMenu.tsx
54648
- import { useState as useState35 } from "react";
54722
+ import { useState as useState36 } from "react";
54649
54723
 
54650
54724
  // src/components/Icons.tsx
54651
54725
  import { jsx as jsx34 } from "react/jsx-runtime";
@@ -54772,8 +54846,8 @@ var AppearanceMenu = () => {
54772
54846
  lightingEnabled,
54773
54847
  setLightingEnabled
54774
54848
  } = useAppearance();
54775
- const [appearanceSubOpen, setAppearanceSubOpen] = useState35(false);
54776
- const [hoveredItem, setHoveredItem] = useState35(null);
54849
+ const [appearanceSubOpen, setAppearanceSubOpen] = useState36(false);
54850
+ const [hoveredItem, setHoveredItem] = useState36(null);
54777
54851
  return /* @__PURE__ */ jsxs7(Fragment10, { children: [
54778
54852
  /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles }),
54779
54853
  /* @__PURE__ */ jsxs7(Sub2, { onOpenChange: setAppearanceSubOpen, children: [
@@ -55214,14 +55288,17 @@ var ContextMenu = ({
55214
55288
  onReferenceObjectSelect = () => {
55215
55289
  },
55216
55290
  onViewSchematicComponent,
55291
+ componentName,
55292
+ onHideComponent,
55293
+ onUnhideAllComponents,
55217
55294
  onDownloadGltf,
55218
55295
  onOpenKeyboardShortcuts
55219
55296
  }) => {
55220
55297
  const { cameraType, setCameraType } = useCameraController();
55221
55298
  const { gridEnabled, setGridEnabled } = useAppearance();
55222
- const [cameraSubOpen, setCameraSubOpen] = useState36(false);
55223
- const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState36(false);
55224
- const [hoveredItem, setHoveredItem] = useState36(null);
55299
+ const [cameraSubOpen, setCameraSubOpen] = useState37(false);
55300
+ const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState37(false);
55301
+ const [hoveredItem, setHoveredItem] = useState37(null);
55225
55302
  return /* @__PURE__ */ jsx36(
55226
55303
  "div",
55227
55304
  {
@@ -55244,23 +55321,49 @@ var ContextMenu = ({
55244
55321
  sideOffset: 0,
55245
55322
  align: "start",
55246
55323
  children: [
55247
- onViewSchematicComponent && /* @__PURE__ */ jsxs8(Fragment11, { children: [
55248
- /* @__PURE__ */ jsx36(
55249
- Item22,
55250
- {
55251
- style: {
55252
- ...itemStyles2,
55253
- ...itemPaddingStyles2,
55254
- backgroundColor: hoveredItem === "schematic" ? "#404040" : "transparent"
55255
- },
55256
- onSelect: onViewSchematicComponent,
55257
- onMouseEnter: () => setHoveredItem("schematic"),
55258
- onMouseLeave: () => setHoveredItem(null),
55259
- children: "Show on schematic"
55260
- }
55261
- ),
55262
- /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 })
55263
- ] }),
55324
+ onViewSchematicComponent && /* @__PURE__ */ jsx36(Fragment11, { children: /* @__PURE__ */ jsx36(
55325
+ Item22,
55326
+ {
55327
+ style: {
55328
+ ...itemStyles2,
55329
+ ...itemPaddingStyles2,
55330
+ backgroundColor: hoveredItem === "schematic" ? "#404040" : "transparent"
55331
+ },
55332
+ onSelect: onViewSchematicComponent,
55333
+ onMouseEnter: () => setHoveredItem("schematic"),
55334
+ onMouseLeave: () => setHoveredItem(null),
55335
+ children: "Show on schematic"
55336
+ }
55337
+ ) }),
55338
+ onHideComponent && /* @__PURE__ */ jsx36(
55339
+ Item22,
55340
+ {
55341
+ style: {
55342
+ ...itemStyles2,
55343
+ ...itemPaddingStyles2,
55344
+ backgroundColor: hoveredItem === "hide" ? "#404040" : "transparent"
55345
+ },
55346
+ onSelect: onHideComponent,
55347
+ onMouseEnter: () => setHoveredItem("hide"),
55348
+ onMouseLeave: () => setHoveredItem(null),
55349
+ children: `Hide "${componentName}"`
55350
+ }
55351
+ ),
55352
+ onUnhideAllComponents && /* @__PURE__ */ jsx36(
55353
+ Item22,
55354
+ {
55355
+ style: {
55356
+ ...itemStyles2,
55357
+ ...itemPaddingStyles2,
55358
+ backgroundColor: hoveredItem === "unhide" ? "#404040" : "transparent"
55359
+ },
55360
+ onSelect: onUnhideAllComponents,
55361
+ onMouseEnter: () => setHoveredItem("unhide"),
55362
+ onMouseLeave: () => setHoveredItem(null),
55363
+ children: "Unhide All Components"
55364
+ }
55365
+ ),
55366
+ (onViewSchematicComponent || onHideComponent || onUnhideAllComponents) && /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55264
55367
  /* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setCameraSubOpen, children: [
55265
55368
  /* @__PURE__ */ jsxs8(
55266
55369
  SubTrigger2,
@@ -55603,10 +55706,10 @@ var ContextMenu = ({
55603
55706
  };
55604
55707
 
55605
55708
  // src/components/KeyboardShortcutsDialog.tsx
55606
- import { useEffect as useEffect48, useMemo as useMemo33, useRef as useRef27, useState as useState38 } from "react";
55709
+ import { useEffect as useEffect48, useMemo as useMemo33, useRef as useRef27, useState as useState39 } from "react";
55607
55710
 
55608
55711
  // src/hooks/useRegisteredHotkey.ts
55609
- import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef26, useState as useState37 } from "react";
55712
+ import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef26, useState as useState38 } from "react";
55610
55713
  var hotkeyRegistry = /* @__PURE__ */ new Map();
55611
55714
  var subscribers = /* @__PURE__ */ new Set();
55612
55715
  var isListenerAttached = false;
@@ -55750,7 +55853,7 @@ var useRegisteredHotkey = (id, handler, metadata) => {
55750
55853
  }, [id, normalizedMetadata]);
55751
55854
  };
55752
55855
  var useHotkeyRegistry = () => {
55753
- const [entries, setEntries] = useState37(
55856
+ const [entries, setEntries] = useState38(
55754
55857
  () => Array.from(hotkeyRegistry.values())
55755
55858
  );
55756
55859
  useEffect47(() => subscribeToRegistry(setEntries), []);
@@ -55767,7 +55870,7 @@ var KeyboardShortcutsDialog = ({
55767
55870
  open,
55768
55871
  onClose
55769
55872
  }) => {
55770
- const [query, setQuery] = useState38("");
55873
+ const [query, setQuery] = useState39("");
55771
55874
  const inputRef = useRef27(null);
55772
55875
  const hotkeys = useHotkeyRegistry();
55773
55876
  useEffect48(() => {
@@ -56010,10 +56113,10 @@ function useCameraPreset({
56010
56113
  }
56011
56114
 
56012
56115
  // src/hooks/useContextMenu.ts
56013
- import { useState as useState39, useCallback as useCallback22, useRef as useRef28, useEffect as useEffect49 } from "react";
56116
+ import { useState as useState40, useCallback as useCallback22, useRef as useRef28, useEffect as useEffect49 } from "react";
56014
56117
  var useContextMenu = ({ containerRef, onOpen }) => {
56015
- const [menuVisible, setMenuVisible] = useState39(false);
56016
- const [menuPos, setMenuPos] = useState39({
56118
+ const [menuVisible, setMenuVisible] = useState40(false);
56119
+ const [menuPos, setMenuPos] = useState40({
56017
56120
  x: 0,
56018
56121
  y: 0
56019
56122
  });
@@ -56205,37 +56308,48 @@ var CadViewerInner = (props) => {
56205
56308
  const circuitJson = props.circuitJson ?? childrenCircuitJson;
56206
56309
  const hasBends = circuitJson.some((element) => element.type === "pcb_bend");
56207
56310
  const hasFlexGeometry = hasBends || circuitJson.some((element) => element.type === "pcb_stiffener");
56208
- const [foldPcbsOverride, setFoldPcbs] = useState40(
56311
+ const [foldPcbsOverride, setFoldPcbs] = useState41(
56209
56312
  void 0
56210
56313
  );
56211
56314
  const foldPcbs = foldPcbsOverride ?? props.foldPcbs;
56212
56315
  const resolvedFoldPcbs = resolveFoldPcbs(circuitJson, foldPcbs);
56213
- const resolvedProps = { ...props, circuitJson, children: void 0 };
56214
- const [engine, setEngine] = useState40(() => {
56316
+ const circuitKey = JSON.stringify(circuitJson);
56317
+ const { hiddenCadComponentIds, hideComponent, unhideAllComponents } = useHiddenCadComponents(circuitKey);
56318
+ const resolvedProps = {
56319
+ ...props,
56320
+ circuitJson,
56321
+ children: void 0,
56322
+ hiddenCadComponentIds
56323
+ };
56324
+ const [engine, setEngine] = useState41(() => {
56215
56325
  const stored = window.localStorage.getItem("cadViewerEngine");
56216
56326
  return stored === "jscad" || stored === "manifold" ? stored : "manifold";
56217
56327
  });
56218
56328
  const containerRef = useRef29(null);
56219
- const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState40(false);
56220
- const [autoRotate, setAutoRotate] = useState40(() => {
56329
+ const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState41(false);
56330
+ const [autoRotate, setAutoRotate] = useState41(() => {
56221
56331
  const stored = window.localStorage.getItem("cadViewerAutoRotate");
56222
56332
  return stored !== "false";
56223
56333
  });
56224
- const [autoRotateUserToggled, setAutoRotateUserToggled] = useState40(() => {
56334
+ const [autoRotateUserToggled, setAutoRotateUserToggled] = useState41(() => {
56225
56335
  const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled");
56226
56336
  return stored === "true";
56227
56337
  });
56228
- const [cameraPreset, setCameraPreset] = useState40("Custom");
56229
- const [referenceObject, setReferenceObject] = useState40(null);
56338
+ const [cameraPreset, setCameraPreset] = useState41("Custom");
56339
+ const [referenceObject, setReferenceObject] = useState41(null);
56230
56340
  const { cameraType } = useCameraController();
56231
56341
  const { visibility, setLayerVisibility } = useLayerVisibility();
56232
56342
  const { showToast } = useToast();
56233
56343
  const cameraControllerRef = useRef29(null);
56234
56344
  const externalCameraControllerReady = props.onCameraControllerReady;
56235
56345
  const sceneRef = useContext10(SchematicNavigationContext);
56236
- const [selectedComponent, setSelectedComponent] = useState40();
56346
+ const [selectedComponent, setSelectedComponent] = useState41();
56347
+ const [selectedCadComponent, setSelectedCadComponent] = useState41();
56237
56348
  const handleMenuOpen = useCallback24(
56238
56349
  (position) => {
56350
+ setSelectedCadComponent(
56351
+ pickCadComponent(sceneRef.current, position, circuitJson)
56352
+ );
56239
56353
  setSelectedComponent(
56240
56354
  props.onViewSchematicComponent ? pickSchematicComponent(sceneRef.current, position, circuitJson) : void 0
56241
56355
  );
@@ -56367,7 +56481,7 @@ var CadViewerInner = (props) => {
56367
56481
  useEffect50(() => {
56368
56482
  window.localStorage.setItem("cadViewerCameraType", cameraType);
56369
56483
  }, [cameraType]);
56370
- const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
56484
+ const viewerKey = props.circuitJson ? circuitKey : void 0;
56371
56485
  return /* @__PURE__ */ jsxs11(
56372
56486
  "div",
56373
56487
  {
@@ -56418,6 +56532,15 @@ var CadViewerInner = (props) => {
56418
56532
  menuVisible && /* @__PURE__ */ jsx39(
56419
56533
  ContextMenu,
56420
56534
  {
56535
+ componentName: selectedCadComponent?.componentName,
56536
+ onHideComponent: selectedCadComponent ? () => {
56537
+ hideComponent(selectedCadComponent.cad_component_id);
56538
+ closeMenu();
56539
+ } : void 0,
56540
+ onUnhideAllComponents: hiddenCadComponentIds.size > 0 ? () => {
56541
+ unhideAllComponents();
56542
+ closeMenu();
56543
+ } : void 0,
56421
56544
  onViewSchematicComponent: selectedComponent && props.onViewSchematicComponent ? () => {
56422
56545
  props.onViewSchematicComponent?.(selectedComponent);
56423
56546
  closeMenu();
@@ -56783,7 +56906,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
56783
56906
 
56784
56907
  // src/hooks/exporter/gltf.ts
56785
56908
  import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
56786
- import { useEffect as useEffect51, useState as useState41, useMemo as useMemo34, useCallback as useCallback25 } from "react";
56909
+ import { useEffect as useEffect51, useState as useState42, useMemo as useMemo34, useCallback as useCallback25 } from "react";
56787
56910
  function useSaveGltfAs(options = {}) {
56788
56911
  const parse2 = useParser(options);
56789
56912
  const link = useMemo34(() => document.createElement("a"), []);
@@ -56811,8 +56934,8 @@ function useSaveGltfAs(options = {}) {
56811
56934
  }
56812
56935
  function useExportGltfUrl(options = {}) {
56813
56936
  const parse2 = useParser(options);
56814
- const [url, setUrl] = useState41();
56815
- const [error, setError] = useState41();
56937
+ const [url, setUrl] = useState42();
56938
+ const [error, setError] = useState42();
56816
56939
  const ref = useCallback25(
56817
56940
  (instance) => parse2(instance).then(setUrl).catch(setError),
56818
56941
  []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.609",
3
+ "version": "0.0.610",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/tscircuit/3d-viewer"