@tscircuit/pcb-viewer 1.11.313 → 1.11.315

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
@@ -6451,7 +6451,7 @@ var ToastContainer = () => {
6451
6451
  };
6452
6452
 
6453
6453
  // src/PCBViewer.tsx
6454
- import { useEffect as useEffect16, useMemo as useMemo8, useRef as useRef11, useState as useState11 } from "react";
6454
+ import { useEffect as useEffect16, useMemo as useMemo8, useRef as useRef12, useState as useState11 } from "react";
6455
6455
 
6456
6456
  // node_modules/react-use/esm/misc/util.js
6457
6457
  var noop = function() {
@@ -10455,6 +10455,7 @@ var DimensionOverlay = ({
10455
10455
  start: null,
10456
10456
  end: null
10457
10457
  });
10458
+ const isMouseOverContainer = useGlobalStore((s) => s.is_mouse_over_container);
10458
10459
  const disarmMeasure = useCallback3(() => {
10459
10460
  if (measureToolArmed) {
10460
10461
  setMeasureToolArmed(false);
@@ -10572,8 +10573,9 @@ var DimensionOverlay = ({
10572
10573
  [snappingPointsWithScreen, transform]
10573
10574
  );
10574
10575
  useEffect7(() => {
10575
- const container2 = containerRef.current;
10576
10576
  const down = (e) => {
10577
+ const containerHasFocus = containerRef.current?.contains(document.activeElement) || document.activeElement === containerRef.current;
10578
+ if (!isMouseOverContainer && !containerHasFocus) return;
10577
10579
  if (e.key === "d") {
10578
10580
  const snap = findSnap({
10579
10581
  x: mousePosRef.current.x,
@@ -10602,34 +10604,14 @@ var DimensionOverlay = ({
10602
10604
  const armMeasure = () => {
10603
10605
  setMeasureToolArmed(true);
10604
10606
  };
10605
- const addKeyListener = () => {
10606
- if (container2) {
10607
- window.addEventListener("keydown", down);
10608
- }
10609
- };
10610
- const removeKeyListener = () => {
10611
- if (container2) {
10612
- window.removeEventListener("keydown", down);
10613
- }
10614
- };
10607
+ window.addEventListener("keydown", down);
10615
10608
  window.addEventListener("arm-dimension-tool", armMeasure);
10616
- if (container2) {
10617
- container2.addEventListener("focus", addKeyListener);
10618
- container2.addEventListener("blur", removeKeyListener);
10619
- container2.addEventListener("mouseenter", addKeyListener);
10620
- container2.addEventListener("mouseleave", removeKeyListener);
10621
- }
10622
10609
  return () => {
10610
+ window.removeEventListener("keydown", down);
10623
10611
  window.removeEventListener("arm-dimension-tool", armMeasure);
10624
10612
  disarmMeasure();
10625
- if (container2) {
10626
- container2.removeEventListener("focus", addKeyListener);
10627
- container2.removeEventListener("blur", removeKeyListener);
10628
- container2.removeEventListener("mouseenter", addKeyListener);
10629
- container2.removeEventListener("mouseleave", removeKeyListener);
10630
- }
10631
10613
  };
10632
- }, [containerRef, dimensionToolVisible, disarmMeasure, findSnap]);
10614
+ }, [isMouseOverContainer, dimensionToolVisible, disarmMeasure, findSnap]);
10633
10615
  const screenDStart = applyToPoint8(transform, dStart);
10634
10616
  const screenDEnd = applyToPoint8(transform, dEnd);
10635
10617
  const arrowScreenBounds = {
@@ -10656,8 +10638,9 @@ var DimensionOverlay = ({
10656
10638
  "div",
10657
10639
  {
10658
10640
  ref: containerRef,
10641
+ "data-pcb-viewer": true,
10659
10642
  tabIndex: 0,
10660
- style: { position: "relative" },
10643
+ style: { position: "relative", outline: "none" },
10661
10644
  onMouseEnter: () => {
10662
10645
  if (focusOnHover && containerRef.current) {
10663
10646
  containerRef.current.focus();
@@ -10668,6 +10651,11 @@ var DimensionOverlay = ({
10668
10651
  containerRef.current.blur();
10669
10652
  }
10670
10653
  },
10654
+ onClick: () => {
10655
+ if (containerRef.current) {
10656
+ containerRef.current.focus();
10657
+ }
10658
+ },
10671
10659
  onMouseMove: (e) => {
10672
10660
  const rect = e.currentTarget.getBoundingClientRect();
10673
10661
  const x = e.clientX - rect.left;
@@ -13565,13 +13553,19 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
13565
13553
  };
13566
13554
 
13567
13555
  // src/components/ToolbarOverlay.tsx
13568
- import { useEffect as useEffect15, useState as useState9, useCallback as useCallback4, useRef as useRef10 } from "react";
13556
+ import {
13557
+ useEffect as useEffect15,
13558
+ useState as useState9,
13559
+ useCallback as useCallback4,
13560
+ useRef as useRef11,
13561
+ useLayoutEffect as useLayoutEffect2
13562
+ } from "react";
13569
13563
  import { css as css3 } from "@emotion/css";
13570
13564
 
13571
13565
  // package.json
13572
13566
  var package_default = {
13573
13567
  name: "@tscircuit/pcb-viewer",
13574
- version: "1.11.312",
13568
+ version: "1.11.314",
13575
13569
  main: "dist/index.js",
13576
13570
  type: "module",
13577
13571
  repository: "tscircuit/pcb-viewer",
@@ -13624,8 +13618,8 @@ var package_default = {
13624
13618
  "@tscircuit/alphabet": "^0.0.9",
13625
13619
  "@tscircuit/math-utils": "^0.0.29",
13626
13620
  "@vitejs/plugin-react": "^5.0.2",
13627
- "circuit-json": "^0.0.354",
13628
- "circuit-to-canvas": "^0.0.48",
13621
+ "circuit-json": "^0.0.356",
13622
+ "circuit-to-canvas": "^0.0.50",
13629
13623
  "circuit-to-svg": "^0.0.271",
13630
13624
  color: "^4.2.3",
13631
13625
  "react-supergrid": "^1.0.10",
@@ -13636,13 +13630,21 @@ var package_default = {
13636
13630
  };
13637
13631
 
13638
13632
  // src/hooks/useHotKey.ts
13639
- import { useEffect as useEffect13 } from "react";
13640
- var useHotKey = (key, onUse) => {
13633
+ import { useEffect as useEffect13, useRef as useRef10 } from "react";
13634
+ var useHotKey = (key, onUse, containerRef) => {
13641
13635
  const isMouseOverContainer = useGlobalStore(
13642
13636
  (s) => s.is_mouse_over_container
13643
13637
  );
13638
+ const isMouseOverContainerRef = useRef10(isMouseOverContainer);
13639
+ const onUseRef = useRef10(onUse);
13640
+ useEffect13(() => {
13641
+ isMouseOverContainerRef.current = isMouseOverContainer;
13642
+ }, [isMouseOverContainer]);
13643
+ useEffect13(() => {
13644
+ onUseRef.current = onUse;
13645
+ }, [onUse]);
13644
13646
  useEffect13(() => {
13645
- if (!key || typeof onUse !== "function") return;
13647
+ if (!key) return;
13646
13648
  const handleKeyDown = (event) => {
13647
13649
  const keyParts = key.split("+");
13648
13650
  const ctrlRequired = keyParts.includes("ctrl");
@@ -13650,16 +13652,18 @@ var useHotKey = (key, onUse) => {
13650
13652
  const altRequired = keyParts.includes("alt");
13651
13653
  const metaRequired = keyParts.includes("meta");
13652
13654
  const mainKey = keyParts[keyParts.length - 1];
13653
- if (isMouseOverContainer && (!ctrlRequired || event.ctrlKey) && (!shiftRequired || event.shiftKey) && (!altRequired || event.altKey) && (!metaRequired || event.metaKey) && event.key.toLowerCase() === mainKey.toLowerCase()) {
13655
+ const containerHasFocus = containerRef?.current ? containerRef.current.contains(document.activeElement) || document.activeElement === containerRef.current : false;
13656
+ const shouldTrigger = isMouseOverContainerRef.current || containerHasFocus;
13657
+ if (shouldTrigger && (!ctrlRequired || event.ctrlKey) && (!shiftRequired || event.shiftKey) && (!altRequired || event.altKey) && (!metaRequired || event.metaKey) && event.key.toLowerCase() === mainKey.toLowerCase()) {
13654
13658
  event.preventDefault();
13655
- onUse();
13659
+ onUseRef.current();
13656
13660
  }
13657
13661
  };
13658
13662
  window.addEventListener("keydown", handleKeyDown);
13659
13663
  return () => {
13660
13664
  window.removeEventListener("keydown", handleKeyDown);
13661
13665
  };
13662
- }, [key, onUse]);
13666
+ }, [key]);
13663
13667
  };
13664
13668
 
13665
13669
  // src/hooks/useIsSmallScreen.ts
@@ -13879,8 +13883,8 @@ var ToolbarOverlay = ({ children, elements }) => {
13879
13883
  const [isLayerMenuOpen, setLayerMenuOpen] = useState9(false);
13880
13884
  const [isErrorsOpen, setErrorsOpen] = useState9(false);
13881
13885
  const [measureToolArmed, setMeasureToolArmed] = useState9(false);
13882
- const errorElementsRef = useRef10(/* @__PURE__ */ new Map());
13883
- const arrowElementsRef = useRef10(/* @__PURE__ */ new Map());
13886
+ const errorElementsRef = useRef11(/* @__PURE__ */ new Map());
13887
+ const arrowElementsRef = useRef11(/* @__PURE__ */ new Map());
13884
13888
  useEffect15(() => {
13885
13889
  const arm = () => setMeasureToolArmed(true);
13886
13890
  const disarm = () => setMeasureToolArmed(false);
@@ -13901,6 +13905,8 @@ var ToolbarOverlay = ({ children, elements }) => {
13901
13905
  "bottom"
13902
13906
  ];
13903
13907
  const processedLayers = availableLayers;
13908
+ const hasRunInitialMouseCheck = useRef11(false);
13909
+ const hotkeyBoundaryRef = useRef11(null);
13904
13910
  const hotKeyCallbacks = {
13905
13911
  "1": availableLayers[0] ? () => selectLayer(availableLayers[0]) : () => {
13906
13912
  },
@@ -13919,17 +13925,40 @@ var ToolbarOverlay = ({ children, elements }) => {
13919
13925
  "8": availableLayers[7] ? () => selectLayer(availableLayers[7]) : () => {
13920
13926
  }
13921
13927
  };
13922
- useHotKey("1", hotKeyCallbacks["1"]);
13923
- useHotKey("2", hotKeyCallbacks["2"]);
13924
- useHotKey("3", hotKeyCallbacks["3"]);
13925
- useHotKey("4", hotKeyCallbacks["4"]);
13926
- useHotKey("5", hotKeyCallbacks["5"]);
13927
- useHotKey("6", hotKeyCallbacks["6"]);
13928
- useHotKey("7", hotKeyCallbacks["7"]);
13929
- useHotKey("8", hotKeyCallbacks["8"]);
13928
+ useHotKey("1", hotKeyCallbacks["1"], hotkeyBoundaryRef);
13929
+ useHotKey("2", hotKeyCallbacks["2"], hotkeyBoundaryRef);
13930
+ useHotKey("3", hotKeyCallbacks["3"], hotkeyBoundaryRef);
13931
+ useHotKey("4", hotKeyCallbacks["4"], hotkeyBoundaryRef);
13932
+ useHotKey("5", hotKeyCallbacks["5"], hotkeyBoundaryRef);
13933
+ useHotKey("6", hotKeyCallbacks["6"], hotkeyBoundaryRef);
13934
+ useHotKey("7", hotKeyCallbacks["7"], hotkeyBoundaryRef);
13935
+ useHotKey("8", hotKeyCallbacks["8"], hotkeyBoundaryRef);
13936
+ useLayoutEffect2(() => {
13937
+ if (hasRunInitialMouseCheck.current) return;
13938
+ hasRunInitialMouseCheck.current = true;
13939
+ const checkMousePosition = (e) => {
13940
+ if (hotkeyBoundaryRef.current) {
13941
+ const rect = hotkeyBoundaryRef.current.getBoundingClientRect();
13942
+ const isInside = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
13943
+ if (isInside) {
13944
+ setIsMouseOverContainer(true);
13945
+ }
13946
+ }
13947
+ document.removeEventListener("mousemove", checkMousePosition);
13948
+ };
13949
+ document.addEventListener("mousemove", checkMousePosition);
13950
+ return () => {
13951
+ document.removeEventListener("mousemove", checkMousePosition);
13952
+ };
13953
+ }, [setIsMouseOverContainer]);
13930
13954
  const handleMouseEnter = useCallback4(() => {
13931
13955
  setIsMouseOverContainer(true);
13932
13956
  }, [setIsMouseOverContainer]);
13957
+ const handleMouseMove = useCallback4(() => {
13958
+ if (!isMouseOverContainer) {
13959
+ setIsMouseOverContainer(true);
13960
+ }
13961
+ }, [isMouseOverContainer, setIsMouseOverContainer]);
13933
13962
  const handleMouseLeave = useCallback4(() => {
13934
13963
  setIsMouseOverContainer(false);
13935
13964
  setLayerMenuOpen(false);
@@ -13973,9 +14002,11 @@ var ToolbarOverlay = ({ children, elements }) => {
13973
14002
  return /* @__PURE__ */ jsxs14(
13974
14003
  "div",
13975
14004
  {
14005
+ ref: hotkeyBoundaryRef,
13976
14006
  style: { position: "relative", zIndex: "999 !important" },
13977
14007
  onMouseEnter: handleMouseEnter,
13978
14008
  onMouseLeave: handleMouseLeave,
14009
+ onMouseMove: handleMouseMove,
13979
14010
  children: [
13980
14011
  children,
13981
14012
  /* @__PURE__ */ jsxs14(
@@ -14682,8 +14713,8 @@ var PCBViewer = ({
14682
14713
  });
14683
14714
  let [editEvents, setEditEvents] = useState11([]);
14684
14715
  editEvents = editEventsProp ?? editEvents;
14685
- const initialRenderCompleted = useRef11(false);
14686
- const touchStartRef = useRef11(null);
14716
+ const initialRenderCompleted = useRef12(false);
14717
+ const touchStartRef = useRef12(null);
14687
14718
  const circuitJsonKey = useMemo8(
14688
14719
  () => calculateCircuitJsonKey(circuitJson),
14689
14720
  [circuitJson]