@tscircuit/pcb-viewer 1.11.361 → 1.11.362

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
@@ -6788,7 +6788,7 @@ var ToastContainer = () => {
6788
6788
  };
6789
6789
 
6790
6790
  // src/PCBViewer.tsx
6791
- import { useCallback as useCallback10, useEffect as useEffect17, useMemo as useMemo8, useRef as useRef14, useState as useState12 } from "react";
6791
+ import { useCallback as useCallback11, useEffect as useEffect17, useMemo as useMemo9, useRef as useRef14, useState as useState13 } from "react";
6792
6792
 
6793
6793
  // node_modules/react-use/esm/useMountedState.js
6794
6794
  import { useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
@@ -7427,7 +7427,7 @@ function addInteractionMetadataToPrimitives({
7427
7427
  }
7428
7428
 
7429
7429
  // src/components/CanvasElementsRenderer.tsx
7430
- import { useCallback as useCallback9, useMemo as useMemo7, useState as useState11 } from "react";
7430
+ import { useCallback as useCallback10, useMemo as useMemo8, useState as useState12 } from "react";
7431
7431
 
7432
7432
  // src/lib/util/expand-stroke.ts
7433
7433
  function getExpandedStroke(strokeInput, defaultWidth) {
@@ -14361,8 +14361,8 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
14361
14361
  // src/components/ToolbarOverlay.tsx
14362
14362
  import {
14363
14363
  useEffect as useEffect16,
14364
- useState as useState10,
14365
- useCallback as useCallback8,
14364
+ useState as useState11,
14365
+ useCallback as useCallback9,
14366
14366
  useRef as useRef13,
14367
14367
  useLayoutEffect as useLayoutEffect2
14368
14368
  } from "react";
@@ -14371,7 +14371,7 @@ import { css as css3 } from "@emotion/css";
14371
14371
  // package.json
14372
14372
  var package_default = {
14373
14373
  name: "@tscircuit/pcb-viewer",
14374
- version: "1.11.360",
14374
+ version: "1.11.361",
14375
14375
  main: "dist/index.js",
14376
14376
  type: "module",
14377
14377
  repository: "tscircuit/pcb-viewer",
@@ -14525,43 +14525,8 @@ var useMobileTouch = (onClick, options = { stopPropagation: true }) => {
14525
14525
  };
14526
14526
  };
14527
14527
 
14528
- // src/components/ToolbarOverlay.tsx
14529
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
14530
- var LayerButton = ({ name, selected, onClick }) => {
14531
- const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14532
- return /* @__PURE__ */ jsxs14(
14533
- "div",
14534
- {
14535
- className: css3`
14536
- margin-top: 2px;
14537
- padding: 4px;
14538
- padding-left: 8px;
14539
- padding-right: 18px;
14540
- cursor: pointer;
14541
-
14542
- &:hover {
14543
- background-color: rgba(255, 255, 255, 0.1);
14544
- }
14545
- `,
14546
- ...touchHandlers,
14547
- style: touchStyle,
14548
- children: [
14549
- /* @__PURE__ */ jsx20("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
14550
- /* @__PURE__ */ jsx20(
14551
- "span",
14552
- {
14553
- style: {
14554
- marginLeft: 2,
14555
- fontWeight: 500,
14556
- color: LAYER_NAME_TO_COLOR[name.replace(/-/, "")]
14557
- },
14558
- children: name
14559
- }
14560
- )
14561
- ]
14562
- }
14563
- );
14564
- };
14528
+ // src/components/ToolbarButton.tsx
14529
+ import { jsx as jsx20 } from "react/jsx-runtime";
14565
14530
  var ToolbarButton = ({
14566
14531
  children,
14567
14532
  isSmallScreen,
@@ -14595,13 +14560,425 @@ var ToolbarButton = ({
14595
14560
  }
14596
14561
  );
14597
14562
  };
14563
+
14564
+ // src/components/ToolbarErrorDropdown.tsx
14565
+ import { useCallback as useCallback8, useMemo as useMemo7, useState as useState10 } from "react";
14566
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
14567
+ var CopyErrorButton = ({
14568
+ errorId,
14569
+ errorMessage,
14570
+ copiedErrorId,
14571
+ onCopy
14572
+ }) => {
14573
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(
14574
+ () => onCopy(errorMessage, errorId)
14575
+ );
14576
+ return /* @__PURE__ */ jsx21(
14577
+ "button",
14578
+ {
14579
+ type: "button",
14580
+ "aria-label": copiedErrorId === errorId ? "Error message copied" : "Copy error message",
14581
+ style: {
14582
+ position: "absolute",
14583
+ top: 12,
14584
+ right: 16,
14585
+ cursor: "pointer",
14586
+ color: "#888",
14587
+ fontSize: 16,
14588
+ background: "none",
14589
+ border: "none",
14590
+ padding: 0,
14591
+ display: "flex",
14592
+ alignItems: "center",
14593
+ ...touchStyle
14594
+ },
14595
+ ...touchHandlers,
14596
+ children: copiedErrorId === errorId ? /* @__PURE__ */ jsx21("span", { style: { color: "#4caf50", fontSize: 12 }, children: "Copied!" }) : /* @__PURE__ */ jsx21("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx21("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" }) })
14597
+ }
14598
+ );
14599
+ };
14600
+ var ToolbarErrorDropdown = ({
14601
+ elements,
14602
+ isOpen,
14603
+ isSmallScreen,
14604
+ onToggle,
14605
+ setHoveredErrorId
14606
+ }) => {
14607
+ const [copiedErrorId, setCopiedErrorId] = useState10(null);
14608
+ const [collapsedErrorGroups, setCollapsedErrorGroups] = useState10(
14609
+ /* @__PURE__ */ new Set()
14610
+ );
14611
+ const [expandedErrorIds, setExpandedErrorIds] = useState10(
14612
+ /* @__PURE__ */ new Set()
14613
+ );
14614
+ const [, copyToClipboard] = useCopyToClipboard_default();
14615
+ const errorElements = useMemo7(
14616
+ () => elements?.filter(
14617
+ (el) => el.type.includes("error")
14618
+ ) ?? [],
14619
+ [elements]
14620
+ );
14621
+ const errorCount = errorElements.length;
14622
+ const getErrorId = useCallback8(
14623
+ (error, index) => {
14624
+ return error.pcb_trace_error_id || `error_${index}_${error.error_type}_${error.message?.slice(0, 20)}`;
14625
+ },
14626
+ []
14627
+ );
14628
+ const groupedErrorElements = useMemo7(() => {
14629
+ const groups = /* @__PURE__ */ new Map();
14630
+ errorElements.forEach((error, index) => {
14631
+ const errorType = error.error_type || "unknown_error";
14632
+ const existingGroup = groups.get(errorType) || [];
14633
+ existingGroup.push({
14634
+ error,
14635
+ index,
14636
+ errorId: getErrorId(error, index)
14637
+ });
14638
+ groups.set(errorType, existingGroup);
14639
+ });
14640
+ return Array.from(groups.entries()).map(([errorType, errors]) => ({
14641
+ errorType,
14642
+ errors
14643
+ }));
14644
+ }, [errorElements, getErrorId]);
14645
+ const toggleErrorGroup = useCallback8((errorType) => {
14646
+ setCollapsedErrorGroups((prev) => {
14647
+ const next = new Set(prev);
14648
+ if (next.has(errorType)) {
14649
+ next.delete(errorType);
14650
+ } else {
14651
+ next.add(errorType);
14652
+ }
14653
+ return next;
14654
+ });
14655
+ }, []);
14656
+ const toggleExpandedError = useCallback8((errorId) => {
14657
+ setExpandedErrorIds((prev) => {
14658
+ const next = new Set(prev);
14659
+ if (next.has(errorId)) {
14660
+ next.delete(errorId);
14661
+ } else {
14662
+ next.add(errorId);
14663
+ }
14664
+ return next;
14665
+ });
14666
+ }, []);
14667
+ return /* @__PURE__ */ jsxs14("div", { style: { position: "relative" }, children: [
14668
+ /* @__PURE__ */ jsx21(
14669
+ ToolbarButton,
14670
+ {
14671
+ isSmallScreen,
14672
+ style: errorCount > 0 ? { color: "red" } : void 0,
14673
+ onClick: onToggle,
14674
+ children: /* @__PURE__ */ jsxs14("div", { children: [
14675
+ errorCount,
14676
+ " errors"
14677
+ ] })
14678
+ }
14679
+ ),
14680
+ isOpen && errorCount > 0 && /* @__PURE__ */ jsx21(
14681
+ "div",
14682
+ {
14683
+ style: {
14684
+ position: "absolute",
14685
+ top: "100%",
14686
+ left: 0,
14687
+ backgroundColor: "#2a2a2a",
14688
+ border: "1px solid #666",
14689
+ borderRadius: 4,
14690
+ marginTop: 4,
14691
+ zIndex: 1e3,
14692
+ minWidth: isSmallScreen ? "280px" : "400px",
14693
+ maxWidth: isSmallScreen ? "90vw" : "600px",
14694
+ maxHeight: "400px",
14695
+ overflow: "auto",
14696
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.3)"
14697
+ },
14698
+ children: groupedErrorElements.map(({ errorType, errors }, groupIndex) => {
14699
+ const isGroupCollapsed = collapsedErrorGroups.has(errorType);
14700
+ return /* @__PURE__ */ jsxs14(
14701
+ "div",
14702
+ {
14703
+ style: {
14704
+ borderBottom: groupIndex < groupedErrorElements.length - 1 ? "1px solid #444" : "none"
14705
+ },
14706
+ children: [
14707
+ /* @__PURE__ */ jsxs14(
14708
+ "div",
14709
+ {
14710
+ style: {
14711
+ display: "flex",
14712
+ alignItems: "center",
14713
+ justifyContent: "space-between",
14714
+ padding: "12px 16px",
14715
+ cursor: "pointer",
14716
+ backgroundColor: "#232323",
14717
+ transition: "background-color 0.2s ease",
14718
+ touchAction: "manipulation",
14719
+ position: "sticky",
14720
+ top: 0,
14721
+ zIndex: 1
14722
+ },
14723
+ onMouseEnter: (e) => {
14724
+ e.currentTarget.style.backgroundColor = "#303030";
14725
+ },
14726
+ onMouseLeave: (e) => {
14727
+ e.currentTarget.style.backgroundColor = "#232323";
14728
+ },
14729
+ onTouchStart: (e) => {
14730
+ e.stopPropagation();
14731
+ e.currentTarget.style.backgroundColor = "#303030";
14732
+ },
14733
+ onTouchEnd: (e) => {
14734
+ e.stopPropagation();
14735
+ e.preventDefault();
14736
+ e.currentTarget.style.backgroundColor = "#232323";
14737
+ toggleErrorGroup(errorType);
14738
+ },
14739
+ onClick: (e) => {
14740
+ e.stopPropagation();
14741
+ toggleErrorGroup(errorType);
14742
+ },
14743
+ children: [
14744
+ /* @__PURE__ */ jsxs14(
14745
+ "div",
14746
+ {
14747
+ style: {
14748
+ display: "flex",
14749
+ alignItems: "center",
14750
+ gap: 8,
14751
+ color: "#ff6b6b"
14752
+ },
14753
+ children: [
14754
+ /* @__PURE__ */ jsx21(
14755
+ "div",
14756
+ {
14757
+ style: {
14758
+ color: "#888",
14759
+ fontSize: "16px",
14760
+ transform: isGroupCollapsed ? "rotate(90deg)" : "rotate(0deg)",
14761
+ transition: "transform 0.2s ease",
14762
+ flexShrink: 0
14763
+ },
14764
+ children: "\u203A"
14765
+ }
14766
+ ),
14767
+ /* @__PURE__ */ jsx21(
14768
+ "div",
14769
+ {
14770
+ style: {
14771
+ fontWeight: "bold",
14772
+ fontSize: isSmallScreen ? "12px" : "13px"
14773
+ },
14774
+ children: errorType
14775
+ }
14776
+ )
14777
+ ]
14778
+ }
14779
+ ),
14780
+ /* @__PURE__ */ jsx21(
14781
+ "div",
14782
+ {
14783
+ style: {
14784
+ fontSize: isSmallScreen ? "12px" : "13px",
14785
+ color: "#aaa",
14786
+ whiteSpace: "nowrap",
14787
+ marginLeft: 12
14788
+ },
14789
+ children: errors.length
14790
+ }
14791
+ )
14792
+ ]
14793
+ }
14794
+ ),
14795
+ !isGroupCollapsed && errors.map(({ error, index, errorId }) => {
14796
+ const isExpanded = expandedErrorIds.has(errorId);
14797
+ const errorMessage = error.message ?? "No error message";
14798
+ return /* @__PURE__ */ jsxs14(
14799
+ "div",
14800
+ {
14801
+ style: {
14802
+ borderTop: "1px solid #3a3a3a"
14803
+ },
14804
+ children: [
14805
+ /* @__PURE__ */ jsxs14(
14806
+ "div",
14807
+ {
14808
+ style: {
14809
+ display: "flex",
14810
+ alignItems: "center",
14811
+ gap: 12,
14812
+ padding: "12px 16px 12px 24px",
14813
+ cursor: "pointer",
14814
+ backgroundColor: "#2a2a2a",
14815
+ transition: "background-color 0.2s ease",
14816
+ touchAction: "manipulation"
14817
+ },
14818
+ onMouseEnter: (e) => {
14819
+ e.currentTarget.style.backgroundColor = "#333";
14820
+ setHoveredErrorId(errorId);
14821
+ },
14822
+ onMouseLeave: (e) => {
14823
+ e.currentTarget.style.backgroundColor = "#2a2a2a";
14824
+ setHoveredErrorId(null);
14825
+ },
14826
+ onTouchStart: (e) => {
14827
+ e.stopPropagation();
14828
+ e.currentTarget.style.backgroundColor = "#333";
14829
+ setHoveredErrorId(errorId);
14830
+ },
14831
+ onTouchEnd: (e) => {
14832
+ e.stopPropagation();
14833
+ e.preventDefault();
14834
+ e.currentTarget.style.backgroundColor = "#2a2a2a";
14835
+ setHoveredErrorId(null);
14836
+ toggleExpandedError(errorId);
14837
+ },
14838
+ onClick: (e) => {
14839
+ e.stopPropagation();
14840
+ toggleExpandedError(errorId);
14841
+ },
14842
+ children: [
14843
+ /* @__PURE__ */ jsx21(
14844
+ "div",
14845
+ {
14846
+ style: {
14847
+ flex: 1,
14848
+ fontSize: isSmallScreen ? "12px" : "13px",
14849
+ color: "#ddd",
14850
+ lineHeight: 1.4,
14851
+ overflow: "hidden",
14852
+ textOverflow: "ellipsis",
14853
+ whiteSpace: "nowrap",
14854
+ userSelect: "text"
14855
+ },
14856
+ onMouseDown: (event) => event.stopPropagation(),
14857
+ onClick: (event) => event.stopPropagation(),
14858
+ children: errorMessage
14859
+ }
14860
+ ),
14861
+ /* @__PURE__ */ jsx21(
14862
+ "div",
14863
+ {
14864
+ style: {
14865
+ color: "#888",
14866
+ fontSize: "16px",
14867
+ transform: isExpanded ? "rotate(0deg)" : "rotate(90deg)",
14868
+ transition: "transform 0.2s ease",
14869
+ flexShrink: 0
14870
+ },
14871
+ children: "\u203A"
14872
+ }
14873
+ )
14874
+ ]
14875
+ }
14876
+ ),
14877
+ isExpanded && /* @__PURE__ */ jsxs14(
14878
+ "div",
14879
+ {
14880
+ "data-error-id": index,
14881
+ style: {
14882
+ display: "block",
14883
+ padding: "12px 16px 12px 24px",
14884
+ backgroundColor: "#1a1a1a",
14885
+ borderTop: "1px solid #444",
14886
+ position: "relative"
14887
+ },
14888
+ children: [
14889
+ /* @__PURE__ */ jsx21(
14890
+ "div",
14891
+ {
14892
+ style: {
14893
+ fontSize: isSmallScreen ? "11px" : "12px",
14894
+ color: "#ccc",
14895
+ lineHeight: 1.5,
14896
+ wordWrap: "break-word",
14897
+ overflowWrap: "break-word",
14898
+ hyphens: "auto",
14899
+ userSelect: "text",
14900
+ paddingRight: 30
14901
+ },
14902
+ onMouseDown: (event) => event.stopPropagation(),
14903
+ onClick: (event) => event.stopPropagation(),
14904
+ children: errorMessage
14905
+ }
14906
+ ),
14907
+ /* @__PURE__ */ jsx21(
14908
+ CopyErrorButton,
14909
+ {
14910
+ errorId,
14911
+ errorMessage,
14912
+ copiedErrorId,
14913
+ onCopy: (message, id) => {
14914
+ copyToClipboard(message);
14915
+ setCopiedErrorId(id);
14916
+ setTimeout(() => setCopiedErrorId(null), 2e3);
14917
+ }
14918
+ }
14919
+ )
14920
+ ]
14921
+ }
14922
+ )
14923
+ ]
14924
+ },
14925
+ errorId
14926
+ );
14927
+ })
14928
+ ]
14929
+ },
14930
+ errorType
14931
+ );
14932
+ })
14933
+ }
14934
+ )
14935
+ ] });
14936
+ };
14937
+
14938
+ // src/components/ToolbarOverlay.tsx
14939
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
14940
+ var LayerButton = ({ name, selected, onClick }) => {
14941
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14942
+ return /* @__PURE__ */ jsxs15(
14943
+ "div",
14944
+ {
14945
+ className: css3`
14946
+ margin-top: 2px;
14947
+ padding: 4px;
14948
+ padding-left: 8px;
14949
+ padding-right: 18px;
14950
+ cursor: pointer;
14951
+
14952
+ &:hover {
14953
+ background-color: rgba(255, 255, 255, 0.1);
14954
+ }
14955
+ `,
14956
+ ...touchHandlers,
14957
+ style: touchStyle,
14958
+ children: [
14959
+ /* @__PURE__ */ jsx22("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
14960
+ /* @__PURE__ */ jsx22(
14961
+ "span",
14962
+ {
14963
+ style: {
14964
+ marginLeft: 2,
14965
+ fontWeight: 500,
14966
+ color: LAYER_NAME_TO_COLOR[name.replace(/-/, "")]
14967
+ },
14968
+ children: name
14969
+ }
14970
+ )
14971
+ ]
14972
+ }
14973
+ );
14974
+ };
14598
14975
  var CheckboxMenuItem = ({
14599
14976
  label,
14600
14977
  checked,
14601
14978
  onClick
14602
14979
  }) => {
14603
14980
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14604
- return /* @__PURE__ */ jsxs14(
14981
+ return /* @__PURE__ */ jsxs15(
14605
14982
  "div",
14606
14983
  {
14607
14984
  className: css3`
@@ -14621,16 +14998,16 @@ var CheckboxMenuItem = ({
14621
14998
  ...touchHandlers,
14622
14999
  style: touchStyle,
14623
15000
  children: [
14624
- /* @__PURE__ */ jsx20("input", { type: "checkbox", checked, onChange: () => {
15001
+ /* @__PURE__ */ jsx22("input", { type: "checkbox", checked, onChange: () => {
14625
15002
  }, readOnly: true }),
14626
- /* @__PURE__ */ jsx20("span", { style: { color: "#eee" }, children: label })
15003
+ /* @__PURE__ */ jsx22("span", { style: { color: "#eee" }, children: label })
14627
15004
  ]
14628
15005
  }
14629
15006
  );
14630
15007
  };
14631
15008
  var RadioMenuItem = ({ label, checked, onClick }) => {
14632
15009
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14633
- return /* @__PURE__ */ jsxs14(
15010
+ return /* @__PURE__ */ jsxs15(
14634
15011
  "div",
14635
15012
  {
14636
15013
  className: css3`
@@ -14650,46 +15027,13 @@ var RadioMenuItem = ({ label, checked, onClick }) => {
14650
15027
  ...touchHandlers,
14651
15028
  style: touchStyle,
14652
15029
  children: [
14653
- /* @__PURE__ */ jsx20("input", { type: "radio", checked, onChange: () => {
15030
+ /* @__PURE__ */ jsx22("input", { type: "radio", checked, onChange: () => {
14654
15031
  }, readOnly: true }),
14655
- /* @__PURE__ */ jsx20("span", { style: { color: "#eee" }, children: label })
15032
+ /* @__PURE__ */ jsx22("span", { style: { color: "#eee" }, children: label })
14656
15033
  ]
14657
15034
  }
14658
15035
  );
14659
15036
  };
14660
- var CopyErrorButton = ({
14661
- errorId,
14662
- errorMessage,
14663
- copiedErrorId,
14664
- onCopy
14665
- }) => {
14666
- const { style: touchStyle, ...touchHandlers } = useMobileTouch(
14667
- () => onCopy(errorMessage, errorId)
14668
- );
14669
- return /* @__PURE__ */ jsx20(
14670
- "button",
14671
- {
14672
- type: "button",
14673
- "aria-label": copiedErrorId === errorId ? "Error message copied" : "Copy error message",
14674
- style: {
14675
- position: "absolute",
14676
- top: 12,
14677
- right: 16,
14678
- cursor: "pointer",
14679
- color: "#888",
14680
- fontSize: 16,
14681
- background: "none",
14682
- border: "none",
14683
- padding: 0,
14684
- display: "flex",
14685
- alignItems: "center",
14686
- ...touchStyle
14687
- },
14688
- ...touchHandlers,
14689
- children: copiedErrorId === errorId ? /* @__PURE__ */ jsx20("span", { style: { color: "#4caf50", fontSize: 12 }, children: "Copied!" }) : /* @__PURE__ */ jsx20("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx20("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" }) })
14690
- }
14691
- );
14692
- };
14693
15037
  var ToolbarOverlay = ({ children, elements }) => {
14694
15038
  const isSmallScreen = useIsSmallScreen();
14695
15039
  const {
@@ -14751,14 +15095,10 @@ var ToolbarOverlay = ({ children, elements }) => {
14751
15095
  setPcbGroupViewMode: s.setPcbGroupViewMode,
14752
15096
  setHoveredErrorId: s.setHoveredErrorId
14753
15097
  }));
14754
- const [isViewMenuOpen, setViewMenuOpen] = useState10(false);
14755
- const [isLayerMenuOpen, setLayerMenuOpen] = useState10(false);
14756
- const [isErrorsOpen, setErrorsOpen] = useState10(false);
14757
- const [measureToolArmed, setMeasureToolArmed] = useState10(false);
14758
- const [copiedErrorId, setCopiedErrorId] = useState10(null);
14759
- const [, copyToClipboard] = useCopyToClipboard_default();
14760
- const errorElementsRef = useRef13(/* @__PURE__ */ new Map());
14761
- const arrowElementsRef = useRef13(/* @__PURE__ */ new Map());
15098
+ const [isViewMenuOpen, setViewMenuOpen] = useState11(false);
15099
+ const [isLayerMenuOpen, setLayerMenuOpen] = useState11(false);
15100
+ const [isErrorsOpen, setErrorsOpen] = useState11(false);
15101
+ const [measureToolArmed, setMeasureToolArmed] = useState11(false);
14762
15102
  useEffect16(() => {
14763
15103
  const arm = () => setMeasureToolArmed(true);
14764
15104
  const disarm = () => setMeasureToolArmed(false);
@@ -14769,8 +15109,6 @@ var ToolbarOverlay = ({ children, elements }) => {
14769
15109
  window.removeEventListener("disarm-dimension-tool", disarm);
14770
15110
  };
14771
15111
  }, []);
14772
- const errorCount = elements?.filter((e) => e.type.includes("error")).length ?? 0;
14773
- const errorElements = elements?.filter((el) => el.type.includes("error")) || [];
14774
15112
  const pcbBoard = elements?.find((el) => el.type === "pcb_board");
14775
15113
  const numLayers = pcbBoard?.num_layers || 2;
14776
15114
  const availableLayers = numLayers <= 2 ? ["top", "bottom"] : [
@@ -14825,25 +15163,25 @@ var ToolbarOverlay = ({ children, elements }) => {
14825
15163
  document.removeEventListener("mousemove", checkMousePosition);
14826
15164
  };
14827
15165
  }, [setIsMouseOverContainer]);
14828
- const handleMouseEnter = useCallback8(() => {
15166
+ const handleMouseEnter = useCallback9(() => {
14829
15167
  setIsMouseOverContainer(true);
14830
15168
  }, [setIsMouseOverContainer]);
14831
- const handleMouseMove = useCallback8(() => {
15169
+ const handleMouseMove = useCallback9(() => {
14832
15170
  if (!isMouseOverContainer) {
14833
15171
  setIsMouseOverContainer(true);
14834
15172
  }
14835
15173
  }, [isMouseOverContainer, setIsMouseOverContainer]);
14836
- const handleMouseLeave = useCallback8(() => {
15174
+ const handleMouseLeave = useCallback9(() => {
14837
15175
  setIsMouseOverContainer(false);
14838
15176
  setLayerMenuOpen(false);
14839
15177
  setViewMenuOpen(false);
14840
15178
  setErrorsOpen(false);
14841
15179
  setHoveredErrorId(null);
14842
15180
  }, [setIsMouseOverContainer, setHoveredErrorId]);
14843
- const handleLayerMenuToggle = useCallback8(() => {
15181
+ const handleLayerMenuToggle = useCallback9(() => {
14844
15182
  setLayerMenuOpen(!isLayerMenuOpen);
14845
15183
  }, [isLayerMenuOpen]);
14846
- const handleErrorsToggle = useCallback8(() => {
15184
+ const handleErrorsToggle = useCallback9(() => {
14847
15185
  const newErrorsOpen = !isErrorsOpen;
14848
15186
  setErrorsOpen(newErrorsOpen);
14849
15187
  if (newErrorsOpen) {
@@ -14853,33 +15191,33 @@ var ToolbarOverlay = ({ children, elements }) => {
14853
15191
  setHoveredErrorId(null);
14854
15192
  }
14855
15193
  }, [isErrorsOpen, setHoveredErrorId]);
14856
- const handleEditTraceToggle = useCallback8(() => {
15194
+ const handleEditTraceToggle = useCallback9(() => {
14857
15195
  setEditMode(editModes.in_draw_trace_mode ? "off" : "draw_trace");
14858
15196
  }, [editModes.in_draw_trace_mode, setEditMode]);
14859
- const handleMoveComponentToggle = useCallback8(() => {
15197
+ const handleMoveComponentToggle = useCallback9(() => {
14860
15198
  setEditMode(editModes.in_move_footprint_mode ? "off" : "move_footprint");
14861
15199
  }, [editModes.in_move_footprint_mode, setEditMode]);
14862
- const handleRatsNestToggle = useCallback8(() => {
15200
+ const handleRatsNestToggle = useCallback9(() => {
14863
15201
  setIsShowingRatsNest(!viewSettings.is_showing_rats_nest);
14864
15202
  }, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest]);
14865
- const handleMeasureToolClick = useCallback8(() => {
15203
+ const handleMeasureToolClick = useCallback9(() => {
14866
15204
  setMeasureToolArmed(true);
14867
15205
  window.dispatchEvent(new Event("arm-dimension-tool"));
14868
15206
  }, []);
14869
- const handleViewMenuToggle = useCallback8(() => {
15207
+ const handleViewMenuToggle = useCallback9(() => {
14870
15208
  const newViewMenuOpen = !isViewMenuOpen;
14871
15209
  setViewMenuOpen(newViewMenuOpen);
14872
15210
  if (newViewMenuOpen) {
14873
15211
  setErrorsOpen(false);
14874
15212
  }
14875
15213
  }, [isViewMenuOpen]);
14876
- const stopCanvasInteractionPropagation = useCallback8(
15214
+ const stopCanvasInteractionPropagation = useCallback9(
14877
15215
  (event) => {
14878
15216
  event.stopPropagation();
14879
15217
  },
14880
15218
  []
14881
15219
  );
14882
- return /* @__PURE__ */ jsxs14(
15220
+ return /* @__PURE__ */ jsxs15(
14883
15221
  "div",
14884
15222
  {
14885
15223
  ref: hotkeyBoundaryRef,
@@ -14889,7 +15227,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14889
15227
  onMouseMove: handleMouseMove,
14890
15228
  children: [
14891
15229
  children,
14892
- /* @__PURE__ */ jsxs14(
15230
+ /* @__PURE__ */ jsxs15(
14893
15231
  "div",
14894
15232
  {
14895
15233
  style: {
@@ -14910,7 +15248,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14910
15248
  ]
14911
15249
  }
14912
15250
  ),
14913
- /* @__PURE__ */ jsxs14(
15251
+ /* @__PURE__ */ jsxs15(
14914
15252
  "div",
14915
15253
  {
14916
15254
  "data-toolbar-overlay": true,
@@ -14940,7 +15278,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14940
15278
  fontFamily: "sans-serif"
14941
15279
  },
14942
15280
  children: [
14943
- /* @__PURE__ */ jsxs14(
15281
+ /* @__PURE__ */ jsxs15(
14944
15282
  ToolbarButton,
14945
15283
  {
14946
15284
  isSmallScreen,
@@ -14951,10 +15289,10 @@ var ToolbarOverlay = ({ children, elements }) => {
14951
15289
  }
14952
15290
  },
14953
15291
  children: [
14954
- /* @__PURE__ */ jsxs14("div", { children: [
15292
+ /* @__PURE__ */ jsxs15("div", { children: [
14955
15293
  "layer:",
14956
15294
  " ",
14957
- /* @__PURE__ */ jsx20(
15295
+ /* @__PURE__ */ jsx22(
14958
15296
  "span",
14959
15297
  {
14960
15298
  style: {
@@ -14966,7 +15304,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14966
15304
  }
14967
15305
  )
14968
15306
  ] }),
14969
- isLayerMenuOpen && /* @__PURE__ */ jsx20("div", { style: { marginTop: 4, minWidth: 120 }, children: processedLayers.map((layer) => /* @__PURE__ */ jsx20(
15307
+ isLayerMenuOpen && /* @__PURE__ */ jsx22("div", { style: { marginTop: 4, minWidth: 120 }, children: processedLayers.map((layer) => /* @__PURE__ */ jsx22(
14970
15308
  LayerButton,
14971
15309
  {
14972
15310
  name: layer,
@@ -14980,259 +15318,68 @@ var ToolbarOverlay = ({ children, elements }) => {
14980
15318
  ]
14981
15319
  }
14982
15320
  ),
14983
- /* @__PURE__ */ jsx20(
14984
- ToolbarButton,
15321
+ /* @__PURE__ */ jsx22(
15322
+ ToolbarErrorDropdown,
14985
15323
  {
15324
+ elements,
15325
+ isOpen: isErrorsOpen,
14986
15326
  isSmallScreen,
14987
- style: {
14988
- position: "relative",
14989
- ...errorCount > 0 ? { color: "red" } : {}
14990
- },
14991
- onClick: handleErrorsToggle,
14992
- children: /* @__PURE__ */ jsxs14("div", { children: [
14993
- errorCount,
14994
- " errors"
14995
- ] })
15327
+ onToggle: handleErrorsToggle,
15328
+ setHoveredErrorId
14996
15329
  }
14997
15330
  ),
14998
- isErrorsOpen && errorCount > 0 && /* @__PURE__ */ jsx20(
14999
- "div",
15000
- {
15001
- style: {
15002
- position: "absolute",
15003
- top: "100%",
15004
- left: 0,
15005
- backgroundColor: "#2a2a2a",
15006
- border: "1px solid #666",
15007
- borderRadius: 4,
15008
- marginTop: 4,
15009
- zIndex: 1e3,
15010
- minWidth: isSmallScreen ? "280px" : "400px",
15011
- maxWidth: isSmallScreen ? "90vw" : "600px",
15012
- maxHeight: "400px",
15013
- overflow: "auto",
15014
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.3)"
15015
- },
15016
- children: errorElements.map((e, i) => {
15017
- const errorId = e.pcb_trace_error_id || `error_${i}_${e.error_type}_${e.message?.slice(0, 20)}`;
15018
- return /* @__PURE__ */ jsxs14(
15019
- "div",
15020
- {
15021
- style: {
15022
- borderBottom: i < errorElements.length - 1 ? "1px solid #444" : "none"
15023
- },
15024
- children: [
15025
- /* @__PURE__ */ jsxs14(
15026
- "div",
15027
- {
15028
- style: {
15029
- display: "flex",
15030
- alignItems: "center",
15031
- gap: 12,
15032
- padding: "12px 16px",
15033
- cursor: "pointer",
15034
- backgroundColor: "#2a2a2a",
15035
- transition: "background-color 0.2s ease",
15036
- touchAction: "manipulation"
15037
- },
15038
- onMouseEnter: (e2) => {
15039
- e2.currentTarget.style.backgroundColor = "#333";
15040
- setHoveredErrorId(errorId);
15041
- },
15042
- onMouseLeave: (e2) => {
15043
- e2.currentTarget.style.backgroundColor = "#2a2a2a";
15044
- setHoveredErrorId(null);
15045
- },
15046
- onTouchStart: (e2) => {
15047
- e2.stopPropagation();
15048
- e2.currentTarget.style.backgroundColor = "#333";
15049
- setHoveredErrorId(errorId);
15050
- },
15051
- onTouchEnd: (e2) => {
15052
- e2.stopPropagation();
15053
- e2.preventDefault();
15054
- e2.currentTarget.style.backgroundColor = "#2a2a2a";
15055
- setHoveredErrorId(null);
15056
- const errorElement = errorElementsRef.current.get(i);
15057
- const arrow = arrowElementsRef.current.get(i);
15058
- if (errorElement && arrow) {
15059
- const isVisible = errorElement.style.display !== "none";
15060
- errorElement.style.display = isVisible ? "none" : "block";
15061
- arrow.style.transform = isVisible ? "rotate(90deg)" : "rotate(0deg)";
15062
- }
15063
- },
15064
- onClick: (e2) => {
15065
- e2.stopPropagation();
15066
- const errorElement = errorElementsRef.current.get(i);
15067
- const arrow = arrowElementsRef.current.get(i);
15068
- if (errorElement && arrow) {
15069
- const isVisible = errorElement.style.display !== "none";
15070
- errorElement.style.display = isVisible ? "none" : "block";
15071
- arrow.style.transform = isVisible ? "rotate(90deg)" : "rotate(0deg)";
15072
- }
15073
- },
15074
- children: [
15075
- /* @__PURE__ */ jsx20(
15076
- "div",
15077
- {
15078
- style: {
15079
- fontWeight: "bold",
15080
- fontSize: isSmallScreen ? "12px" : "13px",
15081
- whiteSpace: "nowrap",
15082
- flexShrink: 0,
15083
- color: "#ff6b6b",
15084
- display: isSmallScreen ? "none" : "block"
15085
- },
15086
- children: e.error_type
15087
- }
15088
- ),
15089
- /* @__PURE__ */ jsx20(
15090
- "div",
15091
- {
15092
- style: {
15093
- flex: 1,
15094
- fontSize: isSmallScreen ? "12px" : "13px",
15095
- color: "#ddd",
15096
- lineHeight: 1.4,
15097
- overflow: "hidden",
15098
- textOverflow: "ellipsis",
15099
- whiteSpace: "nowrap",
15100
- userSelect: "text"
15101
- },
15102
- onMouseDown: (event) => event.stopPropagation(),
15103
- onClick: (event) => event.stopPropagation(),
15104
- children: e.message
15105
- }
15106
- ),
15107
- /* @__PURE__ */ jsx20(
15108
- "div",
15109
- {
15110
- ref: (el) => {
15111
- if (el) arrowElementsRef.current.set(i, el);
15112
- },
15113
- "data-arrow-id": i,
15114
- style: {
15115
- color: "#888",
15116
- fontSize: "16px",
15117
- transform: "rotate(90deg)",
15118
- transition: "transform 0.2s ease",
15119
- flexShrink: 0
15120
- },
15121
- children: "\u203A"
15122
- }
15123
- )
15124
- ]
15125
- }
15126
- ),
15127
- /* @__PURE__ */ jsxs14(
15128
- "div",
15129
- {
15130
- ref: (el) => {
15131
- if (el) errorElementsRef.current.set(i, el);
15132
- },
15133
- "data-error-id": i,
15134
- style: {
15135
- display: "none",
15136
- padding: "12px 16px",
15137
- backgroundColor: "#1a1a1a",
15138
- borderTop: "1px solid #444",
15139
- position: "relative"
15140
- },
15141
- children: [
15142
- /* @__PURE__ */ jsx20(
15143
- "div",
15144
- {
15145
- style: {
15146
- fontSize: isSmallScreen ? "11px" : "12px",
15147
- color: "#ccc",
15148
- lineHeight: 1.5,
15149
- wordWrap: "break-word",
15150
- overflowWrap: "break-word",
15151
- hyphens: "auto",
15152
- userSelect: "text",
15153
- paddingRight: 30
15154
- // Space for the copy icon
15155
- },
15156
- onMouseDown: (event) => event.stopPropagation(),
15157
- onClick: (event) => event.stopPropagation(),
15158
- children: e.message
15159
- }
15160
- ),
15161
- /* @__PURE__ */ jsx20(
15162
- CopyErrorButton,
15163
- {
15164
- errorId,
15165
- errorMessage: e.message,
15166
- copiedErrorId,
15167
- onCopy: (msg, id) => {
15168
- copyToClipboard(msg);
15169
- setCopiedErrorId(id);
15170
- setTimeout(() => setCopiedErrorId(null), 2e3);
15171
- }
15172
- }
15173
- )
15174
- ]
15175
- }
15176
- )
15177
- ]
15178
- },
15179
- errorId
15180
- );
15181
- })
15182
- }
15183
- ),
15184
- /* @__PURE__ */ jsx20(
15331
+ /* @__PURE__ */ jsx22(
15185
15332
  ToolbarButton,
15186
15333
  {
15187
15334
  isSmallScreen,
15188
15335
  style: {},
15189
15336
  onClick: handleEditTraceToggle,
15190
- children: /* @__PURE__ */ jsxs14("div", { children: [
15337
+ children: /* @__PURE__ */ jsxs15("div", { children: [
15191
15338
  editModes.in_draw_trace_mode ? "\u2716 " : "",
15192
15339
  "Edit Traces"
15193
15340
  ] })
15194
15341
  }
15195
15342
  ),
15196
- /* @__PURE__ */ jsx20(
15343
+ /* @__PURE__ */ jsx22(
15197
15344
  ToolbarButton,
15198
15345
  {
15199
15346
  isSmallScreen,
15200
15347
  style: {},
15201
15348
  onClick: handleMoveComponentToggle,
15202
- children: /* @__PURE__ */ jsxs14("div", { children: [
15349
+ children: /* @__PURE__ */ jsxs15("div", { children: [
15203
15350
  editModes.in_move_footprint_mode ? "\u2716 " : "",
15204
15351
  "Move Components"
15205
15352
  ] })
15206
15353
  }
15207
15354
  ),
15208
- /* @__PURE__ */ jsx20(
15355
+ /* @__PURE__ */ jsx22(
15209
15356
  ToolbarButton,
15210
15357
  {
15211
15358
  isSmallScreen,
15212
15359
  style: {},
15213
15360
  onClick: handleRatsNestToggle,
15214
- children: /* @__PURE__ */ jsxs14("div", { children: [
15361
+ children: /* @__PURE__ */ jsxs15("div", { children: [
15215
15362
  viewSettings.is_showing_rats_nest ? "\u2716 " : "",
15216
15363
  "Rats Nest"
15217
15364
  ] })
15218
15365
  }
15219
15366
  ),
15220
- /* @__PURE__ */ jsx20(
15367
+ /* @__PURE__ */ jsx22(
15221
15368
  ToolbarButton,
15222
15369
  {
15223
15370
  isSmallScreen,
15224
15371
  style: measureToolArmed ? { backgroundColor: "#444" } : {},
15225
15372
  onClick: handleMeasureToolClick,
15226
- children: /* @__PURE__ */ jsx20("div", { children: "\u{1F4CF}" })
15373
+ children: /* @__PURE__ */ jsx22("div", { children: "\u{1F4CF}" })
15227
15374
  }
15228
15375
  ),
15229
- /* @__PURE__ */ jsx20(
15376
+ /* @__PURE__ */ jsx22(
15230
15377
  ToolbarButton,
15231
15378
  {
15232
15379
  isSmallScreen,
15233
15380
  onClick: handleViewMenuToggle,
15234
- children: /* @__PURE__ */ jsxs14("div", { children: [
15235
- /* @__PURE__ */ jsxs14(
15381
+ children: /* @__PURE__ */ jsxs15("div", { children: [
15382
+ /* @__PURE__ */ jsxs15(
15236
15383
  "div",
15237
15384
  {
15238
15385
  style: {
@@ -15242,7 +15389,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15242
15389
  },
15243
15390
  children: [
15244
15391
  "View",
15245
- /* @__PURE__ */ jsx20(
15392
+ /* @__PURE__ */ jsx22(
15246
15393
  "span",
15247
15394
  {
15248
15395
  style: {
@@ -15257,8 +15404,8 @@ var ToolbarOverlay = ({ children, elements }) => {
15257
15404
  ]
15258
15405
  }
15259
15406
  ),
15260
- isViewMenuOpen && /* @__PURE__ */ jsxs14("div", { style: { marginTop: 4, minWidth: 120 }, children: [
15261
- /* @__PURE__ */ jsx20(
15407
+ isViewMenuOpen && /* @__PURE__ */ jsxs15("div", { style: { marginTop: 4, minWidth: 120 }, children: [
15408
+ /* @__PURE__ */ jsx22(
15262
15409
  CheckboxMenuItem,
15263
15410
  {
15264
15411
  label: "Show All Trace Lengths",
@@ -15270,7 +15417,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15270
15417
  }
15271
15418
  }
15272
15419
  ),
15273
- /* @__PURE__ */ jsx20(
15420
+ /* @__PURE__ */ jsx22(
15274
15421
  CheckboxMenuItem,
15275
15422
  {
15276
15423
  label: "Show Autorouting Animation",
@@ -15282,7 +15429,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15282
15429
  }
15283
15430
  }
15284
15431
  ),
15285
- /* @__PURE__ */ jsx20(
15432
+ /* @__PURE__ */ jsx22(
15286
15433
  CheckboxMenuItem,
15287
15434
  {
15288
15435
  label: "Show DRC Errors",
@@ -15292,7 +15439,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15292
15439
  }
15293
15440
  }
15294
15441
  ),
15295
- /* @__PURE__ */ jsx20(
15442
+ /* @__PURE__ */ jsx22(
15296
15443
  CheckboxMenuItem,
15297
15444
  {
15298
15445
  label: "Show Copper Pours",
@@ -15304,7 +15451,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15304
15451
  }
15305
15452
  }
15306
15453
  ),
15307
- /* @__PURE__ */ jsx20(
15454
+ /* @__PURE__ */ jsx22(
15308
15455
  CheckboxMenuItem,
15309
15456
  {
15310
15457
  label: "Show Courtyards",
@@ -15314,7 +15461,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15314
15461
  }
15315
15462
  }
15316
15463
  ),
15317
- /* @__PURE__ */ jsx20(
15464
+ /* @__PURE__ */ jsx22(
15318
15465
  CheckboxMenuItem,
15319
15466
  {
15320
15467
  label: "Show Solder Mask",
@@ -15324,7 +15471,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15324
15471
  }
15325
15472
  }
15326
15473
  ),
15327
- /* @__PURE__ */ jsx20(
15474
+ /* @__PURE__ */ jsx22(
15328
15475
  CheckboxMenuItem,
15329
15476
  {
15330
15477
  label: "Show Silkscreen",
@@ -15334,7 +15481,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15334
15481
  }
15335
15482
  }
15336
15483
  ),
15337
- /* @__PURE__ */ jsx20(
15484
+ /* @__PURE__ */ jsx22(
15338
15485
  CheckboxMenuItem,
15339
15486
  {
15340
15487
  label: "Show Fabrication Notes",
@@ -15346,7 +15493,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15346
15493
  }
15347
15494
  }
15348
15495
  ),
15349
- /* @__PURE__ */ jsx20(
15496
+ /* @__PURE__ */ jsx22(
15350
15497
  CheckboxMenuItem,
15351
15498
  {
15352
15499
  label: "Show Group Anchor Offsets",
@@ -15358,7 +15505,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15358
15505
  }
15359
15506
  }
15360
15507
  ),
15361
- /* @__PURE__ */ jsx20(
15508
+ /* @__PURE__ */ jsx22(
15362
15509
  CheckboxMenuItem,
15363
15510
  {
15364
15511
  label: "Show PCB Groups",
@@ -15368,8 +15515,8 @@ var ToolbarOverlay = ({ children, elements }) => {
15368
15515
  }
15369
15516
  }
15370
15517
  ),
15371
- viewSettings.is_showing_pcb_groups && /* @__PURE__ */ jsxs14("div", { style: { marginLeft: 16 }, children: [
15372
- /* @__PURE__ */ jsx20(
15518
+ viewSettings.is_showing_pcb_groups && /* @__PURE__ */ jsxs15("div", { style: { marginLeft: 16 }, children: [
15519
+ /* @__PURE__ */ jsx22(
15373
15520
  RadioMenuItem,
15374
15521
  {
15375
15522
  label: "Show All Groups",
@@ -15379,7 +15526,7 @@ var ToolbarOverlay = ({ children, elements }) => {
15379
15526
  }
15380
15527
  }
15381
15528
  ),
15382
- /* @__PURE__ */ jsx20(
15529
+ /* @__PURE__ */ jsx22(
15383
15530
  RadioMenuItem,
15384
15531
  {
15385
15532
  label: "Show Named Groups",
@@ -15403,18 +15550,18 @@ var ToolbarOverlay = ({ children, elements }) => {
15403
15550
  };
15404
15551
 
15405
15552
  // src/components/CanvasElementsRenderer.tsx
15406
- import { jsx as jsx21 } from "react/jsx-runtime";
15553
+ import { jsx as jsx23 } from "react/jsx-runtime";
15407
15554
  var CanvasElementsRenderer = (props) => {
15408
15555
  const { transform, elements } = props;
15409
15556
  const hoveredErrorId = useGlobalStore((state) => state.hovered_error_id);
15410
15557
  const isShowingCopperPours = useGlobalStore(
15411
15558
  (state) => state.is_showing_copper_pours
15412
15559
  );
15413
- const elementsToRender = useMemo7(
15560
+ const elementsToRender = useMemo8(
15414
15561
  () => isShowingCopperPours ? elements : elements.filter((elm) => elm.type !== "pcb_copper_pour"),
15415
15562
  [elements, isShowingCopperPours]
15416
15563
  );
15417
- const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo7(() => {
15564
+ const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo8(() => {
15418
15565
  const primitivesWithoutInteractionMetadata2 = elementsToRender.flatMap(
15419
15566
  (elm) => convertElementToPrimitives(elm, props.elements)
15420
15567
  );
@@ -15423,12 +15570,12 @@ var CanvasElementsRenderer = (props) => {
15423
15570
  );
15424
15571
  return [primitivesWithoutInteractionMetadata2, connectivityMap2];
15425
15572
  }, [elementsToRender, props.elements]);
15426
- const [hoverState, setHoverState] = useState11({
15573
+ const [hoverState, setHoverState] = useState12({
15427
15574
  drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
15428
15575
  primitiveIdsInMousedOverNet: []
15429
15576
  });
15430
- const [hoveredComponentIds, setHoveredComponentIds] = useState11([]);
15431
- const errorRelatedIds = useMemo7(() => {
15577
+ const [hoveredComponentIds, setHoveredComponentIds] = useState12([]);
15578
+ const errorRelatedIds = useMemo8(() => {
15432
15579
  if (!hoveredErrorId) return [];
15433
15580
  const errorElements = elements.filter(
15434
15581
  (el) => el.type.includes("error")
@@ -15447,7 +15594,7 @@ var CanvasElementsRenderer = (props) => {
15447
15594
  }
15448
15595
  return relatedIds;
15449
15596
  }, [hoveredErrorId, elements]);
15450
- const primitives = useMemo7(() => {
15597
+ const primitives = useMemo8(() => {
15451
15598
  const combinedPrimitiveIds = [
15452
15599
  ...hoverState.primitiveIdsInMousedOverNet,
15453
15600
  ...errorRelatedIds
@@ -15458,7 +15605,7 @@ var CanvasElementsRenderer = (props) => {
15458
15605
  primitiveIdsInMousedOverNet: combinedPrimitiveIds
15459
15606
  });
15460
15607
  }, [primitivesWithoutInteractionMetadata, hoverState, errorRelatedIds]);
15461
- const onMouseOverPrimitives = useCallback9(
15608
+ const onMouseOverPrimitives = useCallback10(
15462
15609
  (primitivesHoveredOver) => {
15463
15610
  const primitiveIdsInMousedOverNet = [];
15464
15611
  for (const primitive of primitivesHoveredOver) {
@@ -15491,14 +15638,14 @@ var CanvasElementsRenderer = (props) => {
15491
15638
  },
15492
15639
  [connectivityMap]
15493
15640
  );
15494
- return /* @__PURE__ */ jsx21(
15641
+ return /* @__PURE__ */ jsx23(
15495
15642
  MouseElementTracker,
15496
15643
  {
15497
15644
  elements: elementsToRender,
15498
15645
  transform,
15499
15646
  primitives: primitivesWithoutInteractionMetadata,
15500
15647
  onMouseHoverOverPrimitives: onMouseOverPrimitives,
15501
- children: /* @__PURE__ */ jsx21(
15648
+ children: /* @__PURE__ */ jsx23(
15502
15649
  EditPlacementOverlay,
15503
15650
  {
15504
15651
  disabled: !props.allowEditing,
@@ -15507,7 +15654,7 @@ var CanvasElementsRenderer = (props) => {
15507
15654
  cancelPanDrag: props.cancelPanDrag,
15508
15655
  onCreateEditEvent: props.onCreateEditEvent,
15509
15656
  onModifyEditEvent: props.onModifyEditEvent,
15510
- children: /* @__PURE__ */ jsx21(
15657
+ children: /* @__PURE__ */ jsx23(
15511
15658
  EditTraceHintOverlay,
15512
15659
  {
15513
15660
  disabled: !props.allowEditing,
@@ -15516,29 +15663,29 @@ var CanvasElementsRenderer = (props) => {
15516
15663
  cancelPanDrag: props.cancelPanDrag,
15517
15664
  onCreateEditEvent: props.onCreateEditEvent,
15518
15665
  onModifyEditEvent: props.onModifyEditEvent,
15519
- children: /* @__PURE__ */ jsx21(
15666
+ children: /* @__PURE__ */ jsx23(
15520
15667
  DimensionOverlay,
15521
15668
  {
15522
15669
  transform,
15523
15670
  focusOnHover: props.focusOnHover,
15524
15671
  primitives: primitivesWithoutInteractionMetadata,
15525
- children: /* @__PURE__ */ jsx21(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx21(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx21(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx21(
15672
+ children: /* @__PURE__ */ jsx23(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx23(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx23(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx23(
15526
15673
  PcbGroupOverlay,
15527
15674
  {
15528
15675
  transform,
15529
15676
  elements,
15530
15677
  hoveredComponentIds,
15531
- children: /* @__PURE__ */ jsx21(
15678
+ children: /* @__PURE__ */ jsx23(
15532
15679
  DebugGraphicsOverlay,
15533
15680
  {
15534
15681
  transform,
15535
15682
  debugGraphics: props.debugGraphics,
15536
- children: /* @__PURE__ */ jsx21(
15683
+ children: /* @__PURE__ */ jsx23(
15537
15684
  WarningGraphicsOverlay,
15538
15685
  {
15539
15686
  transform,
15540
15687
  elements,
15541
- children: /* @__PURE__ */ jsx21(
15688
+ children: /* @__PURE__ */ jsx23(
15542
15689
  CanvasPrimitiveRenderer,
15543
15690
  {
15544
15691
  transform,
@@ -15620,7 +15767,7 @@ var calculateBoardSizeKey = (circuitJson) => {
15620
15767
  };
15621
15768
 
15622
15769
  // src/PCBViewer.tsx
15623
- import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
15770
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
15624
15771
  var defaultTransform = compose7(translate11(400, 300), scale5(40, -40));
15625
15772
  var PCBViewer = ({
15626
15773
  circuitJson,
@@ -15634,12 +15781,12 @@ var PCBViewer = ({
15634
15781
  clickToInteractEnabled = false,
15635
15782
  disablePcbGroups = false
15636
15783
  }) => {
15637
- const [isInteractionEnabled, setIsInteractionEnabled] = useState12(
15784
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState13(
15638
15785
  !clickToInteractEnabled
15639
15786
  );
15640
15787
  const [ref, refDimensions] = useMeasure_default();
15641
- const [transform, setTransformInternal] = useState12(defaultTransform);
15642
- const shouldAllowCanvasInteraction = useCallback10(
15788
+ const [transform, setTransformInternal] = useState13(defaultTransform);
15789
+ const shouldAllowCanvasInteraction = useCallback11(
15643
15790
  (event) => {
15644
15791
  const target = event.target;
15645
15792
  if (!(target instanceof Element)) return true;
@@ -15657,11 +15804,11 @@ var PCBViewer = ({
15657
15804
  enabled: isInteractionEnabled,
15658
15805
  shouldDrag: shouldAllowCanvasInteraction
15659
15806
  });
15660
- let [editEvents, setEditEvents] = useState12([]);
15807
+ let [editEvents, setEditEvents] = useState13([]);
15661
15808
  editEvents = editEventsProp ?? editEvents;
15662
15809
  const initialRenderCompleted = useRef14(false);
15663
15810
  const touchStartRef = useRef14(null);
15664
- const circuitJsonKey = useMemo8(
15811
+ const circuitJsonKey = useMemo9(
15665
15812
  () => calculateCircuitJsonKey(circuitJson),
15666
15813
  [circuitJson]
15667
15814
  );
@@ -15700,12 +15847,12 @@ var PCBViewer = ({
15700
15847
  resetTransform();
15701
15848
  }
15702
15849
  }, [boardSizeKey]);
15703
- const pcbElmsPreEdit = useMemo8(() => {
15850
+ const pcbElmsPreEdit = useMemo9(() => {
15704
15851
  return circuitJson?.filter(
15705
15852
  (e) => e.type.startsWith("pcb_") || e.type.startsWith("source_")
15706
15853
  ) ?? [];
15707
15854
  }, [circuitJsonKey]);
15708
- const elements = useMemo8(() => {
15855
+ const elements = useMemo9(() => {
15709
15856
  return applyEditEvents({
15710
15857
  circuitJson: pcbElmsPreEdit,
15711
15858
  editEvents
@@ -15722,27 +15869,27 @@ var PCBViewer = ({
15722
15869
  setEditEvents(newEditEvents);
15723
15870
  onEditEventsChanged?.(newEditEvents);
15724
15871
  };
15725
- const mergedInitialState = useMemo8(
15872
+ const mergedInitialState = useMemo9(
15726
15873
  () => ({
15727
15874
  ...initialState,
15728
15875
  ...disablePcbGroups && { is_showing_pcb_groups: false }
15729
15876
  }),
15730
15877
  [initialState, disablePcbGroups]
15731
15878
  );
15732
- return /* @__PURE__ */ jsxs15(
15879
+ return /* @__PURE__ */ jsxs16(
15733
15880
  "div",
15734
15881
  {
15735
15882
  ref: transformRef,
15736
15883
  style: { position: "relative" },
15737
15884
  onContextMenu: (event) => event.preventDefault(),
15738
15885
  children: [
15739
- /* @__PURE__ */ jsx22("div", { ref, children: /* @__PURE__ */ jsxs15(
15886
+ /* @__PURE__ */ jsx24("div", { ref, children: /* @__PURE__ */ jsxs16(
15740
15887
  ContextProviders,
15741
15888
  {
15742
15889
  initialState: mergedInitialState,
15743
15890
  disablePcbGroups,
15744
15891
  children: [
15745
- /* @__PURE__ */ jsx22(
15892
+ /* @__PURE__ */ jsx24(
15746
15893
  CanvasElementsRenderer,
15747
15894
  {
15748
15895
  transform,
@@ -15767,11 +15914,11 @@ var PCBViewer = ({
15767
15914
  },
15768
15915
  refDimensions.width
15769
15916
  ),
15770
- /* @__PURE__ */ jsx22(ToastContainer, {})
15917
+ /* @__PURE__ */ jsx24(ToastContainer, {})
15771
15918
  ]
15772
15919
  }
15773
15920
  ) }),
15774
- clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx22(
15921
+ clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx24(
15775
15922
  "div",
15776
15923
  {
15777
15924
  onClick: () => {
@@ -15808,7 +15955,7 @@ var PCBViewer = ({
15808
15955
  justifyContent: "center",
15809
15956
  touchAction: "pan-x pan-y pinch-zoom"
15810
15957
  },
15811
- children: /* @__PURE__ */ jsx22(
15958
+ children: /* @__PURE__ */ jsx24(
15812
15959
  "div",
15813
15960
  {
15814
15961
  style: {