@tscircuit/3d-viewer 0.0.609 → 0.0.611

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 useState42 } 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 useMemo9, useState as useState9 } 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,
@@ -38139,7 +38199,7 @@ function GltfModel({
38139
38199
  var import_jscad_planner = __toESM(require_dist(), 1);
38140
38200
  var import_modeling = __toESM(require_src(), 1);
38141
38201
  import * as THREE11 from "three";
38142
- import { useMemo as useMemo8, useEffect as useEffect9 } from "react";
38202
+ import { useState as useState6, useEffect as useEffect9 } from "react";
38143
38203
  import { jsx as jsx8 } from "react/jsx-runtime";
38144
38204
  var JscadModel = ({
38145
38205
  jscadPlan,
@@ -38156,31 +38216,39 @@ var JscadModel = ({
38156
38216
  scale: scale2,
38157
38217
  isTranslucent = false
38158
38218
  }) => {
38159
- const { threeGeom, material } = useMemo8(() => {
38219
+ const [mesh, setMesh] = useState6(null);
38220
+ useEffect9(() => {
38160
38221
  const jscadObject = (0, import_jscad_planner.executeJscadOperations)(import_modeling.default, jscadPlan);
38161
38222
  if (!jscadObject || !jscadObject.polygons && !jscadObject.sides) {
38162
- return { threeGeom: null, material: null };
38223
+ setMesh(null);
38224
+ return;
38163
38225
  }
38164
- const threeGeom2 = convertCSGToThreeGeom(jscadObject);
38226
+ const geometry = convertCSGToThreeGeom(jscadObject);
38165
38227
  const material2 = new THREE11.MeshStandardMaterial({
38166
38228
  vertexColors: true,
38167
- side: THREE11.DoubleSide,
38168
- transparent: isTranslucent,
38169
- opacity: isTranslucent ? 0.5 : 1,
38170
- depthWrite: !isTranslucent
38229
+ side: THREE11.DoubleSide
38171
38230
  });
38172
- return { threeGeom: threeGeom2, material: material2 };
38173
- }, [jscadPlan, isTranslucent]);
38174
- const mesh = useMemo8(() => {
38175
- if (!threeGeom) return null;
38176
- const createdMesh = new THREE11.Mesh(threeGeom, material);
38177
- createdMesh.renderOrder = isTranslucent ? 2 : 1;
38178
- configureObjectShadows(createdMesh, {
38231
+ const model = new THREE11.Mesh(geometry, material2);
38232
+ setMesh(model);
38233
+ return () => {
38234
+ geometry.dispose();
38235
+ material2.dispose();
38236
+ };
38237
+ }, [jscadPlan]);
38238
+ useEffect9(() => {
38239
+ if (!mesh) return;
38240
+ const material2 = mesh.material;
38241
+ material2.transparent = isTranslucent;
38242
+ material2.opacity = isTranslucent ? 0.5 : 1;
38243
+ material2.depthWrite = !isTranslucent;
38244
+ material2.needsUpdate = true;
38245
+ mesh.renderOrder = isTranslucent ? 2 : 1;
38246
+ configureObjectShadows(mesh, {
38179
38247
  castShadow: !isTranslucent,
38180
38248
  receiveShadow: true
38181
38249
  });
38182
- return createdMesh;
38183
- }, [threeGeom, material, isTranslucent]);
38250
+ }, [mesh, isTranslucent]);
38251
+ const material = mesh?.material;
38184
38252
  const { boardTransformGroup } = useCadModelTransformGraph({
38185
38253
  model: mesh,
38186
38254
  position: positionOffset,
@@ -38203,7 +38271,7 @@ var JscadModel = ({
38203
38271
  material.emissiveIntensity = 0;
38204
38272
  }
38205
38273
  }, [isHovered, material]);
38206
- if (!threeGeom) return null;
38274
+ if (!mesh) return null;
38207
38275
  return /* @__PURE__ */ jsx8(
38208
38276
  ContainerWithTooltip_default,
38209
38277
  {
@@ -38216,7 +38284,7 @@ var JscadModel = ({
38216
38284
  };
38217
38285
 
38218
38286
  // src/hooks/use-global-obj-loader.ts
38219
- import { useEffect as useEffect10, useState as useState5 } from "react";
38287
+ import { useEffect as useEffect10, useState as useState7 } from "react";
38220
38288
 
38221
38289
  // src/utils/vrml.ts
38222
38290
  import { VRMLLoader } from "three-stdlib";
@@ -38243,7 +38311,7 @@ if (typeof window !== "undefined" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {
38243
38311
  window.TSCIRCUIT_OBJ_LOADER_CACHE = /* @__PURE__ */ new Map();
38244
38312
  }
38245
38313
  function useGlobalObjLoader(url) {
38246
- const [obj, setObj] = useState5(null);
38314
+ const [obj, setObj] = useState7(null);
38247
38315
  useEffect10(() => {
38248
38316
  if (!url) return;
38249
38317
  const cleanUrl = url.replace(/&cachebust_origin=$/, "");
@@ -38314,7 +38382,7 @@ function useGlobalObjLoader(url) {
38314
38382
  }
38315
38383
 
38316
38384
  // src/three-components/MixedStlModel.tsx
38317
- import { useMemo as useMemo9 } from "react";
38385
+ import { useMemo as useMemo8 } from "react";
38318
38386
  import * as THREE12 from "three";
38319
38387
  import { jsx as jsx9 } from "react/jsx-runtime";
38320
38388
  function MixedStlModel({
@@ -38333,7 +38401,7 @@ function MixedStlModel({
38333
38401
  isTranslucent = false
38334
38402
  }) {
38335
38403
  const obj = useGlobalObjLoader(url);
38336
- const model = useMemo9(() => {
38404
+ const model = useMemo8(() => {
38337
38405
  if (obj && !(obj instanceof Error)) {
38338
38406
  obj.traverse((child) => {
38339
38407
  if (child instanceof THREE12.Mesh && child.material) {
@@ -38397,7 +38465,7 @@ function MixedStlModel({
38397
38465
  }
38398
38466
 
38399
38467
  // src/three-components/StepModel.tsx
38400
- import { useEffect as useEffect11, useState as useState6 } from "react";
38468
+ import { useEffect as useEffect11, useState as useState8 } from "react";
38401
38469
  import { GLTFExporter } from "three-stdlib";
38402
38470
 
38403
38471
  // src/three-components/step-mesh-to-group.ts
@@ -38611,7 +38679,7 @@ var StepModel = ({
38611
38679
  isHovered,
38612
38680
  isTranslucent
38613
38681
  }) => {
38614
- const [stepGltfUrl, setStepGltfUrl] = useState6(null);
38682
+ const [stepGltfUrl, setStepGltfUrl] = useState8(null);
38615
38683
  useEffect11(() => {
38616
38684
  let isActive = true;
38617
38685
  let objectUrl = null;
@@ -39049,9 +39117,9 @@ var AnyCadComponent = ({
39049
39117
  resolveStaticAsset
39050
39118
  }) => {
39051
39119
  const pcbThickness = usePcbThickness(circuitJson);
39052
- const [isHovered, setIsHovered] = useState7(false);
39120
+ const [isHovered, setIsHovered] = useState9(false);
39053
39121
  const { visibility } = useLayerVisibility();
39054
- const [hoverPosition, setHoverPosition] = useState7(null);
39122
+ const [hoverPosition, setHoverPosition] = useState9(null);
39055
39123
  const handleHover = useCallback3((e) => {
39056
39124
  if (e?.mousePosition) {
39057
39125
  setIsHovered(true);
@@ -39065,12 +39133,12 @@ var AnyCadComponent = ({
39065
39133
  setIsHovered(false);
39066
39134
  setHoverPosition(null);
39067
39135
  }, []);
39068
- const componentName = useMemo10(() => {
39136
+ const componentName = useMemo9(() => {
39069
39137
  return su2(circuitJson).source_component.getUsing({
39070
39138
  source_component_id: cad_component.source_component_id
39071
39139
  })?.name;
39072
39140
  }, [circuitJson, cad_component.source_component_id]);
39073
- const { pcbComponent, layer, isThroughHole } = useMemo10(
39141
+ const { pcbComponent, layer, isThroughHole } = useMemo9(
39074
39142
  () => getCadPcbContext(cad_component, circuitJson),
39075
39143
  [cad_component, circuitJson]
39076
39144
  );
@@ -39087,13 +39155,13 @@ var AnyCadComponent = ({
39087
39155
  const stepUrl = resolveModelUrlWithStaticResolver(
39088
39156
  cad_component.model_step_url
39089
39157
  );
39090
- const [fallbackModelIndex, setFallbackModelIndex] = useState7(0);
39091
- const [lastModelError, setLastModelError] = useState7(null);
39158
+ const [fallbackModelIndex, setFallbackModelIndex] = useState9(0);
39159
+ const [lastModelError, setLastModelError] = useState9(null);
39092
39160
  useEffect12(() => {
39093
39161
  setFallbackModelIndex(0);
39094
39162
  setLastModelError(null);
39095
39163
  }, [cad_component.cad_component_id, url, gltfUrl, stepUrl]);
39096
- const isEnclosure = useMemo10(
39164
+ const isEnclosure = useMemo9(
39097
39165
  () => isLegacyFdmEnclosure(cad_component, circuitJson),
39098
39166
  [cad_component, circuitJson]
39099
39167
  );
@@ -39102,7 +39170,7 @@ var AnyCadComponent = ({
39102
39170
  const renderedModelType = getRenderedCadModelType(sourceModelType);
39103
39171
  const gltfModelType = cad_component.model_glb_url ? "glb" : "gltf";
39104
39172
  const meshModelType = cad_component.model_wrl_url ? "wrl" : cad_component.model_stl_url ? "stl" : "obj";
39105
- const modelTransform = useMemo10(
39173
+ const modelTransform = useMemo9(
39106
39174
  () => getCadModelTransform(cad_component, {
39107
39175
  layer,
39108
39176
  pcbThickness,
@@ -39112,7 +39180,7 @@ var AnyCadComponent = ({
39112
39180
  );
39113
39181
  const rotationOffset = tuple(...modelTransform.rotation);
39114
39182
  const adjustedPosition = modelTransform.position;
39115
- const fallbackModelComponents = useMemo10(() => {
39183
+ const fallbackModelComponents = useMemo9(() => {
39116
39184
  const components = [];
39117
39185
  if (gltfUrl) {
39118
39186
  components.push(
@@ -39309,13 +39377,13 @@ var AnyCadComponent = ({
39309
39377
  };
39310
39378
 
39311
39379
  // src/CadViewerContainer.tsx
39312
- import { forwardRef as forwardRef2, useEffect as useEffect21, useMemo as useMemo18, useState as useState11 } from "react";
39380
+ import { forwardRef as forwardRef2, useEffect as useEffect21, useMemo as useMemo17, useState as useState13 } from "react";
39313
39381
  import * as THREE25 from "three";
39314
39382
 
39315
39383
  // package.json
39316
39384
  var package_default = {
39317
39385
  name: "@tscircuit/3d-viewer",
39318
- version: "0.0.608",
39386
+ version: "0.0.610",
39319
39387
  repository: {
39320
39388
  type: "git",
39321
39389
  url: "https://github.com/tscircuit/3d-viewer"
@@ -39413,7 +39481,7 @@ var package_default = {
39413
39481
  };
39414
39482
 
39415
39483
  // src/contexts/appearance-context.tsx
39416
- import { createContext as createContext5, useContext as useContext5, useEffect as useEffect13, useMemo as useMemo11, useState as useState8 } from "react";
39484
+ import { createContext as createContext5, useContext as useContext5, useEffect as useEffect13, useMemo as useMemo10, useState as useState10 } from "react";
39417
39485
  import { jsx as jsx12 } from "react/jsx-runtime";
39418
39486
  var LIGHTING_STORAGE_KEY = "cadViewerLightingEnabled";
39419
39487
  var readStoredLightingEnabled = () => {
@@ -39426,9 +39494,9 @@ var AppearanceContext = createContext5(
39426
39494
  var AppearanceProvider = ({
39427
39495
  children
39428
39496
  }) => {
39429
- const [darkBackgroundEnabled, setDarkBackgroundEnabled] = useState8(false);
39430
- const [gridEnabled, setGridEnabled] = useState8(false);
39431
- const [lightingEnabled, setLightingEnabled] = useState8(
39497
+ const [darkBackgroundEnabled, setDarkBackgroundEnabled] = useState10(false);
39498
+ const [gridEnabled, setGridEnabled] = useState10(false);
39499
+ const [lightingEnabled, setLightingEnabled] = useState10(
39432
39500
  readStoredLightingEnabled
39433
39501
  );
39434
39502
  useEffect13(() => {
@@ -39437,7 +39505,7 @@ var AppearanceProvider = ({
39437
39505
  lightingEnabled ? "true" : "false"
39438
39506
  );
39439
39507
  }, [lightingEnabled]);
39440
- const value = useMemo11(
39508
+ const value = useMemo10(
39441
39509
  () => ({
39442
39510
  darkBackgroundEnabled,
39443
39511
  setDarkBackgroundEnabled,
@@ -39463,9 +39531,9 @@ import {
39463
39531
  createContext as createContext6,
39464
39532
  useCallback as useCallback4,
39465
39533
  useContext as useContext6,
39466
- useMemo as useMemo12,
39534
+ useMemo as useMemo11,
39467
39535
  useRef as useRef3,
39468
- useState as useState9
39536
+ useState as useState11
39469
39537
  } from "react";
39470
39538
  import * as THREE15 from "three";
39471
39539
  import { jsx as jsx13 } from "react/jsx-runtime";
@@ -39510,15 +39578,15 @@ var CameraControllerContext = createContext6(void 0);
39510
39578
  var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition, initialCameraType }) => {
39511
39579
  const controlsRef = useRef3(null);
39512
39580
  const mainCameraRef = useRef3(null);
39513
- const [controller, setController] = useState9(null);
39514
- const [cameraType, setCameraType] = useState9(
39581
+ const [controller, setController] = useState11(null);
39582
+ const [cameraType, setCameraType] = useState11(
39515
39583
  initialCameraType ?? "perspective"
39516
39584
  );
39517
- const [cameraPosition, setCameraPosition] = useState9(initialCameraPosition ?? null);
39518
- const [cameraRotation, setCameraRotation] = useState9(
39585
+ const [cameraPosition, setCameraPosition] = useState11(initialCameraPosition ?? null);
39586
+ const [cameraRotation, setCameraRotation] = useState11(
39519
39587
  new THREE15.Euler(0, 0, 0)
39520
39588
  );
39521
- const baseDistance = useMemo12(() => {
39589
+ const baseDistance = useMemo11(() => {
39522
39590
  const [x, y, z42] = initialCameraPosition ?? [5, -5, 5];
39523
39591
  const distance6 = Math.hypot(
39524
39592
  x - defaultTarget.x,
@@ -39626,7 +39694,7 @@ var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition
39626
39694
  },
39627
39695
  []
39628
39696
  );
39629
- const cameraControllerContextValue = useMemo12(
39697
+ const cameraControllerContextValue = useMemo11(
39630
39698
  () => ({
39631
39699
  controlsRef,
39632
39700
  mainCameraRef,
@@ -39857,11 +39925,11 @@ var useCameraSession = () => {
39857
39925
  import {
39858
39926
  useRef as useRef6,
39859
39927
  useEffect as useEffect15,
39860
- useState as useState10,
39928
+ useState as useState12,
39861
39929
  useCallback as useCallback7,
39862
39930
  forwardRef,
39863
39931
  useImperativeHandle,
39864
- useMemo as useMemo13
39932
+ useMemo as useMemo12
39865
39933
  } from "react";
39866
39934
  import * as THREE18 from "three";
39867
39935
 
@@ -39886,7 +39954,7 @@ var Canvas = forwardRef(
39886
39954
  ({ children, scene: sceneProps, camera: cameraProps, style, onCreated }, ref) => {
39887
39955
  const { cameraType } = useCameraController();
39888
39956
  const mountRef = useRef6(null);
39889
- const [contextState, setContextState] = useState10(
39957
+ const [contextState, setContextState] = useState12(
39890
39958
  null
39891
39959
  );
39892
39960
  const frameListeners = useRef6(
@@ -39909,7 +39977,7 @@ var Canvas = forwardRef(
39909
39977
  },
39910
39978
  []
39911
39979
  );
39912
- const scene = useMemo13(() => new THREE18.Scene(), []);
39980
+ const scene = useMemo12(() => new THREE18.Scene(), []);
39913
39981
  if (sceneProps?.up) {
39914
39982
  scene.up.set(sceneProps.up.x, sceneProps.up.y, sceneProps.up.z);
39915
39983
  }
@@ -40023,7 +40091,7 @@ var Canvas = forwardRef(
40023
40091
  );
40024
40092
 
40025
40093
  // src/react-three/Grid.tsx
40026
- import { useEffect as useEffect16, useMemo as useMemo14 } from "react";
40094
+ import { useEffect as useEffect16, useMemo as useMemo13 } from "react";
40027
40095
  import * as THREE19 from "three";
40028
40096
  var vertexShader = `
40029
40097
  varying vec3 worldPosition;
@@ -40069,7 +40137,7 @@ var Grid = ({
40069
40137
  }) => {
40070
40138
  const { scene, camera } = useThree();
40071
40139
  const size4 = 1e3;
40072
- const gridMesh = useMemo14(() => {
40140
+ const gridMesh = useMemo13(() => {
40073
40141
  const geometry = new THREE19.PlaneGeometry(size4, size4);
40074
40142
  geometry.rotateX(-Math.PI / 2);
40075
40143
  const material = new THREE19.ShaderMaterial({
@@ -40115,7 +40183,7 @@ var Grid = ({
40115
40183
  };
40116
40184
 
40117
40185
  // src/react-three/Lights.tsx
40118
- import { useEffect as useEffect17, useMemo as useMemo15 } from "react";
40186
+ import { useEffect as useEffect17, useMemo as useMemo14 } from "react";
40119
40187
  import * as THREE20 from "three";
40120
40188
  var UNDERSIDE_LIGHT_FACTOR = 0.75;
40121
40189
  var Lights = ({
@@ -40125,7 +40193,7 @@ var Lights = ({
40125
40193
  shadowsEnabled = false
40126
40194
  }) => {
40127
40195
  const { scene } = useThree();
40128
- const lightRig = useMemo15(() => {
40196
+ const lightRig = useMemo14(() => {
40129
40197
  const rig = new THREE20.Group();
40130
40198
  rig.name = "cad-viewer-light-rig";
40131
40199
  const centerX = boardCenter?.x ?? 0;
@@ -40240,7 +40308,7 @@ var Lights = ({
40240
40308
  };
40241
40309
 
40242
40310
  // src/react-three/OrbitControls.tsx
40243
- import { useEffect as useEffect18, useMemo as useMemo16 } from "react";
40311
+ import { useEffect as useEffect18, useMemo as useMemo15 } from "react";
40244
40312
  import * as THREE21 from "three";
40245
40313
  import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
40246
40314
  var OrbitControls = ({
@@ -40256,7 +40324,7 @@ var OrbitControls = ({
40256
40324
  onControlsChange
40257
40325
  }) => {
40258
40326
  const { camera, renderer } = useThree();
40259
- const controls = useMemo16(() => {
40327
+ const controls = useMemo15(() => {
40260
40328
  if (!camera || !renderer) return null;
40261
40329
  return new ThreeOrbitControls(camera, renderer.domElement);
40262
40330
  }, [camera, renderer]);
@@ -40564,7 +40632,7 @@ var OrientationCubeCanvas = () => {
40564
40632
  };
40565
40633
 
40566
40634
  // src/three-components/reference-object.tsx
40567
- import { useEffect as useEffect20, useMemo as useMemo17 } from "react";
40635
+ import { useEffect as useEffect20, useMemo as useMemo16 } from "react";
40568
40636
 
40569
40637
  // src/reference-objects/create-reference-object.ts
40570
40638
  import * as THREE23 from "three";
@@ -40950,7 +41018,7 @@ var ReferenceObject = ({
40950
41018
  boardCenter
40951
41019
  }) => {
40952
41020
  const { scene } = useThree();
40953
- const object = useMemo17(() => {
41021
+ const object = useMemo16(() => {
40954
41022
  const nextObject = createReferenceObject(type);
40955
41023
  const position = getReferenceObjectPosition(
40956
41024
  type,
@@ -41002,7 +41070,7 @@ var CadViewerContainer = forwardRef2(
41002
41070
  onUserInteraction,
41003
41071
  onCameraControllerReady
41004
41072
  }, ref) => {
41005
- const [isInteractionEnabled, setIsInteractionEnabled] = useState11(
41073
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState13(
41006
41074
  !clickToInteractEnabled
41007
41075
  );
41008
41076
  const { mainCameraRef, handleControlsChange, controller } = useCameraController();
@@ -41016,17 +41084,17 @@ var CadViewerContainer = forwardRef2(
41016
41084
  onCameraControllerReady(controller);
41017
41085
  }
41018
41086
  }, [controller, onCameraControllerReady]);
41019
- const comparisonBounds = useMemo18(() => {
41087
+ const comparisonBounds = useMemo17(() => {
41020
41088
  if (!referenceObject) return void 0;
41021
41089
  return getComparisonBounds(referenceObject, boardDimensions, boardCenter);
41022
41090
  }, [referenceObject, boardDimensions, boardCenter]);
41023
- const gridSectionSize = useMemo18(() => {
41091
+ const gridSectionSize = useMemo17(() => {
41024
41092
  if (!boardDimensions) return 10;
41025
41093
  const width10 = boardDimensions.width ?? 0;
41026
41094
  const height10 = boardDimensions.height ?? 0;
41027
41095
  return Math.max(Math.max(width10, height10) * 1.5, 10);
41028
41096
  }, [boardDimensions]);
41029
- const orbitTarget = useMemo18(() => {
41097
+ const orbitTarget = useMemo17(() => {
41030
41098
  if (comparisonBounds) {
41031
41099
  return [
41032
41100
  (comparisonBounds.minX + comparisonBounds.maxX) / 2,
@@ -41161,11 +41229,11 @@ var CadViewerContainer = forwardRef2(
41161
41229
  );
41162
41230
 
41163
41231
  // src/hooks/use-stls-from-geom.ts
41164
- import { useState as useState12, useEffect as useEffect22 } from "react";
41232
+ import { useState as useState14, useEffect as useEffect22 } from "react";
41165
41233
  import stlSerializer from "@jscad/stl-serializer";
41166
41234
  var useStlsFromGeom = (geom) => {
41167
- const [stls, setStls] = useState12([]);
41168
- const [loading, setLoading] = useState12(true);
41235
+ const [stls, setStls] = useState14([]);
41236
+ const [loading, setLoading] = useState14(true);
41169
41237
  useEffect22(() => {
41170
41238
  if (!geom) return;
41171
41239
  const generateStls = async () => {
@@ -41195,7 +41263,7 @@ var useStlsFromGeom = (geom) => {
41195
41263
  };
41196
41264
 
41197
41265
  // src/hooks/useBoardGeomBuilder.ts
41198
- import { useState as useState13, useEffect as useEffect23, useRef as useRef8 } from "react";
41266
+ import { useState as useState15, useEffect as useEffect23, useRef as useRef8 } from "react";
41199
41267
 
41200
41268
  // src/soup-to-3d/index.ts
41201
41269
  var import_colors = __toESM(require_colors(), 1);
@@ -42637,7 +42705,7 @@ var BoardGeomBuilder = class {
42637
42705
 
42638
42706
  // src/hooks/useBoardGeomBuilder.ts
42639
42707
  var useBoardGeomBuilder = (circuitJson) => {
42640
- const [boardGeom, setBoardGeom] = useState13(null);
42708
+ const [boardGeom, setBoardGeom] = useState15(null);
42641
42709
  const isProcessingRef = useRef8(false);
42642
42710
  useEffect23(() => {
42643
42711
  let isCancelled = false;
@@ -42685,10 +42753,10 @@ var useBoardGeomBuilder = (circuitJson) => {
42685
42753
  };
42686
42754
 
42687
42755
  // src/three-components/Error3d.tsx
42688
- import { useState as useState14, useCallback as useCallback8, useEffect as useEffect25, useMemo as useMemo20 } from "react";
42756
+ import { useState as useState16, useCallback as useCallback8, useEffect as useEffect25, useMemo as useMemo19 } from "react";
42689
42757
 
42690
42758
  // src/react-three/Text.tsx
42691
- import { useEffect as useEffect24, useMemo as useMemo19 } from "react";
42759
+ import { useEffect as useEffect24, useMemo as useMemo18 } from "react";
42692
42760
  import { Text as TroikaText2 } from "troika-three-text";
42693
42761
  var Text = ({
42694
42762
  children,
@@ -42703,7 +42771,7 @@ var Text = ({
42703
42771
  depthOffset
42704
42772
  }) => {
42705
42773
  const { rootObject } = useThree();
42706
- const mesh = useMemo19(() => {
42774
+ const mesh = useMemo18(() => {
42707
42775
  const textMesh = new TroikaText2();
42708
42776
  textMesh.text = children;
42709
42777
  if (position) textMesh.position.fromArray(position);
@@ -42748,8 +42816,8 @@ var Error3d = ({
42748
42816
  cad_component
42749
42817
  }) => {
42750
42818
  const { rootObject } = useThree();
42751
- const [isHovered, setIsHovered] = useState14(false);
42752
- const [hoverPosition, setHoverPosition] = useState14(null);
42819
+ const [isHovered, setIsHovered] = useState16(false);
42820
+ const [hoverPosition, setHoverPosition] = useState16(null);
42753
42821
  const handleHover = useCallback8((e) => {
42754
42822
  if (e?.mousePosition) {
42755
42823
  setIsHovered(true);
@@ -42763,7 +42831,7 @@ var Error3d = ({
42763
42831
  setIsHovered(false);
42764
42832
  setHoverPosition(null);
42765
42833
  }, []);
42766
- const position = useMemo20(() => {
42834
+ const position = useMemo19(() => {
42767
42835
  if (cad_component?.position) {
42768
42836
  const p = [
42769
42837
  cad_component.position.x,
@@ -42774,11 +42842,13 @@ var Error3d = ({
42774
42842
  }
42775
42843
  return [0, 0, 0];
42776
42844
  }, [cad_component]);
42777
- const group = useMemo20(() => {
42845
+ const group = useMemo19(() => {
42778
42846
  const g = new THREE28.Group();
42779
42847
  g.position.fromArray(position);
42780
42848
  return g;
42781
42849
  }, [position]);
42850
+ group.userData.cad_component_id = cad_component?.cad_component_id;
42851
+ group.userData.pcb_component_id = cad_component?.pcb_component_id;
42782
42852
  useEffect25(() => {
42783
42853
  if (!rootObject) return;
42784
42854
  rootObject.add(group);
@@ -42834,7 +42904,7 @@ var Error3d = ({
42834
42904
  ] });
42835
42905
  };
42836
42906
  var ErrorBox = ({ parent }) => {
42837
- const mesh = useMemo20(() => {
42907
+ const mesh = useMemo19(() => {
42838
42908
  const m = new THREE28.Mesh(
42839
42909
  new THREE28.BoxGeometry(0.5, 0.5, 0.5),
42840
42910
  new THREE28.MeshStandardMaterial({
@@ -44970,6 +45040,46 @@ function createTextureMeshes(textures, boardData, pcbThickness, isFaux = false)
44970
45040
  // src/three-components/JscadBoardTextures.tsx
44971
45041
  import * as THREE44 from "three";
44972
45042
 
45043
+ // src/hooks/useBoardTextureVisibility.ts
45044
+ import { useMemo as useMemo20 } from "react";
45045
+ var useBoardTextureVisibility = (visibility) => {
45046
+ const {
45047
+ boardBody,
45048
+ topCopper,
45049
+ bottomCopper,
45050
+ topSilkscreen,
45051
+ bottomSilkscreen,
45052
+ topMask,
45053
+ bottomMask,
45054
+ keepout,
45055
+ pcbNotes
45056
+ } = visibility;
45057
+ return useMemo20(
45058
+ () => ({
45059
+ boardBody,
45060
+ topCopper,
45061
+ bottomCopper,
45062
+ topSilkscreen,
45063
+ bottomSilkscreen,
45064
+ topMask,
45065
+ bottomMask,
45066
+ keepout,
45067
+ pcbNotes
45068
+ }),
45069
+ [
45070
+ boardBody,
45071
+ topCopper,
45072
+ bottomCopper,
45073
+ topSilkscreen,
45074
+ bottomSilkscreen,
45075
+ topMask,
45076
+ bottomMask,
45077
+ keepout,
45078
+ pcbNotes
45079
+ ]
45080
+ );
45081
+ };
45082
+
44973
45083
  // src/utils/layer-texture-resolution.ts
44974
45084
  var DEFAULT_MAX_TEXTURE_PIXELS = 4e6;
44975
45085
  var DEFAULT_MAX_TEXTURE_DIMENSION = 4096;
@@ -45005,6 +45115,7 @@ function JscadBoardTextures({
45005
45115
  }) {
45006
45116
  const { rootObject } = useThree();
45007
45117
  const { visibility } = useLayerVisibility();
45118
+ const textureVisibility = useBoardTextureVisibility(visibility);
45008
45119
  const boardData = useMemo21(() => {
45009
45120
  const panels = circuitJson.filter(
45010
45121
  (e) => e.type === "pcb_panel"
@@ -45042,9 +45153,9 @@ function JscadBoardTextures({
45042
45153
  circuitJson,
45043
45154
  boardData,
45044
45155
  traceTextureResolution,
45045
- visibility
45156
+ visibility: textureVisibility
45046
45157
  });
45047
- }, [circuitJson, boardData, traceTextureResolution, visibility]);
45158
+ }, [circuitJson, boardData, traceTextureResolution, textureVisibility]);
45048
45159
  useEffect26(() => {
45049
45160
  if (!rootObject || !boardData || !textures) return;
45050
45161
  const meshes = [];
@@ -45183,7 +45294,7 @@ function JscadBoardTextures({
45183
45294
  }
45184
45295
 
45185
45296
  // src/three-components/STLModel.tsx
45186
- import { useState as useState15, useEffect as useEffect27, useMemo as useMemo22 } from "react";
45297
+ import { useState as useState17, useEffect as useEffect27, useMemo as useMemo22 } from "react";
45187
45298
  import * as THREE45 from "three";
45188
45299
  import { STLLoader } from "three-stdlib";
45189
45300
  function STLModel({
@@ -45195,7 +45306,7 @@ function STLModel({
45195
45306
  layerType
45196
45307
  }) {
45197
45308
  const { rootObject } = useThree();
45198
- const [geom, setGeom] = useState15(null);
45309
+ const [geom, setGeom] = useState17(null);
45199
45310
  useEffect27(() => {
45200
45311
  const loader = new STLLoader();
45201
45312
  if (stlData) {
@@ -45383,7 +45494,8 @@ var CadViewerJscad = forwardRef3(
45383
45494
  onUserInteraction,
45384
45495
  onCameraControllerReady,
45385
45496
  resolveStaticAsset,
45386
- referenceObject
45497
+ referenceObject,
45498
+ hiddenCadComponentIds
45387
45499
  }, ref) => {
45388
45500
  const childrenSoup = useConvertChildrenToCircuitJson(children);
45389
45501
  const internalCircuitJson = useMemo23(() => {
@@ -45453,7 +45565,7 @@ var CadViewerJscad = forwardRef3(
45453
45565
  }, [internalCircuitJson]);
45454
45566
  const pcbThickness = usePcbThickness(internalCircuitJson);
45455
45567
  const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
45456
- const cad_components = su12(internalCircuitJson).cad_component.list();
45568
+ const cad_components = su12(internalCircuitJson).cad_component.list().filter((cad) => !hiddenCadComponentIds?.has(cad.cad_component_id));
45457
45569
  return /* @__PURE__ */ jsxs5(
45458
45570
  CadViewerContainer,
45459
45571
  {
@@ -45710,15 +45822,11 @@ function indexSegment(head, stop) {
45710
45822
  do {
45711
45823
  const b = numBlocks++;
45712
45824
  blockHead[b] = p;
45713
- let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
45825
+ let minX = p.x, minY = p.y, maxX = p.x, maxY = p.y;
45714
45826
  let k = 0;
45715
45827
  do {
45716
45828
  const c = p.next;
45717
45829
  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
45830
  if (c.x < minX) minX = c.x;
45723
45831
  if (c.x > maxX) maxX = c.x;
45724
45832
  if (c.y < minY) minY = c.y;
@@ -45827,6 +45935,20 @@ function indexCurve(start, minX, minY, invSize) {
45827
45935
  prev = node;
45828
45936
  }
45829
45937
  prev.nextZ = null;
45938
+ sortArr.fill(
45939
+ /** @type {Node} */
45940
+ /** @type {unknown} */
45941
+ null,
45942
+ 0,
45943
+ n
45944
+ );
45945
+ sortBuf.fill(
45946
+ /** @type {Node} */
45947
+ /** @type {unknown} */
45948
+ null,
45949
+ 0,
45950
+ n
45951
+ );
45830
45952
  }
45831
45953
  function sortNodes(n) {
45832
45954
  if (n <= 32) {
@@ -46630,12 +46752,12 @@ function createFlexMeshes(geometryMeshes, textureMeshes, json, foldPcbs) {
46630
46752
 
46631
46753
  // src/CadViewerManifold.tsx
46632
46754
  import { su as su17 } from "@tscircuit/circuit-json-util";
46633
- import { useEffect as useEffect29, useMemo as useMemo25, useState as useState17 } from "react";
46755
+ import { useEffect as useEffect29, useMemo as useMemo25, useState as useState19 } from "react";
46634
46756
  import * as THREE53 from "three";
46635
46757
 
46636
46758
  // src/hooks/useManifoldBoardBuilder.ts
46637
46759
  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";
46760
+ import { useEffect as useEffect28, useMemo as useMemo24, useRef as useRef9, useState as useState18 } from "react";
46639
46761
  import * as THREE50 from "three";
46640
46762
 
46641
46763
  // src/utils/manifold/create-manifold-board.ts
@@ -47750,10 +47872,11 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
47750
47872
 
47751
47873
  // src/hooks/useManifoldBoardBuilder.ts
47752
47874
  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);
47875
+ const textureVisibility = useBoardTextureVisibility(visibility);
47876
+ const [geoms, setGeoms] = useState18(null);
47877
+ const [pcbThickness, setPcbThickness] = useState18(null);
47878
+ const [error, setError] = useState18(null);
47879
+ const [isLoading, setIsLoading] = useState18(true);
47757
47880
  const manifoldInstancesForCleanup = useRef9([]);
47758
47881
  const boardData = useMemo24(() => {
47759
47882
  const panels = circuitJson.filter(
@@ -47973,9 +48096,9 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
47973
48096
  circuitJson,
47974
48097
  boardData,
47975
48098
  traceTextureResolution,
47976
- visibility
48099
+ visibility: textureVisibility
47977
48100
  });
47978
- }, [circuitJson, boardData, traceTextureResolution, visibility]);
48101
+ }, [circuitJson, boardData, traceTextureResolution, textureVisibility]);
47979
48102
  return {
47980
48103
  geoms,
47981
48104
  textures,
@@ -48157,15 +48280,16 @@ var CadViewerManifold = ({
48157
48280
  children,
48158
48281
  onCameraControllerReady,
48159
48282
  resolveStaticAsset,
48160
- referenceObject
48283
+ referenceObject,
48284
+ hiddenCadComponentIds
48161
48285
  }) => {
48162
48286
  const childrenCircuitJson = useConvertChildrenToCircuitJson(children);
48163
48287
  const circuitJson = useMemo25(() => {
48164
48288
  const rawCircuitJson = circuitJsonProp ?? childrenCircuitJson;
48165
48289
  return addFauxBoardIfNeeded(rawCircuitJson);
48166
48290
  }, [circuitJsonProp, childrenCircuitJson]);
48167
- const [manifoldJSModule, setManifoldJSModule] = useState17(null);
48168
- const [manifoldLoadingError, setManifoldLoadingError] = useState17(null);
48291
+ const [manifoldJSModule, setManifoldJSModule] = useState19(null);
48292
+ const [manifoldLoadingError, setManifoldLoadingError] = useState19(null);
48169
48293
  const { visibility } = useLayerVisibility();
48170
48294
  useEffect29(() => {
48171
48295
  if (window.ManifoldModule && typeof window.ManifoldModule === "object" && window.ManifoldModule.setup) {
@@ -48270,8 +48394,8 @@ try {
48270
48394
  foldPcbs
48271
48395
  ]);
48272
48396
  const cadComponents = useMemo25(
48273
- () => su17(flex.posedJson).cad_component.list(),
48274
- [flex.posedJson]
48397
+ () => su17(flex.posedJson).cad_component.list().filter((cad) => !hiddenCadComponentIds?.has(cad.cad_component_id)),
48398
+ [flex.posedJson, hiddenCadComponentIds]
48275
48399
  );
48276
48400
  const boardDimensions = useMemo25(() => {
48277
48401
  if (!boardData) return void 0;
@@ -52970,9 +53094,9 @@ function assignRef(ref, value) {
52970
53094
  }
52971
53095
 
52972
53096
  // node_modules/use-callback-ref/dist/es2015/useRef.js
52973
- import { useState as useState30 } from "react";
53097
+ import { useState as useState32 } from "react";
52974
53098
  function useCallbackRef2(initialValue, callback) {
52975
- var ref = useState30(function() {
53099
+ var ref = useState32(function() {
52976
53100
  return {
52977
53101
  // value
52978
53102
  value: initialValue,
@@ -54583,11 +54707,11 @@ var SubTrigger2 = DropdownMenuSubTrigger;
54583
54707
  var SubContent2 = DropdownMenuSubContent;
54584
54708
 
54585
54709
  // src/components/ViewportSubContent.tsx
54586
- import { useLayoutEffect as useLayoutEffect5, useState as useState34 } from "react";
54710
+ import { useLayoutEffect as useLayoutEffect5, useState as useState36 } from "react";
54587
54711
  import { jsx as jsx33 } from "react/jsx-runtime";
54588
54712
  var ViewportSubContent = (props) => {
54589
- const [content, setContent] = useState34(null);
54590
- const [overlapWidth, setOverlapWidth] = useState34();
54713
+ const [content, setContent] = useState36(null);
54714
+ const [overlapWidth, setOverlapWidth] = useState36();
54591
54715
  useLayoutEffect5(() => {
54592
54716
  if (!content) return;
54593
54717
  const trigger = document.getElementById(
@@ -54642,10 +54766,10 @@ var menuViewportStyles = {
54642
54766
  };
54643
54767
 
54644
54768
  // src/components/ContextMenu.tsx
54645
- import { useState as useState36 } from "react";
54769
+ import { useState as useState38 } from "react";
54646
54770
 
54647
54771
  // src/components/AppearanceMenu.tsx
54648
- import { useState as useState35 } from "react";
54772
+ import { useState as useState37 } from "react";
54649
54773
 
54650
54774
  // src/components/Icons.tsx
54651
54775
  import { jsx as jsx34 } from "react/jsx-runtime";
@@ -54772,8 +54896,8 @@ var AppearanceMenu = () => {
54772
54896
  lightingEnabled,
54773
54897
  setLightingEnabled
54774
54898
  } = useAppearance();
54775
- const [appearanceSubOpen, setAppearanceSubOpen] = useState35(false);
54776
- const [hoveredItem, setHoveredItem] = useState35(null);
54899
+ const [appearanceSubOpen, setAppearanceSubOpen] = useState37(false);
54900
+ const [hoveredItem, setHoveredItem] = useState37(null);
54777
54901
  return /* @__PURE__ */ jsxs7(Fragment10, { children: [
54778
54902
  /* @__PURE__ */ jsx35(Separator2, { style: separatorStyles }),
54779
54903
  /* @__PURE__ */ jsxs7(Sub2, { onOpenChange: setAppearanceSubOpen, children: [
@@ -55214,14 +55338,17 @@ var ContextMenu = ({
55214
55338
  onReferenceObjectSelect = () => {
55215
55339
  },
55216
55340
  onViewSchematicComponent,
55341
+ componentName,
55342
+ onHideComponent,
55343
+ onUnhideAllComponents,
55217
55344
  onDownloadGltf,
55218
55345
  onOpenKeyboardShortcuts
55219
55346
  }) => {
55220
55347
  const { cameraType, setCameraType } = useCameraController();
55221
55348
  const { gridEnabled, setGridEnabled } = useAppearance();
55222
- const [cameraSubOpen, setCameraSubOpen] = useState36(false);
55223
- const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState36(false);
55224
- const [hoveredItem, setHoveredItem] = useState36(null);
55349
+ const [cameraSubOpen, setCameraSubOpen] = useState38(false);
55350
+ const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState38(false);
55351
+ const [hoveredItem, setHoveredItem] = useState38(null);
55225
55352
  return /* @__PURE__ */ jsx36(
55226
55353
  "div",
55227
55354
  {
@@ -55244,23 +55371,49 @@ var ContextMenu = ({
55244
55371
  sideOffset: 0,
55245
55372
  align: "start",
55246
55373
  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
- ] }),
55374
+ onViewSchematicComponent && /* @__PURE__ */ jsx36(Fragment11, { children: /* @__PURE__ */ jsx36(
55375
+ Item22,
55376
+ {
55377
+ style: {
55378
+ ...itemStyles2,
55379
+ ...itemPaddingStyles2,
55380
+ backgroundColor: hoveredItem === "schematic" ? "#404040" : "transparent"
55381
+ },
55382
+ onSelect: onViewSchematicComponent,
55383
+ onMouseEnter: () => setHoveredItem("schematic"),
55384
+ onMouseLeave: () => setHoveredItem(null),
55385
+ children: "Show on schematic"
55386
+ }
55387
+ ) }),
55388
+ onHideComponent && /* @__PURE__ */ jsx36(
55389
+ Item22,
55390
+ {
55391
+ style: {
55392
+ ...itemStyles2,
55393
+ ...itemPaddingStyles2,
55394
+ backgroundColor: hoveredItem === "hide" ? "#404040" : "transparent"
55395
+ },
55396
+ onSelect: onHideComponent,
55397
+ onMouseEnter: () => setHoveredItem("hide"),
55398
+ onMouseLeave: () => setHoveredItem(null),
55399
+ children: `Hide "${componentName}"`
55400
+ }
55401
+ ),
55402
+ onUnhideAllComponents && /* @__PURE__ */ jsx36(
55403
+ Item22,
55404
+ {
55405
+ style: {
55406
+ ...itemStyles2,
55407
+ ...itemPaddingStyles2,
55408
+ backgroundColor: hoveredItem === "unhide" ? "#404040" : "transparent"
55409
+ },
55410
+ onSelect: onUnhideAllComponents,
55411
+ onMouseEnter: () => setHoveredItem("unhide"),
55412
+ onMouseLeave: () => setHoveredItem(null),
55413
+ children: "Unhide All Components"
55414
+ }
55415
+ ),
55416
+ (onViewSchematicComponent || onHideComponent || onUnhideAllComponents) && /* @__PURE__ */ jsx36(Separator2, { style: separatorStyles2 }),
55264
55417
  /* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setCameraSubOpen, children: [
55265
55418
  /* @__PURE__ */ jsxs8(
55266
55419
  SubTrigger2,
@@ -55603,10 +55756,10 @@ var ContextMenu = ({
55603
55756
  };
55604
55757
 
55605
55758
  // src/components/KeyboardShortcutsDialog.tsx
55606
- import { useEffect as useEffect48, useMemo as useMemo33, useRef as useRef27, useState as useState38 } from "react";
55759
+ import { useEffect as useEffect48, useMemo as useMemo33, useRef as useRef27, useState as useState40 } from "react";
55607
55760
 
55608
55761
  // src/hooks/useRegisteredHotkey.ts
55609
- import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef26, useState as useState37 } from "react";
55762
+ import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef26, useState as useState39 } from "react";
55610
55763
  var hotkeyRegistry = /* @__PURE__ */ new Map();
55611
55764
  var subscribers = /* @__PURE__ */ new Set();
55612
55765
  var isListenerAttached = false;
@@ -55750,7 +55903,7 @@ var useRegisteredHotkey = (id, handler, metadata) => {
55750
55903
  }, [id, normalizedMetadata]);
55751
55904
  };
55752
55905
  var useHotkeyRegistry = () => {
55753
- const [entries, setEntries] = useState37(
55906
+ const [entries, setEntries] = useState39(
55754
55907
  () => Array.from(hotkeyRegistry.values())
55755
55908
  );
55756
55909
  useEffect47(() => subscribeToRegistry(setEntries), []);
@@ -55767,7 +55920,7 @@ var KeyboardShortcutsDialog = ({
55767
55920
  open,
55768
55921
  onClose
55769
55922
  }) => {
55770
- const [query, setQuery] = useState38("");
55923
+ const [query, setQuery] = useState40("");
55771
55924
  const inputRef = useRef27(null);
55772
55925
  const hotkeys = useHotkeyRegistry();
55773
55926
  useEffect48(() => {
@@ -56010,10 +56163,10 @@ function useCameraPreset({
56010
56163
  }
56011
56164
 
56012
56165
  // src/hooks/useContextMenu.ts
56013
- import { useState as useState39, useCallback as useCallback22, useRef as useRef28, useEffect as useEffect49 } from "react";
56166
+ import { useState as useState41, useCallback as useCallback22, useRef as useRef28, useEffect as useEffect49 } from "react";
56014
56167
  var useContextMenu = ({ containerRef, onOpen }) => {
56015
- const [menuVisible, setMenuVisible] = useState39(false);
56016
- const [menuPos, setMenuPos] = useState39({
56168
+ const [menuVisible, setMenuVisible] = useState41(false);
56169
+ const [menuPos, setMenuPos] = useState41({
56017
56170
  x: 0,
56018
56171
  y: 0
56019
56172
  });
@@ -56205,37 +56358,48 @@ var CadViewerInner = (props) => {
56205
56358
  const circuitJson = props.circuitJson ?? childrenCircuitJson;
56206
56359
  const hasBends = circuitJson.some((element) => element.type === "pcb_bend");
56207
56360
  const hasFlexGeometry = hasBends || circuitJson.some((element) => element.type === "pcb_stiffener");
56208
- const [foldPcbsOverride, setFoldPcbs] = useState40(
56361
+ const [foldPcbsOverride, setFoldPcbs] = useState42(
56209
56362
  void 0
56210
56363
  );
56211
56364
  const foldPcbs = foldPcbsOverride ?? props.foldPcbs;
56212
56365
  const resolvedFoldPcbs = resolveFoldPcbs(circuitJson, foldPcbs);
56213
- const resolvedProps = { ...props, circuitJson, children: void 0 };
56214
- const [engine, setEngine] = useState40(() => {
56366
+ const circuitKey = JSON.stringify(circuitJson);
56367
+ const { hiddenCadComponentIds, hideComponent, unhideAllComponents } = useHiddenCadComponents(circuitKey);
56368
+ const resolvedProps = {
56369
+ ...props,
56370
+ circuitJson,
56371
+ children: void 0,
56372
+ hiddenCadComponentIds
56373
+ };
56374
+ const [engine, setEngine] = useState42(() => {
56215
56375
  const stored = window.localStorage.getItem("cadViewerEngine");
56216
56376
  return stored === "jscad" || stored === "manifold" ? stored : "manifold";
56217
56377
  });
56218
56378
  const containerRef = useRef29(null);
56219
- const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState40(false);
56220
- const [autoRotate, setAutoRotate] = useState40(() => {
56379
+ const [isKeyboardShortcutsDialogOpen, setIsKeyboardShortcutsDialogOpen] = useState42(false);
56380
+ const [autoRotate, setAutoRotate] = useState42(() => {
56221
56381
  const stored = window.localStorage.getItem("cadViewerAutoRotate");
56222
56382
  return stored !== "false";
56223
56383
  });
56224
- const [autoRotateUserToggled, setAutoRotateUserToggled] = useState40(() => {
56384
+ const [autoRotateUserToggled, setAutoRotateUserToggled] = useState42(() => {
56225
56385
  const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled");
56226
56386
  return stored === "true";
56227
56387
  });
56228
- const [cameraPreset, setCameraPreset] = useState40("Custom");
56229
- const [referenceObject, setReferenceObject] = useState40(null);
56388
+ const [cameraPreset, setCameraPreset] = useState42("Custom");
56389
+ const [referenceObject, setReferenceObject] = useState42(null);
56230
56390
  const { cameraType } = useCameraController();
56231
56391
  const { visibility, setLayerVisibility } = useLayerVisibility();
56232
56392
  const { showToast } = useToast();
56233
56393
  const cameraControllerRef = useRef29(null);
56234
56394
  const externalCameraControllerReady = props.onCameraControllerReady;
56235
56395
  const sceneRef = useContext10(SchematicNavigationContext);
56236
- const [selectedComponent, setSelectedComponent] = useState40();
56396
+ const [selectedComponent, setSelectedComponent] = useState42();
56397
+ const [selectedCadComponent, setSelectedCadComponent] = useState42();
56237
56398
  const handleMenuOpen = useCallback24(
56238
56399
  (position) => {
56400
+ setSelectedCadComponent(
56401
+ pickCadComponent(sceneRef.current, position, circuitJson)
56402
+ );
56239
56403
  setSelectedComponent(
56240
56404
  props.onViewSchematicComponent ? pickSchematicComponent(sceneRef.current, position, circuitJson) : void 0
56241
56405
  );
@@ -56367,7 +56531,7 @@ var CadViewerInner = (props) => {
56367
56531
  useEffect50(() => {
56368
56532
  window.localStorage.setItem("cadViewerCameraType", cameraType);
56369
56533
  }, [cameraType]);
56370
- const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
56534
+ const viewerKey = props.circuitJson ? circuitKey : void 0;
56371
56535
  return /* @__PURE__ */ jsxs11(
56372
56536
  "div",
56373
56537
  {
@@ -56418,6 +56582,15 @@ var CadViewerInner = (props) => {
56418
56582
  menuVisible && /* @__PURE__ */ jsx39(
56419
56583
  ContextMenu,
56420
56584
  {
56585
+ componentName: selectedCadComponent?.componentName,
56586
+ onHideComponent: selectedCadComponent ? () => {
56587
+ hideComponent(selectedCadComponent.cad_component_id);
56588
+ closeMenu();
56589
+ } : void 0,
56590
+ onUnhideAllComponents: hiddenCadComponentIds.size > 0 ? () => {
56591
+ unhideAllComponents();
56592
+ closeMenu();
56593
+ } : void 0,
56421
56594
  onViewSchematicComponent: selectedComponent && props.onViewSchematicComponent ? () => {
56422
56595
  props.onViewSchematicComponent?.(selectedComponent);
56423
56596
  closeMenu();
@@ -56783,7 +56956,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
56783
56956
 
56784
56957
  // src/hooks/exporter/gltf.ts
56785
56958
  import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
56786
- import { useEffect as useEffect51, useState as useState41, useMemo as useMemo34, useCallback as useCallback25 } from "react";
56959
+ import { useEffect as useEffect51, useState as useState43, useMemo as useMemo34, useCallback as useCallback25 } from "react";
56787
56960
  function useSaveGltfAs(options = {}) {
56788
56961
  const parse2 = useParser(options);
56789
56962
  const link = useMemo34(() => document.createElement("a"), []);
@@ -56811,8 +56984,8 @@ function useSaveGltfAs(options = {}) {
56811
56984
  }
56812
56985
  function useExportGltfUrl(options = {}) {
56813
56986
  const parse2 = useParser(options);
56814
- const [url, setUrl] = useState41();
56815
- const [error, setError] = useState41();
56987
+ const [url, setUrl] = useState43();
56988
+ const [error, setError] = useState43();
56816
56989
  const ref = useCallback25(
56817
56990
  (instance) => parse2(instance).then(setUrl).catch(setError),
56818
56991
  []
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.611",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/tscircuit/3d-viewer"