@tscircuit/3d-viewer 0.0.608 → 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.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 useState39 } 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
 
@@ -14687,15 +14747,15 @@ var zIndexMap = {
14687
14747
  clickToInteractOverlay: 100,
14688
14748
  htmlElements: 95,
14689
14749
  orientationCube: 95,
14690
- contextMenu: 90,
14691
- appearanceMenu: 91
14750
+ contextMenu: 110,
14751
+ appearanceMenu: 111
14692
14752
  };
14693
14753
 
14694
14754
  // src/react-three/Html.tsx
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.607",
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,
@@ -54582,15 +54656,74 @@ var Sub2 = DropdownMenuSub;
54582
54656
  var SubTrigger2 = DropdownMenuSubTrigger;
54583
54657
  var SubContent2 = DropdownMenuSubContent;
54584
54658
 
54659
+ // src/components/ViewportSubContent.tsx
54660
+ import { useLayoutEffect as useLayoutEffect5, useState as useState35 } from "react";
54661
+ import { jsx as jsx33 } from "react/jsx-runtime";
54662
+ var ViewportSubContent = (props) => {
54663
+ const [content, setContent] = useState35(null);
54664
+ const [overlapWidth, setOverlapWidth] = useState35();
54665
+ useLayoutEffect5(() => {
54666
+ if (!content) return;
54667
+ const trigger = document.getElementById(
54668
+ content.getAttribute("aria-labelledby") ?? ""
54669
+ );
54670
+ if (!trigger) return;
54671
+ let naturalWidth = 0;
54672
+ const update = () => {
54673
+ naturalWidth = Math.max(naturalWidth, content.offsetWidth);
54674
+ if (!naturalWidth) return;
54675
+ const bounds = trigger.getBoundingClientRect();
54676
+ const availableWidth = Math.max(
54677
+ bounds.left - 10,
54678
+ document.documentElement.clientWidth - bounds.right - 10
54679
+ );
54680
+ setOverlapWidth(availableWidth < naturalWidth ? bounds.width : void 0);
54681
+ };
54682
+ const observer = new ResizeObserver(update);
54683
+ observer.observe(content);
54684
+ observer.observe(trigger);
54685
+ update();
54686
+ window.addEventListener("resize", update);
54687
+ return () => {
54688
+ observer.disconnect();
54689
+ window.removeEventListener("resize", update);
54690
+ };
54691
+ }, [content]);
54692
+ return /* @__PURE__ */ jsx33(
54693
+ SubContent2,
54694
+ {
54695
+ ...props,
54696
+ ref: setContent,
54697
+ sideOffset: overlapWidth === void 0 ? props.sideOffset : -overlapWidth,
54698
+ style: {
54699
+ ...props.style,
54700
+ ...overlapWidth === void 0 ? {} : { minWidth: Math.min(160, overlapWidth), maxWidth: overlapWidth }
54701
+ }
54702
+ }
54703
+ );
54704
+ };
54705
+
54706
+ // src/components/menu-viewport-styles.ts
54707
+ var menuViewportStyles = {
54708
+ boxSizing: "border-box",
54709
+ minWidth: "min(160px, calc(100vw - 20px))",
54710
+ maxWidth: "calc(100vw - 20px)",
54711
+ maxHeight: "var(--radix-dropdown-menu-content-available-height, calc(100dvh - 20px))",
54712
+ overflowY: "auto",
54713
+ overflowX: "hidden",
54714
+ overscrollBehavior: "contain",
54715
+ overflowWrap: "anywhere"
54716
+ };
54717
+
54585
54718
  // src/components/ContextMenu.tsx
54586
- import { useState as useState35 } from "react";
54719
+ import { useState as useState37 } from "react";
54587
54720
 
54588
54721
  // src/components/AppearanceMenu.tsx
54589
- import { useState as useState34 } from "react";
54722
+ import { useState as useState36 } from "react";
54590
54723
 
54591
54724
  // src/components/Icons.tsx
54592
- import { jsx as jsx33 } from "react/jsx-runtime";
54593
- var CheckIcon = () => /* @__PURE__ */ jsx33(
54725
+ import { jsx as jsx34 } from "react/jsx-runtime";
54726
+ var CheckIcon = () => /* @__PURE__ */ jsx34(
54594
54727
  "svg",
54595
54728
  {
54596
54729
  xmlns: "http://www.w3.org/2000/svg",
@@ -54602,10 +54735,10 @@ var CheckIcon = () => /* @__PURE__ */ jsx33(
54602
54735
  strokeWidth: "2",
54603
54736
  strokeLinecap: "round",
54604
54737
  strokeLinejoin: "round",
54605
- children: /* @__PURE__ */ jsx33("path", { d: "M20 6 9 17l-5-5" })
54738
+ children: /* @__PURE__ */ jsx34("path", { d: "M20 6 9 17l-5-5" })
54606
54739
  }
54607
54740
  );
54608
- var ChevronRightIcon = ({ isOpen }) => /* @__PURE__ */ jsx33(
54741
+ var ChevronRightIcon = ({ isOpen }) => /* @__PURE__ */ jsx34(
54609
54742
  "svg",
54610
54743
  {
54611
54744
  xmlns: "http://www.w3.org/2000/svg",
@@ -54622,10 +54755,10 @@ var ChevronRightIcon = ({ isOpen }) => /* @__PURE__ */ jsx33(
54622
54755
  transform: isOpen ? "rotate(90deg)" : "rotate(0deg)",
54623
54756
  opacity: 0.6
54624
54757
  },
54625
- children: /* @__PURE__ */ jsx33("path", { d: "m9 18 6-6-6-6" })
54758
+ children: /* @__PURE__ */ jsx34("path", { d: "m9 18 6-6-6-6" })
54626
54759
  }
54627
54760
  );
54628
- var CheckMinusIcon = () => /* @__PURE__ */ jsx33(
54761
+ var CheckMinusIcon = () => /* @__PURE__ */ jsx34(
54629
54762
  "svg",
54630
54763
  {
54631
54764
  xmlns: "http://www.w3.org/2000/svg",
@@ -54637,10 +54770,10 @@ var CheckMinusIcon = () => /* @__PURE__ */ jsx33(
54637
54770
  strokeWidth: "2",
54638
54771
  strokeLinecap: "round",
54639
54772
  strokeLinejoin: "round",
54640
- children: /* @__PURE__ */ jsx33("path", { d: "M5 12h14" })
54773
+ children: /* @__PURE__ */ jsx34("path", { d: "M5 12h14" })
54641
54774
  }
54642
54775
  );
54643
- var DotIcon = () => /* @__PURE__ */ jsx33(
54776
+ var DotIcon = () => /* @__PURE__ */ jsx34(
54644
54777
  "svg",
54645
54778
  {
54646
54779
  xmlns: "http://www.w3.org/2000/svg",
@@ -54653,12 +54786,12 @@ var DotIcon = () => /* @__PURE__ */ jsx33(
54653
54786
  strokeLinecap: "round",
54654
54787
  strokeLinejoin: "round",
54655
54788
  className: "lucide lucide-dot-icon lucide-dot",
54656
- children: /* @__PURE__ */ jsx33("circle", { cx: "12.1", cy: "12.1", r: "4.5", fill: "white" })
54789
+ children: /* @__PURE__ */ jsx34("circle", { cx: "12.1", cy: "12.1", r: "4.5", fill: "white" })
54657
54790
  }
54658
54791
  );
54659
54792
 
54660
54793
  // src/components/AppearanceMenu.tsx
54661
- import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs7 } from "react/jsx-runtime";
54794
+ import { Fragment as Fragment10, jsx as jsx35, jsxs as jsxs7 } from "react/jsx-runtime";
54662
54795
  var itemStyles = {
54663
54796
  padding: "6px 8px",
54664
54797
  borderRadius: 6,
@@ -54686,13 +54819,13 @@ var separatorStyles = {
54686
54819
  margin: "4px 0"
54687
54820
  };
54688
54821
  var contentStyles = {
54822
+ ...menuViewportStyles,
54689
54823
  backgroundColor: "#262626",
54690
54824
  color: "#fafafa",
54691
54825
  borderRadius: 8,
54692
54826
  boxShadow: "0px 12px 48px -12px rgba(0, 0, 0, 0.5), 0px 8px 24px -8px rgba(0, 0, 0, 0.3)",
54693
54827
  border: "1px solid #333333",
54694
54828
  padding: "4px",
54695
- minWidth: 160,
54696
54829
  zIndex: zIndexMap.appearanceMenu,
54697
54830
  fontSize: 14,
54698
54831
  fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
@@ -54713,10 +54846,10 @@ var AppearanceMenu = () => {
54713
54846
  lightingEnabled,
54714
54847
  setLightingEnabled
54715
54848
  } = useAppearance();
54716
- const [appearanceSubOpen, setAppearanceSubOpen] = useState34(false);
54717
- const [hoveredItem, setHoveredItem] = useState34(null);
54849
+ const [appearanceSubOpen, setAppearanceSubOpen] = useState36(false);
54850
+ const [hoveredItem, setHoveredItem] = useState36(null);
54718
54851
  return /* @__PURE__ */ jsxs7(Fragment10, { children: [
54719
- /* @__PURE__ */ jsx34(Separator2, { style: separatorStyles }),
54852
+ /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles }),
54720
54853
  /* @__PURE__ */ jsxs7(Sub2, { onOpenChange: setAppearanceSubOpen, children: [
54721
54854
  /* @__PURE__ */ jsxs7(
54722
54855
  SubTrigger2,
@@ -54730,8 +54863,8 @@ var AppearanceMenu = () => {
54730
54863
  onMouseLeave: () => setHoveredItem(null),
54731
54864
  onTouchStart: () => setHoveredItem("appearance"),
54732
54865
  children: [
54733
- /* @__PURE__ */ jsx34("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Appearance" }),
54734
- /* @__PURE__ */ jsx34(
54866
+ /* @__PURE__ */ jsx35("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Appearance" }),
54867
+ /* @__PURE__ */ jsx35(
54735
54868
  "div",
54736
54869
  {
54737
54870
  style: {
@@ -54740,14 +54873,14 @@ var AppearanceMenu = () => {
54740
54873
  alignItems: "flex-end",
54741
54874
  marginBottom: "-5px"
54742
54875
  },
54743
- children: /* @__PURE__ */ jsx34(ChevronRightIcon, { isOpen: appearanceSubOpen })
54876
+ children: /* @__PURE__ */ jsx35(ChevronRightIcon, { isOpen: appearanceSubOpen })
54744
54877
  }
54745
54878
  )
54746
54879
  ]
54747
54880
  }
54748
54881
  ),
54749
- /* @__PURE__ */ jsx34(Portal22, { children: /* @__PURE__ */ jsxs7(
54750
- SubContent2,
54882
+ /* @__PURE__ */ jsx35(Portal22, { children: /* @__PURE__ */ jsxs7(
54883
+ ViewportSubContent,
54751
54884
  {
54752
54885
  style: { ...contentStyles, marginLeft: -2 },
54753
54886
  collisionPadding: 10,
@@ -54769,8 +54902,8 @@ var AppearanceMenu = () => {
54769
54902
  onMouseLeave: () => setHoveredItem(null),
54770
54903
  onTouchStart: () => setHoveredItem("darkBackground"),
54771
54904
  children: [
54772
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: darkBackgroundEnabled && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54773
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Dark Background" })
54905
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: darkBackgroundEnabled && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
54906
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Dark Background" })
54774
54907
  ]
54775
54908
  }
54776
54909
  ),
@@ -54790,12 +54923,12 @@ var AppearanceMenu = () => {
54790
54923
  onMouseLeave: () => setHoveredItem(null),
54791
54924
  onTouchStart: () => setHoveredItem("lighting"),
54792
54925
  children: [
54793
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: lightingEnabled && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54794
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Lighting" })
54926
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: lightingEnabled && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
54927
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Lighting" })
54795
54928
  ]
54796
54929
  }
54797
54930
  ),
54798
- /* @__PURE__ */ jsx34(Separator2, { style: separatorStyles }),
54931
+ /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles }),
54799
54932
  /* @__PURE__ */ jsxs7(
54800
54933
  Item22,
54801
54934
  {
@@ -54812,8 +54945,8 @@ var AppearanceMenu = () => {
54812
54945
  onMouseLeave: () => setHoveredItem(null),
54813
54946
  onTouchStart: () => setHoveredItem("boardBody"),
54814
54947
  children: [
54815
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.boardBody && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54816
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Board Body" })
54948
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.boardBody && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
54949
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Board Body" })
54817
54950
  ]
54818
54951
  }
54819
54952
  ),
@@ -54833,8 +54966,8 @@ var AppearanceMenu = () => {
54833
54966
  onMouseLeave: () => setHoveredItem(null),
54834
54967
  onTouchStart: () => setHoveredItem("topCopper"),
54835
54968
  children: [
54836
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.topCopper && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54837
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Top Copper" })
54969
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.topCopper && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
54970
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Top Copper" })
54838
54971
  ]
54839
54972
  }
54840
54973
  ),
@@ -54854,8 +54987,8 @@ var AppearanceMenu = () => {
54854
54987
  onMouseLeave: () => setHoveredItem(null),
54855
54988
  onTouchStart: () => setHoveredItem("bottomCopper"),
54856
54989
  children: [
54857
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.bottomCopper && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54858
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Copper" })
54990
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.bottomCopper && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
54991
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Copper" })
54859
54992
  ]
54860
54993
  }
54861
54994
  ),
@@ -54875,8 +55008,8 @@ var AppearanceMenu = () => {
54875
55008
  onMouseLeave: () => setHoveredItem(null),
54876
55009
  onTouchStart: () => setHoveredItem("keepout"),
54877
55010
  children: [
54878
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.keepout && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54879
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Keepout" })
55011
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.keepout && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55012
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Keepout" })
54880
55013
  ]
54881
55014
  }
54882
55015
  ),
@@ -54896,8 +55029,8 @@ var AppearanceMenu = () => {
54896
55029
  onMouseLeave: () => setHoveredItem(null),
54897
55030
  onTouchStart: () => setHoveredItem("topSilkscreen"),
54898
55031
  children: [
54899
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.topSilkscreen && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54900
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Top Silkscreen" })
55032
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.topSilkscreen && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55033
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Top Silkscreen" })
54901
55034
  ]
54902
55035
  }
54903
55036
  ),
@@ -54920,8 +55053,8 @@ var AppearanceMenu = () => {
54920
55053
  onMouseLeave: () => setHoveredItem(null),
54921
55054
  onTouchStart: () => setHoveredItem("bottomSilkscreen"),
54922
55055
  children: [
54923
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.bottomSilkscreen && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54924
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Silkscreen" })
55056
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.bottomSilkscreen && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55057
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Silkscreen" })
54925
55058
  ]
54926
55059
  }
54927
55060
  ),
@@ -54941,8 +55074,8 @@ var AppearanceMenu = () => {
54941
55074
  onMouseLeave: () => setHoveredItem(null),
54942
55075
  onTouchStart: () => setHoveredItem("topMask"),
54943
55076
  children: [
54944
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.topMask && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54945
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Top Soldermask" })
55077
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.topMask && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55078
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Top Soldermask" })
54946
55079
  ]
54947
55080
  }
54948
55081
  ),
@@ -54962,8 +55095,8 @@ var AppearanceMenu = () => {
54962
55095
  onMouseLeave: () => setHoveredItem(null),
54963
55096
  onTouchStart: () => setHoveredItem("bottomMask"),
54964
55097
  children: [
54965
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.bottomMask && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54966
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Soldermask" })
55098
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.bottomMask && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55099
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Bottom Soldermask" })
54967
55100
  ]
54968
55101
  }
54969
55102
  ),
@@ -54983,8 +55116,8 @@ var AppearanceMenu = () => {
54983
55116
  onMouseLeave: () => setHoveredItem(null),
54984
55117
  onTouchStart: () => setHoveredItem("pcbNotes"),
54985
55118
  children: [
54986
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.pcbNotes && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
54987
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "PCB Notes" })
55119
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.pcbNotes && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55120
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "PCB Notes" })
54988
55121
  ]
54989
55122
  }
54990
55123
  ),
@@ -55004,8 +55137,8 @@ var AppearanceMenu = () => {
55004
55137
  onMouseLeave: () => setHoveredItem(null),
55005
55138
  onTouchStart: () => setHoveredItem("smtModels"),
55006
55139
  children: [
55007
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.smtModels && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
55008
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Surface Mount Components" })
55140
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.smtModels && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55141
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Surface Mount Components" })
55009
55142
  ]
55010
55143
  }
55011
55144
  ),
@@ -55028,12 +55161,12 @@ var AppearanceMenu = () => {
55028
55161
  onMouseLeave: () => setHoveredItem(null),
55029
55162
  onTouchStart: () => setHoveredItem("throughHoleModels"),
55030
55163
  children: [
55031
- /* @__PURE__ */ jsx34("span", { style: iconContainerStyles, children: visibility.throughHoleModels && /* @__PURE__ */ jsx34(CheckIcon, {}) }),
55032
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Through-Hole Components" })
55164
+ /* @__PURE__ */ jsx35("span", { style: iconContainerStyles, children: visibility.throughHoleModels && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55165
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Through-Hole Components" })
55033
55166
  ]
55034
55167
  }
55035
55168
  ),
55036
- /* @__PURE__ */ jsx34(Separator2, { style: separatorStyles }),
55169
+ /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles }),
55037
55170
  /* @__PURE__ */ jsxs7(
55038
55171
  Item22,
55039
55172
  {
@@ -55055,10 +55188,10 @@ var AppearanceMenu = () => {
55055
55188
  title: `Enclosure: ${visibility.enclosure}`,
55056
55189
  children: [
55057
55190
  /* @__PURE__ */ jsxs7("span", { style: iconContainerStyles, children: [
55058
- visibility.enclosure === "opaque" && /* @__PURE__ */ jsx34(CheckIcon, {}),
55059
- visibility.enclosure === "translucent" && /* @__PURE__ */ jsx34(CheckMinusIcon, {})
55191
+ visibility.enclosure === "opaque" && /* @__PURE__ */ jsx35(CheckIcon, {}),
55192
+ visibility.enclosure === "translucent" && /* @__PURE__ */ jsx35(CheckMinusIcon, {})
55060
55193
  ] }),
55061
- /* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: "Enclosure" })
55194
+ /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Enclosure" })
55062
55195
  ]
55063
55196
  }
55064
55197
  )
@@ -55070,7 +55203,7 @@ var AppearanceMenu = () => {
55070
55203
  };
55071
55204
 
55072
55205
  // src/components/ContextMenu.tsx
55073
- import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs8 } from "react/jsx-runtime";
55206
+ import { Fragment as Fragment11, jsx as jsx36, jsxs as jsxs8 } from "react/jsx-runtime";
55074
55207
  var cameraOptions = [
55075
55208
  "Custom",
55076
55209
  "Top Center Angled",
@@ -55082,13 +55215,13 @@ var cameraOptions = [
55082
55215
  "Front"
55083
55216
  ];
55084
55217
  var contentStyles2 = {
55218
+ ...menuViewportStyles,
55085
55219
  backgroundColor: "#262626",
55086
55220
  color: "#fafafa",
55087
55221
  borderRadius: 6,
55088
55222
  boxShadow: "0px 12px 48px -12px rgba(0, 0, 0, 0.5), 0px 8px 24px -8px rgba(0, 0, 0, 0.3)",
55089
55223
  border: "1px solid #333333",
55090
55224
  padding: "4px",
55091
- minWidth: 160,
55092
55225
  zIndex: zIndexMap.contextMenu,
55093
55226
  fontSize: 14,
55094
55227
  fontWeight: 400,
@@ -55155,15 +55288,18 @@ var ContextMenu = ({
55155
55288
  onReferenceObjectSelect = () => {
55156
55289
  },
55157
55290
  onViewSchematicComponent,
55291
+ componentName,
55292
+ onHideComponent,
55293
+ onUnhideAllComponents,
55158
55294
  onDownloadGltf,
55159
55295
  onOpenKeyboardShortcuts
55160
55296
  }) => {
55161
55297
  const { cameraType, setCameraType } = useCameraController();
55162
55298
  const { gridEnabled, setGridEnabled } = useAppearance();
55163
- const [cameraSubOpen, setCameraSubOpen] = useState35(false);
55164
- const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState35(false);
55165
- const [hoveredItem, setHoveredItem] = useState35(null);
55166
- return /* @__PURE__ */ jsx35(
55299
+ const [cameraSubOpen, setCameraSubOpen] = useState37(false);
55300
+ const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState37(false);
55301
+ const [hoveredItem, setHoveredItem] = useState37(null);
55302
+ return /* @__PURE__ */ jsx36(
55167
55303
  "div",
55168
55304
  {
55169
55305
  ref: menuRef,
@@ -55175,8 +55311,8 @@ var ContextMenu = ({
55175
55311
  height: 0
55176
55312
  },
55177
55313
  children: /* @__PURE__ */ jsxs8(Root22, { open: true, modal: false, children: [
55178
- /* @__PURE__ */ jsx35(Trigger, { asChild: true, children: /* @__PURE__ */ jsx35("div", { style: { position: "absolute", width: 1, height: 1 } }) }),
55179
- /* @__PURE__ */ jsx35(Portal22, { children: /* @__PURE__ */ jsxs8(
55314
+ /* @__PURE__ */ jsx36(Trigger, { asChild: true, children: /* @__PURE__ */ jsx36("div", { style: { position: "absolute", width: 1, height: 1 } }) }),
55315
+ /* @__PURE__ */ jsx36(Portal22, { children: /* @__PURE__ */ jsxs8(
55180
55316
  Content22,
55181
55317
  {
55182
55318
  style: contentStyles2,
@@ -55185,23 +55321,49 @@ var ContextMenu = ({
55185
55321
  sideOffset: 0,
55186
55322
  align: "start",
55187
55323
  children: [
55188
- onViewSchematicComponent && /* @__PURE__ */ jsxs8(Fragment11, { children: [
55189
- /* @__PURE__ */ jsx35(
55190
- Item22,
55191
- {
55192
- style: {
55193
- ...itemStyles2,
55194
- ...itemPaddingStyles2,
55195
- backgroundColor: hoveredItem === "schematic" ? "#404040" : "transparent"
55196
- },
55197
- onSelect: onViewSchematicComponent,
55198
- onMouseEnter: () => setHoveredItem("schematic"),
55199
- onMouseLeave: () => setHoveredItem(null),
55200
- children: "Show on schematic"
55201
- }
55202
- ),
55203
- /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles2 })
55204
- ] }),
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 }),
55205
55367
  /* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setCameraSubOpen, children: [
55206
55368
  /* @__PURE__ */ jsxs8(
55207
55369
  SubTrigger2,
@@ -55215,11 +55377,11 @@ var ContextMenu = ({
55215
55377
  onMouseLeave: () => setHoveredItem(null),
55216
55378
  onTouchStart: () => setHoveredItem("camera"),
55217
55379
  children: [
55218
- /* @__PURE__ */ jsx35(
55380
+ /* @__PURE__ */ jsx36(
55219
55381
  "span",
55220
55382
  {
55221
55383
  style: { flex: 1, display: "flex", alignItems: "center" },
55222
- children: "Camera Position"
55384
+ children: "Camera"
55223
55385
  }
55224
55386
  ),
55225
55387
  /* @__PURE__ */ jsxs8(
@@ -55232,89 +55394,83 @@ var ContextMenu = ({
55232
55394
  marginLeft: "auto"
55233
55395
  },
55234
55396
  children: [
55235
- /* @__PURE__ */ jsx35("span", { style: { opacity: 0.55, fontSize: 13 }, children: cameraPreset }),
55236
- /* @__PURE__ */ jsx35(ChevronRightIcon, { isOpen: cameraSubOpen })
55397
+ /* @__PURE__ */ jsx36("span", { style: { opacity: 0.55, fontSize: 13 }, children: cameraPreset }),
55398
+ /* @__PURE__ */ jsx36(ChevronRightIcon, { isOpen: cameraSubOpen })
55237
55399
  ]
55238
55400
  }
55239
55401
  )
55240
55402
  ]
55241
55403
  }
55242
55404
  ),
55243
- /* @__PURE__ */ jsx35(Portal22, { children: /* @__PURE__ */ jsx35(
55244
- SubContent2,
55405
+ /* @__PURE__ */ jsx36(Portal22, { children: /* @__PURE__ */ jsxs8(
55406
+ ViewportSubContent,
55245
55407
  {
55246
55408
  style: { ...contentStyles2, marginLeft: -2 },
55247
55409
  collisionPadding: 10,
55248
55410
  avoidCollisions: true,
55249
- children: cameraOptions.map((option) => /* @__PURE__ */ jsxs8(
55250
- Item22,
55251
- {
55252
- style: {
55253
- ...itemStyles2,
55254
- backgroundColor: hoveredItem === option ? "#404040" : "transparent"
55255
- },
55256
- onSelect: (e) => e.preventDefault(),
55257
- onPointerDown: (e) => {
55258
- e.preventDefault();
55259
- onCameraPresetSelect(option);
55411
+ children: [
55412
+ cameraOptions.map((option) => /* @__PURE__ */ jsxs8(
55413
+ Item22,
55414
+ {
55415
+ style: {
55416
+ ...itemStyles2,
55417
+ backgroundColor: hoveredItem === option ? "#404040" : "transparent"
55418
+ },
55419
+ onSelect: () => onCameraPresetSelect(option),
55420
+ onMouseEnter: () => setHoveredItem(option),
55421
+ onMouseLeave: () => setHoveredItem(null),
55422
+ onTouchStart: () => setHoveredItem(option),
55423
+ children: [
55424
+ /* @__PURE__ */ jsx36("span", { style: iconContainerStyles2, children: cameraPreset === option && /* @__PURE__ */ jsx36(DotIcon, {}) }),
55425
+ /* @__PURE__ */ jsx36("span", { style: { display: "flex", alignItems: "center" }, children: option })
55426
+ ]
55260
55427
  },
55261
- onMouseEnter: () => setHoveredItem(option),
55262
- onMouseLeave: () => setHoveredItem(null),
55263
- onTouchStart: () => setHoveredItem(option),
55264
- children: [
55265
- /* @__PURE__ */ jsx35("span", { style: iconContainerStyles2, children: cameraPreset === option && /* @__PURE__ */ jsx35(DotIcon, {}) }),
55266
- /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: option })
55267
- ]
55268
- },
55269
- option
55270
- ))
55428
+ option
55429
+ )),
55430
+ /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55431
+ /* @__PURE__ */ jsxs8(
55432
+ Item22,
55433
+ {
55434
+ style: {
55435
+ ...itemStyles2,
55436
+ backgroundColor: hoveredItem === "autorotate" ? "#404040" : "transparent"
55437
+ },
55438
+ onSelect: onAutoRotateToggle,
55439
+ onMouseEnter: () => setHoveredItem("autorotate"),
55440
+ onMouseLeave: () => setHoveredItem(null),
55441
+ onTouchStart: () => setHoveredItem("autorotate"),
55442
+ children: [
55443
+ /* @__PURE__ */ jsx36("span", { style: iconContainerStyles2, children: autoRotate && /* @__PURE__ */ jsx36(CheckIcon, {}) }),
55444
+ /* @__PURE__ */ jsx36("span", { style: { display: "flex", alignItems: "center" }, children: "Auto rotate" })
55445
+ ]
55446
+ }
55447
+ ),
55448
+ /* @__PURE__ */ jsxs8(
55449
+ Item22,
55450
+ {
55451
+ style: {
55452
+ ...itemStyles2,
55453
+ backgroundColor: hoveredItem === "cameratype" ? "#404040" : "transparent"
55454
+ },
55455
+ onSelect: (e) => {
55456
+ e.preventDefault();
55457
+ setCameraType(
55458
+ cameraType === "perspective" ? "orthographic" : "perspective"
55459
+ );
55460
+ },
55461
+ onMouseEnter: () => setHoveredItem("cameratype"),
55462
+ onMouseLeave: () => setHoveredItem(null),
55463
+ onTouchStart: () => setHoveredItem("cameratype"),
55464
+ children: [
55465
+ /* @__PURE__ */ jsx36("span", { style: iconContainerStyles2, children: cameraType === "orthographic" && /* @__PURE__ */ jsx36(CheckIcon, {}) }),
55466
+ /* @__PURE__ */ jsx36("span", { style: { display: "flex", alignItems: "center" }, children: "Orthographic Camera" })
55467
+ ]
55468
+ }
55469
+ )
55470
+ ]
55271
55471
  }
55272
55472
  ) })
55273
55473
  ] }),
55274
- /* @__PURE__ */ jsxs8(
55275
- Item22,
55276
- {
55277
- style: {
55278
- ...itemStyles2,
55279
- backgroundColor: hoveredItem === "autorotate" ? "#404040" : "transparent"
55280
- },
55281
- onSelect: (e) => e.preventDefault(),
55282
- onPointerDown: (e) => {
55283
- e.preventDefault();
55284
- onAutoRotateToggle();
55285
- },
55286
- onMouseEnter: () => setHoveredItem("autorotate"),
55287
- onMouseLeave: () => setHoveredItem(null),
55288
- onTouchStart: () => setHoveredItem("autorotate"),
55289
- children: [
55290
- /* @__PURE__ */ jsx35("span", { style: iconContainerStyles2, children: autoRotate && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55291
- /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Auto rotate" })
55292
- ]
55293
- }
55294
- ),
55295
- /* @__PURE__ */ jsxs8(
55296
- Item22,
55297
- {
55298
- style: {
55299
- ...itemStyles2,
55300
- backgroundColor: hoveredItem === "cameratype" ? "#404040" : "transparent"
55301
- },
55302
- onSelect: (e) => e.preventDefault(),
55303
- onPointerDown: (e) => {
55304
- e.preventDefault();
55305
- setCameraType(
55306
- cameraType === "perspective" ? "orthographic" : "perspective"
55307
- );
55308
- },
55309
- onMouseEnter: () => setHoveredItem("cameratype"),
55310
- onMouseLeave: () => setHoveredItem(null),
55311
- onTouchStart: () => setHoveredItem("cameratype"),
55312
- children: [
55313
- /* @__PURE__ */ jsx35("span", { style: iconContainerStyles2, children: cameraType === "orthographic" && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55314
- /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Orthographic Camera" })
55315
- ]
55316
- }
55317
- ),
55318
55474
  /* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setReferenceObjectSubOpen, children: [
55319
55475
  /* @__PURE__ */ jsxs8(
55320
55476
  SubTrigger2,
@@ -55328,14 +55484,14 @@ var ContextMenu = ({
55328
55484
  onMouseLeave: () => setHoveredItem(null),
55329
55485
  onTouchStart: () => setHoveredItem("reference-object"),
55330
55486
  children: [
55331
- /* @__PURE__ */ jsx35(
55487
+ /* @__PURE__ */ jsx36(
55332
55488
  "span",
55333
55489
  {
55334
55490
  style: { flex: 1, display: "flex", alignItems: "center" },
55335
55491
  children: "Show Reference Object"
55336
55492
  }
55337
55493
  ),
55338
- /* @__PURE__ */ jsx35(
55494
+ /* @__PURE__ */ jsx36(
55339
55495
  "div",
55340
55496
  {
55341
55497
  style: {
@@ -55344,14 +55500,14 @@ var ContextMenu = ({
55344
55500
  gap: 6,
55345
55501
  marginLeft: "auto"
55346
55502
  },
55347
- children: /* @__PURE__ */ jsx35(ChevronRightIcon, { isOpen: referenceObjectSubOpen })
55503
+ children: /* @__PURE__ */ jsx36(ChevronRightIcon, { isOpen: referenceObjectSubOpen })
55348
55504
  }
55349
55505
  )
55350
55506
  ]
55351
55507
  }
55352
55508
  ),
55353
- /* @__PURE__ */ jsx35(Portal22, { children: /* @__PURE__ */ jsx35(
55354
- SubContent2,
55509
+ /* @__PURE__ */ jsx36(Portal22, { children: /* @__PURE__ */ jsx36(
55510
+ ViewportSubContent,
55355
55511
  {
55356
55512
  style: { ...contentStyles2, marginLeft: -2 },
55357
55513
  collisionPadding: 10,
@@ -55374,8 +55530,8 @@ var ContextMenu = ({
55374
55530
  onMouseLeave: () => setHoveredItem(null),
55375
55531
  onTouchStart: () => setHoveredItem(optionKey),
55376
55532
  children: [
55377
- /* @__PURE__ */ jsx35("span", { style: iconContainerStyles2, children: referenceObject === option.type && /* @__PURE__ */ jsx35(DotIcon, {}) }),
55378
- /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: option.label })
55533
+ /* @__PURE__ */ jsx36("span", { style: iconContainerStyles2, children: referenceObject === option.type && /* @__PURE__ */ jsx36(DotIcon, {}) }),
55534
+ /* @__PURE__ */ jsx36("span", { style: { display: "flex", alignItems: "center" }, children: option.label })
55379
55535
  ]
55380
55536
  },
55381
55537
  optionKey
@@ -55396,8 +55552,8 @@ var ContextMenu = ({
55396
55552
  onMouseEnter: () => setHoveredItem("fold"),
55397
55553
  onMouseLeave: () => setHoveredItem(null),
55398
55554
  children: [
55399
- /* @__PURE__ */ jsx35("span", { style: iconContainerStyles2, children: foldPcbs && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55400
- /* @__PURE__ */ jsx35("span", { children: "Fold PCBs" })
55555
+ /* @__PURE__ */ jsx36("span", { style: iconContainerStyles2, children: foldPcbs && /* @__PURE__ */ jsx36(CheckIcon, {}) }),
55556
+ /* @__PURE__ */ jsx36("span", { children: "Fold PCBs" })
55401
55557
  ]
55402
55558
  }
55403
55559
  ),
@@ -55417,14 +55573,14 @@ var ContextMenu = ({
55417
55573
  onMouseLeave: () => setHoveredItem(null),
55418
55574
  onTouchStart: () => setHoveredItem("grid"),
55419
55575
  children: [
55420
- /* @__PURE__ */ jsx35("span", { style: iconContainerStyles2, children: gridEnabled && /* @__PURE__ */ jsx35(CheckIcon, {}) }),
55421
- /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Show Grid" })
55576
+ /* @__PURE__ */ jsx36("span", { style: iconContainerStyles2, children: gridEnabled && /* @__PURE__ */ jsx36(CheckIcon, {}) }),
55577
+ /* @__PURE__ */ jsx36("span", { style: { display: "flex", alignItems: "center" }, children: "Show Grid" })
55422
55578
  ]
55423
55579
  }
55424
55580
  ),
55425
- /* @__PURE__ */ jsx35(AppearanceMenu, {}),
55426
- /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles2 }),
55427
- /* @__PURE__ */ jsx35(
55581
+ /* @__PURE__ */ jsx36(AppearanceMenu, {}),
55582
+ /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55583
+ /* @__PURE__ */ jsx36(
55428
55584
  Item22,
55429
55585
  {
55430
55586
  style: {
@@ -55436,10 +55592,10 @@ var ContextMenu = ({
55436
55592
  onMouseEnter: () => setHoveredItem("download"),
55437
55593
  onMouseLeave: () => setHoveredItem(null),
55438
55594
  onTouchStart: () => setHoveredItem("download"),
55439
- children: /* @__PURE__ */ jsx35("span", { style: { display: "flex", alignItems: "center" }, children: "Download GLTF" })
55595
+ children: /* @__PURE__ */ jsx36("span", { style: { display: "flex", alignItems: "center" }, children: "Download GLTF" })
55440
55596
  }
55441
55597
  ),
55442
- /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles2 }),
55598
+ /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55443
55599
  !flexScene && /* @__PURE__ */ jsxs8(
55444
55600
  Item22,
55445
55601
  {
@@ -55468,7 +55624,7 @@ var ContextMenu = ({
55468
55624
  ]
55469
55625
  }
55470
55626
  ),
55471
- /* @__PURE__ */ jsx35(
55627
+ /* @__PURE__ */ jsx36(
55472
55628
  "div",
55473
55629
  {
55474
55630
  style: {
@@ -55482,7 +55638,7 @@ var ContextMenu = ({
55482
55638
  ]
55483
55639
  }
55484
55640
  ),
55485
- /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles2 }),
55641
+ /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55486
55642
  /* @__PURE__ */ jsxs8(
55487
55643
  Item22,
55488
55644
  {
@@ -55496,8 +55652,8 @@ var ContextMenu = ({
55496
55652
  onMouseLeave: () => setHoveredItem(null),
55497
55653
  onTouchStart: () => setHoveredItem("shortcuts"),
55498
55654
  children: [
55499
- /* @__PURE__ */ jsx35("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Keyboard Shortcuts" }),
55500
- /* @__PURE__ */ jsx35(
55655
+ /* @__PURE__ */ jsx36("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Keyboard Shortcuts" }),
55656
+ /* @__PURE__ */ jsx36(
55501
55657
  "div",
55502
55658
  {
55503
55659
  style: {
@@ -55511,8 +55667,8 @@ var ContextMenu = ({
55511
55667
  ]
55512
55668
  }
55513
55669
  ),
55514
- /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles2 }),
55515
- /* @__PURE__ */ jsx35(
55670
+ /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55671
+ /* @__PURE__ */ jsx36(
55516
55672
  "div",
55517
55673
  {
55518
55674
  style: {
@@ -55550,10 +55706,10 @@ var ContextMenu = ({
55550
55706
  };
55551
55707
 
55552
55708
  // src/components/KeyboardShortcutsDialog.tsx
55553
- import { useEffect as useEffect48, useMemo as useMemo33, useRef as useRef27, useState as useState37 } from "react";
55709
+ import { useEffect as useEffect48, useMemo as useMemo33, useRef as useRef27, useState as useState39 } from "react";
55554
55710
 
55555
55711
  // src/hooks/useRegisteredHotkey.ts
55556
- import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef26, useState as useState36 } from "react";
55712
+ import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef26, useState as useState38 } from "react";
55557
55713
  var hotkeyRegistry = /* @__PURE__ */ new Map();
55558
55714
  var subscribers = /* @__PURE__ */ new Set();
55559
55715
  var isListenerAttached = false;
@@ -55697,7 +55853,7 @@ var useRegisteredHotkey = (id, handler, metadata) => {
55697
55853
  }, [id, normalizedMetadata]);
55698
55854
  };
55699
55855
  var useHotkeyRegistry = () => {
55700
- const [entries, setEntries] = useState36(
55856
+ const [entries, setEntries] = useState38(
55701
55857
  () => Array.from(hotkeyRegistry.values())
55702
55858
  );
55703
55859
  useEffect47(() => subscribeToRegistry(setEntries), []);
@@ -55709,12 +55865,12 @@ var registerHotkeyViewer = (element) => {
55709
55865
  };
55710
55866
 
55711
55867
  // src/components/KeyboardShortcutsDialog.tsx
55712
- import { jsx as jsx36, jsxs as jsxs9 } from "react/jsx-runtime";
55868
+ import { jsx as jsx37, jsxs as jsxs9 } from "react/jsx-runtime";
55713
55869
  var KeyboardShortcutsDialog = ({
55714
55870
  open,
55715
55871
  onClose
55716
55872
  }) => {
55717
- const [query, setQuery] = useState37("");
55873
+ const [query, setQuery] = useState39("");
55718
55874
  const inputRef = useRef27(null);
55719
55875
  const hotkeys = useHotkeyRegistry();
55720
55876
  useEffect48(() => {
@@ -55748,7 +55904,7 @@ var KeyboardShortcutsDialog = ({
55748
55904
  if (!open) {
55749
55905
  return null;
55750
55906
  }
55751
- return /* @__PURE__ */ jsx36(
55907
+ return /* @__PURE__ */ jsx37(
55752
55908
  "div",
55753
55909
  {
55754
55910
  role: "dialog",
@@ -55788,7 +55944,7 @@ var KeyboardShortcutsDialog = ({
55788
55944
  },
55789
55945
  children: [
55790
55946
  /* @__PURE__ */ jsxs9("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
55791
- /* @__PURE__ */ jsx36(
55947
+ /* @__PURE__ */ jsx37(
55792
55948
  "h2",
55793
55949
  {
55794
55950
  style: {
@@ -55800,7 +55956,7 @@ var KeyboardShortcutsDialog = ({
55800
55956
  children: "Keyboard Shortcuts"
55801
55957
  }
55802
55958
  ),
55803
- /* @__PURE__ */ jsx36(
55959
+ /* @__PURE__ */ jsx37(
55804
55960
  "button",
55805
55961
  {
55806
55962
  type: "button",
@@ -55816,7 +55972,7 @@ var KeyboardShortcutsDialog = ({
55816
55972
  }
55817
55973
  )
55818
55974
  ] }),
55819
- /* @__PURE__ */ jsx36(
55975
+ /* @__PURE__ */ jsx37(
55820
55976
  "input",
55821
55977
  {
55822
55978
  ref: inputRef,
@@ -55839,7 +55995,7 @@ var KeyboardShortcutsDialog = ({
55839
55995
  ]
55840
55996
  }
55841
55997
  ),
55842
- /* @__PURE__ */ jsx36("div", { style: { overflowY: "auto" }, children: /* @__PURE__ */ jsxs9(
55998
+ /* @__PURE__ */ jsx37("div", { style: { overflowY: "auto" }, children: /* @__PURE__ */ jsxs9(
55843
55999
  "table",
55844
56000
  {
55845
56001
  style: {
@@ -55848,11 +56004,11 @@ var KeyboardShortcutsDialog = ({
55848
56004
  fontSize: "0.95rem"
55849
56005
  },
55850
56006
  children: [
55851
- /* @__PURE__ */ jsx36("thead", { children: /* @__PURE__ */ jsxs9("tr", { style: { textAlign: "left", color: "#a1a1b5" }, children: [
55852
- /* @__PURE__ */ jsx36("th", { style: { padding: "12px 24px", width: "25%" }, children: "Key" }),
55853
- /* @__PURE__ */ jsx36("th", { style: { padding: "12px 24px" }, children: "Description" })
56007
+ /* @__PURE__ */ jsx37("thead", { children: /* @__PURE__ */ jsxs9("tr", { style: { textAlign: "left", color: "#a1a1b5" }, children: [
56008
+ /* @__PURE__ */ jsx37("th", { style: { padding: "12px 24px", width: "25%" }, children: "Key" }),
56009
+ /* @__PURE__ */ jsx37("th", { style: { padding: "12px 24px" }, children: "Description" })
55854
56010
  ] }) }),
55855
- /* @__PURE__ */ jsx36("tbody", { children: filteredHotkeys.length === 0 ? /* @__PURE__ */ jsx36("tr", { children: /* @__PURE__ */ jsx36(
56011
+ /* @__PURE__ */ jsx37("tbody", { children: filteredHotkeys.length === 0 ? /* @__PURE__ */ jsx37("tr", { children: /* @__PURE__ */ jsx37(
55856
56012
  "td",
55857
56013
  {
55858
56014
  colSpan: 2,
@@ -55864,7 +56020,7 @@ var KeyboardShortcutsDialog = ({
55864
56020
  {
55865
56021
  style: { borderTop: "1px solid rgba(255, 255, 255, 0.05)" },
55866
56022
  children: [
55867
- /* @__PURE__ */ jsx36("td", { style: { padding: "12px 24px" }, children: /* @__PURE__ */ jsx36(
56023
+ /* @__PURE__ */ jsx37("td", { style: { padding: "12px 24px" }, children: /* @__PURE__ */ jsx37(
55868
56024
  "span",
55869
56025
  {
55870
56026
  style: {
@@ -55882,7 +56038,7 @@ var KeyboardShortcutsDialog = ({
55882
56038
  children: hotkey.shortcut
55883
56039
  }
55884
56040
  ) }),
55885
- /* @__PURE__ */ jsx36("td", { style: { padding: "12px 24px" }, children: hotkey.description })
56041
+ /* @__PURE__ */ jsx37("td", { style: { padding: "12px 24px" }, children: hotkey.description })
55886
56042
  ]
55887
56043
  },
55888
56044
  hotkey.id
@@ -55899,7 +56055,7 @@ var KeyboardShortcutsDialog = ({
55899
56055
 
55900
56056
  // src/contexts/ToastContext.tsx
55901
56057
  import { Toaster, toast as hotToast } from "react-hot-toast";
55902
- import { Fragment as Fragment12, jsx as jsx37, jsxs as jsxs10 } from "react/jsx-runtime";
56058
+ import { Fragment as Fragment12, jsx as jsx38, jsxs as jsxs10 } from "react/jsx-runtime";
55903
56059
  var useToast = () => {
55904
56060
  return {
55905
56061
  showToast: (message, duration = 2e3) => {
@@ -55912,7 +56068,7 @@ var ToastProvider = ({
55912
56068
  }) => {
55913
56069
  return /* @__PURE__ */ jsxs10(Fragment12, { children: [
55914
56070
  children,
55915
- /* @__PURE__ */ jsx37(Toaster, { position: "bottom-right" })
56071
+ /* @__PURE__ */ jsx38(Toaster, { position: "bottom-right" })
55916
56072
  ] });
55917
56073
  };
55918
56074
 
@@ -55957,10 +56113,10 @@ function useCameraPreset({
55957
56113
  }
55958
56114
 
55959
56115
  // src/hooks/useContextMenu.ts
55960
- import { useState as useState38, 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";
55961
56117
  var useContextMenu = ({ containerRef, onOpen }) => {
55962
- const [menuVisible, setMenuVisible] = useState38(false);
55963
- const [menuPos, setMenuPos] = useState38({
56118
+ const [menuVisible, setMenuVisible] = useState40(false);
56119
+ const [menuPos, setMenuPos] = useState40({
55964
56120
  x: 0,
55965
56121
  y: 0
55966
56122
  });
@@ -56137,7 +56293,7 @@ var useGlobalDownloadGltf = () => {
56137
56293
  };
56138
56294
 
56139
56295
  // src/CadViewer.tsx
56140
- import { jsx as jsx38, jsxs as jsxs11 } from "react/jsx-runtime";
56296
+ import { jsx as jsx39, jsxs as jsxs11 } from "react/jsx-runtime";
56141
56297
  var DEFAULT_TARGET = new THREE54.Vector3(0, 0, 0);
56142
56298
  var INITIAL_CAMERA_POSITION = [5, -5, 5];
56143
56299
  var readStoredCameraType = () => {
@@ -56152,37 +56308,48 @@ var CadViewerInner = (props) => {
56152
56308
  const circuitJson = props.circuitJson ?? childrenCircuitJson;
56153
56309
  const hasBends = circuitJson.some((element) => element.type === "pcb_bend");
56154
56310
  const hasFlexGeometry = hasBends || circuitJson.some((element) => element.type === "pcb_stiffener");
56155
- const [foldPcbsOverride, setFoldPcbs] = useState39(
56311
+ const [foldPcbsOverride, setFoldPcbs] = useState41(
56156
56312
  void 0
56157
56313
  );
56158
56314
  const foldPcbs = foldPcbsOverride ?? props.foldPcbs;
56159
56315
  const resolvedFoldPcbs = resolveFoldPcbs(circuitJson, foldPcbs);
56160
- const resolvedProps = { ...props, circuitJson, children: void 0 };
56161
- const [engine, setEngine] = useState39(() => {
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(() => {
56162
56325
  const stored = window.localStorage.getItem("cadViewerEngine");
56163
56326
  return stored === "jscad" || stored === "manifold" ? stored : "manifold";
56164
56327
  });
56165
56328
  const containerRef = useRef29(null);
56166
- const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState39(false);
56167
- const [autoRotate, setAutoRotate] = useState39(() => {
56329
+ const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState41(false);
56330
+ const [autoRotate, setAutoRotate] = useState41(() => {
56168
56331
  const stored = window.localStorage.getItem("cadViewerAutoRotate");
56169
56332
  return stored !== "false";
56170
56333
  });
56171
- const [autoRotateUserToggled, setAutoRotateUserToggled] = useState39(() => {
56334
+ const [autoRotateUserToggled, setAutoRotateUserToggled] = useState41(() => {
56172
56335
  const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled");
56173
56336
  return stored === "true";
56174
56337
  });
56175
- const [cameraPreset, setCameraPreset] = useState39("Custom");
56176
- const [referenceObject, setReferenceObject] = useState39(null);
56338
+ const [cameraPreset, setCameraPreset] = useState41("Custom");
56339
+ const [referenceObject, setReferenceObject] = useState41(null);
56177
56340
  const { cameraType } = useCameraController();
56178
56341
  const { visibility, setLayerVisibility } = useLayerVisibility();
56179
56342
  const { showToast } = useToast();
56180
56343
  const cameraControllerRef = useRef29(null);
56181
56344
  const externalCameraControllerReady = props.onCameraControllerReady;
56182
56345
  const sceneRef = useContext10(SchematicNavigationContext);
56183
- const [selectedComponent, setSelectedComponent] = useState39();
56346
+ const [selectedComponent, setSelectedComponent] = useState41();
56347
+ const [selectedCadComponent, setSelectedCadComponent] = useState41();
56184
56348
  const handleMenuOpen = useCallback24(
56185
56349
  (position) => {
56350
+ setSelectedCadComponent(
56351
+ pickCadComponent(sceneRef.current, position, circuitJson)
56352
+ );
56186
56353
  setSelectedComponent(
56187
56354
  props.onViewSchematicComponent ? pickSchematicComponent(sceneRef.current, position, circuitJson) : void 0
56188
56355
  );
@@ -56314,7 +56481,7 @@ var CadViewerInner = (props) => {
56314
56481
  useEffect50(() => {
56315
56482
  window.localStorage.setItem("cadViewerCameraType", cameraType);
56316
56483
  }, [cameraType]);
56317
- const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
56484
+ const viewerKey = props.circuitJson ? circuitKey : void 0;
56318
56485
  return /* @__PURE__ */ jsxs11(
56319
56486
  "div",
56320
56487
  {
@@ -56331,7 +56498,7 @@ var CadViewerInner = (props) => {
56331
56498
  },
56332
56499
  ...contextMenuEventHandlers,
56333
56500
  children: [
56334
- hasFlexGeometry ? /* @__PURE__ */ jsx38(
56501
+ hasFlexGeometry ? /* @__PURE__ */ jsx39(
56335
56502
  CadViewerManifold_default,
56336
56503
  {
56337
56504
  ...resolvedProps,
@@ -56341,7 +56508,7 @@ var CadViewerInner = (props) => {
56341
56508
  onCameraControllerReady: handleCameraControllerReady,
56342
56509
  referenceObject
56343
56510
  }
56344
- ) : engine === "jscad" ? /* @__PURE__ */ jsx38(
56511
+ ) : engine === "jscad" ? /* @__PURE__ */ jsx39(
56345
56512
  CadViewerJscad,
56346
56513
  {
56347
56514
  ...resolvedProps,
@@ -56351,7 +56518,7 @@ var CadViewerInner = (props) => {
56351
56518
  onCameraControllerReady: handleCameraControllerReady,
56352
56519
  referenceObject
56353
56520
  }
56354
- ) : /* @__PURE__ */ jsx38(
56521
+ ) : /* @__PURE__ */ jsx39(
56355
56522
  CadViewerManifold_default,
56356
56523
  {
56357
56524
  ...resolvedProps,
@@ -56362,9 +56529,18 @@ var CadViewerInner = (props) => {
56362
56529
  referenceObject
56363
56530
  }
56364
56531
  ),
56365
- menuVisible && /* @__PURE__ */ jsx38(
56532
+ menuVisible && /* @__PURE__ */ jsx39(
56366
56533
  ContextMenu,
56367
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,
56368
56544
  onViewSchematicComponent: selectedComponent && props.onViewSchematicComponent ? () => {
56369
56545
  props.onViewSchematicComponent?.(selectedComponent);
56370
56546
  closeMenu();
@@ -56413,7 +56589,7 @@ var CadViewerInner = (props) => {
56413
56589
  }
56414
56590
  }
56415
56591
  ),
56416
- /* @__PURE__ */ jsx38(
56592
+ /* @__PURE__ */ jsx39(
56417
56593
  KeyboardShortcutsDialog,
56418
56594
  {
56419
56595
  open: isKeyboardShortcutsDialogOpen,
@@ -56427,13 +56603,13 @@ var CadViewerInner = (props) => {
56427
56603
  };
56428
56604
  var CadViewer = (props) => {
56429
56605
  const sceneRef = useRef29(null);
56430
- return /* @__PURE__ */ jsx38(SchematicNavigationContext.Provider, { value: sceneRef, children: /* @__PURE__ */ jsx38(
56606
+ return /* @__PURE__ */ jsx39(SchematicNavigationContext.Provider, { value: sceneRef, children: /* @__PURE__ */ jsx39(
56431
56607
  CameraControllerProvider,
56432
56608
  {
56433
56609
  defaultTarget: DEFAULT_TARGET,
56434
56610
  initialCameraPosition: INITIAL_CAMERA_POSITION,
56435
56611
  initialCameraType: readStoredCameraType(),
56436
- children: /* @__PURE__ */ jsx38(LayerVisibilityProvider, { children: /* @__PURE__ */ jsx38(AppearanceProvider, { children: /* @__PURE__ */ jsx38(ToastProvider, { children: /* @__PURE__ */ jsx38(CadViewerInner, { ...props }) }) }) })
56612
+ children: /* @__PURE__ */ jsx39(LayerVisibilityProvider, { children: /* @__PURE__ */ jsx39(AppearanceProvider, { children: /* @__PURE__ */ jsx39(ToastProvider, { children: /* @__PURE__ */ jsx39(CadViewerInner, { ...props }) }) }) })
56437
56613
  }
56438
56614
  ) });
56439
56615
  };
@@ -56730,7 +56906,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
56730
56906
 
56731
56907
  // src/hooks/exporter/gltf.ts
56732
56908
  import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
56733
- import { useEffect as useEffect51, useState as useState40, useMemo as useMemo34, useCallback as useCallback25 } from "react";
56909
+ import { useEffect as useEffect51, useState as useState42, useMemo as useMemo34, useCallback as useCallback25 } from "react";
56734
56910
  function useSaveGltfAs(options = {}) {
56735
56911
  const parse2 = useParser(options);
56736
56912
  const link = useMemo34(() => document.createElement("a"), []);
@@ -56758,8 +56934,8 @@ function useSaveGltfAs(options = {}) {
56758
56934
  }
56759
56935
  function useExportGltfUrl(options = {}) {
56760
56936
  const parse2 = useParser(options);
56761
- const [url, setUrl] = useState40();
56762
- const [error, setError] = useState40();
56937
+ const [url, setUrl] = useState42();
56938
+ const [error, setError] = useState42();
56763
56939
  const ref = useCallback25(
56764
56940
  (instance) => parse2(instance).then(setUrl).catch(setError),
56765
56941
  []