@tscircuit/pcb-viewer 1.11.337 → 1.11.338

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
@@ -24,6 +24,141 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  mod
25
25
  ));
26
26
 
27
+ // node_modules/toggle-selection/index.js
28
+ var require_toggle_selection = __commonJS({
29
+ "node_modules/toggle-selection/index.js"(exports, module) {
30
+ module.exports = function() {
31
+ var selection = document.getSelection();
32
+ if (!selection.rangeCount) {
33
+ return function() {
34
+ };
35
+ }
36
+ var active = document.activeElement;
37
+ var ranges = [];
38
+ for (var i = 0; i < selection.rangeCount; i++) {
39
+ ranges.push(selection.getRangeAt(i));
40
+ }
41
+ switch (active.tagName.toUpperCase()) {
42
+ // .toUpperCase handles XHTML
43
+ case "INPUT":
44
+ case "TEXTAREA":
45
+ active.blur();
46
+ break;
47
+ default:
48
+ active = null;
49
+ break;
50
+ }
51
+ selection.removeAllRanges();
52
+ return function() {
53
+ selection.type === "Caret" && selection.removeAllRanges();
54
+ if (!selection.rangeCount) {
55
+ ranges.forEach(function(range) {
56
+ selection.addRange(range);
57
+ });
58
+ }
59
+ active && active.focus();
60
+ };
61
+ };
62
+ }
63
+ });
64
+
65
+ // node_modules/copy-to-clipboard/index.js
66
+ var require_copy_to_clipboard = __commonJS({
67
+ "node_modules/copy-to-clipboard/index.js"(exports, module) {
68
+ "use strict";
69
+ var deselectCurrent = require_toggle_selection();
70
+ var clipboardToIE11Formatting = {
71
+ "text/plain": "Text",
72
+ "text/html": "Url",
73
+ "default": "Text"
74
+ };
75
+ var defaultMessage = "Copy to clipboard: #{key}, Enter";
76
+ function format(message) {
77
+ var copyKey = (/mac os x/i.test(navigator.userAgent) ? "\u2318" : "Ctrl") + "+C";
78
+ return message.replace(/#{\s*key\s*}/g, copyKey);
79
+ }
80
+ function copy(text, options) {
81
+ var debug, message, reselectPrevious, range, selection, mark, success = false;
82
+ if (!options) {
83
+ options = {};
84
+ }
85
+ debug = options.debug || false;
86
+ try {
87
+ reselectPrevious = deselectCurrent();
88
+ range = document.createRange();
89
+ selection = document.getSelection();
90
+ mark = document.createElement("span");
91
+ mark.textContent = text;
92
+ mark.ariaHidden = "true";
93
+ mark.style.all = "unset";
94
+ mark.style.position = "fixed";
95
+ mark.style.top = 0;
96
+ mark.style.clip = "rect(0, 0, 0, 0)";
97
+ mark.style.whiteSpace = "pre";
98
+ mark.style.webkitUserSelect = "text";
99
+ mark.style.MozUserSelect = "text";
100
+ mark.style.msUserSelect = "text";
101
+ mark.style.userSelect = "text";
102
+ mark.addEventListener("copy", function(e) {
103
+ e.stopPropagation();
104
+ if (options.format) {
105
+ e.preventDefault();
106
+ if (typeof e.clipboardData === "undefined") {
107
+ debug && console.warn("unable to use e.clipboardData");
108
+ debug && console.warn("trying IE specific stuff");
109
+ window.clipboardData.clearData();
110
+ var format2 = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting["default"];
111
+ window.clipboardData.setData(format2, text);
112
+ } else {
113
+ e.clipboardData.clearData();
114
+ e.clipboardData.setData(options.format, text);
115
+ }
116
+ }
117
+ if (options.onCopy) {
118
+ e.preventDefault();
119
+ options.onCopy(e.clipboardData);
120
+ }
121
+ });
122
+ document.body.appendChild(mark);
123
+ range.selectNodeContents(mark);
124
+ selection.addRange(range);
125
+ var successful = document.execCommand("copy");
126
+ if (!successful) {
127
+ throw new Error("copy command was unsuccessful");
128
+ }
129
+ success = true;
130
+ } catch (err) {
131
+ debug && console.error("unable to copy using execCommand: ", err);
132
+ debug && console.warn("trying IE specific stuff");
133
+ try {
134
+ window.clipboardData.setData(options.format || "text", text);
135
+ options.onCopy && options.onCopy(window.clipboardData);
136
+ success = true;
137
+ } catch (err2) {
138
+ debug && console.error("unable to copy using clipboardData: ", err2);
139
+ debug && console.error("falling back to prompt");
140
+ message = format("message" in options ? options.message : defaultMessage);
141
+ window.prompt(message, text);
142
+ }
143
+ } finally {
144
+ if (selection) {
145
+ if (typeof selection.removeRange == "function") {
146
+ selection.removeRange(range);
147
+ } else {
148
+ selection.removeAllRanges();
149
+ }
150
+ }
151
+ if (mark) {
152
+ document.body.removeChild(mark);
153
+ }
154
+ reselectPrevious();
155
+ }
156
+ return success;
157
+ }
158
+ module.exports = copy;
159
+ }
160
+ });
161
+
27
162
  // node_modules/svgson/dist/svgson.umd.js
28
163
  var require_svgson_umd = __commonJS({
29
164
  "node_modules/svgson/dist/svgson.umd.js"(exports, module) {
@@ -6451,20 +6586,109 @@ var ToastContainer = () => {
6451
6586
  };
6452
6587
 
6453
6588
  // src/PCBViewer.tsx
6454
- import { useEffect as useEffect16, useMemo as useMemo8, useRef as useRef12, useState as useState11 } from "react";
6589
+ import { useEffect as useEffect17, useMemo as useMemo8, useRef as useRef14, useState as useState12 } from "react";
6590
+
6591
+ // node_modules/react-use/esm/useMountedState.js
6592
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
6593
+ function useMountedState() {
6594
+ var mountedRef = useRef(false);
6595
+ var get = useCallback2(function() {
6596
+ return mountedRef.current;
6597
+ }, []);
6598
+ useEffect2(function() {
6599
+ mountedRef.current = true;
6600
+ return function() {
6601
+ mountedRef.current = false;
6602
+ };
6603
+ }, []);
6604
+ return get;
6605
+ }
6606
+
6607
+ // node_modules/react-use/esm/useSetState.js
6608
+ import { useCallback as useCallback3, useState } from "react";
6609
+ var useSetState = function(initialState) {
6610
+ if (initialState === void 0) {
6611
+ initialState = {};
6612
+ }
6613
+ var _a = useState(initialState), state = _a[0], set = _a[1];
6614
+ var setState = useCallback3(function(patch) {
6615
+ set(function(prevState) {
6616
+ return Object.assign({}, prevState, patch instanceof Function ? patch(prevState) : patch);
6617
+ });
6618
+ }, []);
6619
+ return [state, setState];
6620
+ };
6621
+ var useSetState_default = useSetState;
6455
6622
 
6456
6623
  // node_modules/react-use/esm/misc/util.js
6457
6624
  var noop = function() {
6458
6625
  };
6459
6626
  var isBrowser = typeof window !== "undefined";
6460
6627
 
6628
+ // node_modules/react-use/esm/useCopyToClipboard.js
6629
+ var import_copy_to_clipboard = __toESM(require_copy_to_clipboard());
6630
+ import { useCallback as useCallback4 } from "react";
6631
+ var useCopyToClipboard = function() {
6632
+ var isMounted = useMountedState();
6633
+ var _a = useSetState_default({
6634
+ value: void 0,
6635
+ error: void 0,
6636
+ noUserInteraction: true
6637
+ }), state = _a[0], setState = _a[1];
6638
+ var copyToClipboard = useCallback4(function(value) {
6639
+ if (!isMounted()) {
6640
+ return;
6641
+ }
6642
+ var noUserInteraction;
6643
+ var normalizedValue;
6644
+ try {
6645
+ if (typeof value !== "string" && typeof value !== "number") {
6646
+ var error = new Error("Cannot copy typeof " + typeof value + " to clipboard, must be a string");
6647
+ if (true)
6648
+ console.error(error);
6649
+ setState({
6650
+ value,
6651
+ error,
6652
+ noUserInteraction: true
6653
+ });
6654
+ return;
6655
+ } else if (value === "") {
6656
+ var error = new Error("Cannot copy empty string to clipboard.");
6657
+ if (true)
6658
+ console.error(error);
6659
+ setState({
6660
+ value,
6661
+ error,
6662
+ noUserInteraction: true
6663
+ });
6664
+ return;
6665
+ }
6666
+ normalizedValue = value.toString();
6667
+ noUserInteraction = (0, import_copy_to_clipboard.default)(normalizedValue);
6668
+ setState({
6669
+ value: normalizedValue,
6670
+ error: void 0,
6671
+ noUserInteraction
6672
+ });
6673
+ } catch (error2) {
6674
+ setState({
6675
+ value: normalizedValue,
6676
+ error: error2,
6677
+ noUserInteraction
6678
+ });
6679
+ }
6680
+ }, []);
6681
+ return [state, copyToClipboard];
6682
+ };
6683
+ var useCopyToClipboard_default = useCopyToClipboard;
6684
+
6461
6685
  // node_modules/react-use/esm/useIsomorphicLayoutEffect.js
6462
- import { useEffect as useEffect2, useLayoutEffect } from "react";
6463
- var useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect2;
6686
+ import { useEffect as useEffect3, useLayoutEffect } from "react";
6687
+ var useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect3;
6464
6688
  var useIsomorphicLayoutEffect_default = useIsomorphicLayoutEffect;
6465
6689
 
6466
6690
  // node_modules/react-use/esm/useMeasure.js
6467
- import { useMemo as useMemo2, useState } from "react";
6691
+ import { useMemo as useMemo2, useState as useState2 } from "react";
6468
6692
  var defaultState = {
6469
6693
  x: 0,
6470
6694
  y: 0,
@@ -6476,8 +6700,8 @@ var defaultState = {
6476
6700
  right: 0
6477
6701
  };
6478
6702
  function useMeasure() {
6479
- var _a = useState(null), element = _a[0], ref = _a[1];
6480
- var _b = useState(defaultState), rect = _b[0], setRect = _b[1];
6703
+ var _a = useState2(null), element = _a[0], ref = _a[1];
6704
+ var _b = useState2(defaultState), rect = _b[0], setRect = _b[1];
6481
6705
  var observer = useMemo2(function() {
6482
6706
  return new window.ResizeObserver(function(entries) {
6483
6707
  if (entries[0]) {
@@ -6552,17 +6776,17 @@ import {
6552
6776
  applyToPoint as applyToPoint2,
6553
6777
  scale as scale2
6554
6778
  } from "transformation-matrix";
6555
- import { useCallback as useCallback2, useEffect as useEffect3, useReducer, useRef, useState as useState2 } from "react";
6779
+ import { useCallback as useCallback5, useEffect as useEffect4, useReducer, useRef as useRef2, useState as useState3 } from "react";
6556
6780
  var useMouseMatrixTransform = (props = {}) => {
6557
- const extRef = useRef(null);
6558
- const [lastDragCancelTime, setLastDragCancelTime] = useState2(0);
6781
+ const extRef = useRef2(null);
6782
+ const [lastDragCancelTime, setLastDragCancelTime] = useState3(0);
6559
6783
  const outerCanvasElm = props.canvasElm ?? extRef.current;
6560
- const [internalTransform, setInternalTransform] = useState2(
6784
+ const [internalTransform, setInternalTransform] = useState3(
6561
6785
  props.initialTransform ?? identity()
6562
6786
  );
6563
- const [waitCounter, setWaitCounter] = useState2(0);
6787
+ const [waitCounter, setWaitCounter] = useState3(0);
6564
6788
  const [extChangeCounter, incExtChangeCounter] = useReducer((s) => s + 1, 0);
6565
- const setTransform = useCallback2(
6789
+ const setTransform = useCallback5(
6566
6790
  (newTransform) => {
6567
6791
  if (props.onSetTransform) {
6568
6792
  props.onSetTransform(newTransform);
@@ -6573,7 +6797,7 @@ var useMouseMatrixTransform = (props = {}) => {
6573
6797
  },
6574
6798
  [props.onSetTransform, setInternalTransform]
6575
6799
  );
6576
- const setTransformExt = useCallback2(
6800
+ const setTransformExt = useCallback5(
6577
6801
  (newTransform) => {
6578
6802
  setTransform(newTransform);
6579
6803
  incExtChangeCounter();
@@ -6581,13 +6805,13 @@ var useMouseMatrixTransform = (props = {}) => {
6581
6805
  [setTransform]
6582
6806
  );
6583
6807
  const transform = props.transform ?? internalTransform;
6584
- const cancelDrag = useCallback2(() => {
6808
+ const cancelDrag = useCallback5(() => {
6585
6809
  setLastDragCancelTime(Date.now());
6586
6810
  }, []);
6587
- const gestureModeRef = useRef("none");
6588
- const dragDataRef = useRef(null);
6589
- const pinchDataRef = useRef(null);
6590
- useEffect3(() => {
6811
+ const gestureModeRef = useRef2("none");
6812
+ const dragDataRef = useRef2(null);
6813
+ const pinchDataRef = useRef2(null);
6814
+ useEffect4(() => {
6591
6815
  const canvasElm = props.canvasElm ?? extRef.current;
6592
6816
  if (canvasElm && !outerCanvasElm) {
6593
6817
  setWaitCounter(waitCounter + 1);
@@ -6781,7 +7005,7 @@ var useMouseMatrixTransform = (props = {}) => {
6781
7005
  props.enabled,
6782
7006
  props.shouldDrag
6783
7007
  ]);
6784
- const applyTransformToPoint = useCallback2(
7008
+ const applyTransformToPoint = useCallback5(
6785
7009
  (obj) => applyToPoint2(transform, obj),
6786
7010
  [transform]
6787
7011
  );
@@ -7001,7 +7225,7 @@ function addInteractionMetadataToPrimitives({
7001
7225
  }
7002
7226
 
7003
7227
  // src/components/CanvasElementsRenderer.tsx
7004
- import { useCallback as useCallback5, useMemo as useMemo7, useState as useState10 } from "react";
7228
+ import { useCallback as useCallback9, useMemo as useMemo7, useState as useState11 } from "react";
7005
7229
 
7006
7230
  // src/lib/util/expand-stroke.ts
7007
7231
  function getExpandedStroke(strokeInput, defaultWidth) {
@@ -9545,7 +9769,7 @@ function drawCourtyardElementsForLayer({
9545
9769
  }
9546
9770
 
9547
9771
  // src/components/CanvasPrimitiveRenderer.tsx
9548
- import { useEffect as useEffect4, useRef as useRef2 } from "react";
9772
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
9549
9773
  import { SuperGrid, toMMSI } from "react-supergrid";
9550
9774
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
9551
9775
  var orderedLayers = [
@@ -9583,10 +9807,10 @@ var CanvasPrimitiveRenderer = ({
9583
9807
  width = 500,
9584
9808
  height = 500
9585
9809
  }) => {
9586
- const canvasRefs = useRef2({});
9810
+ const canvasRefs = useRef3({});
9587
9811
  const selectedLayer = useGlobalStore((s) => s.selected_layer);
9588
9812
  const isShowingSolderMask = useGlobalStore((s) => s.is_showing_solder_mask);
9589
- useEffect4(() => {
9813
+ useEffect5(() => {
9590
9814
  if (!canvasRefs.current) return;
9591
9815
  if (Object.keys(canvasRefs.current).length === 0) return;
9592
9816
  const filteredCanvasRefs = Object.fromEntries(
@@ -10232,17 +10456,17 @@ function drawGraphicsToCanvas(graphics, target, options = {}) {
10232
10456
  }
10233
10457
 
10234
10458
  // src/components/DebugGraphicsOverlay.tsx
10235
- import { useEffect as useEffect5, useRef as useRef3 } from "react";
10459
+ import { useEffect as useEffect6, useRef as useRef4 } from "react";
10236
10460
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
10237
10461
  var DebugGraphicsOverlay = ({
10238
10462
  children,
10239
10463
  transform,
10240
10464
  debugGraphics
10241
10465
  }) => {
10242
- const canvasRef = useRef3(null);
10466
+ const canvasRef = useRef4(null);
10243
10467
  const [containerRef, { width, height }] = useMeasure_default();
10244
10468
  const is_showing_autorouting = useGlobalStore((s) => s.is_showing_autorouting);
10245
- useEffect5(() => {
10469
+ useEffect6(() => {
10246
10470
  if (!is_showing_autorouting) return;
10247
10471
  if (canvasRef.current && debugGraphics && width && height) {
10248
10472
  canvasRef.current.width = width;
@@ -10283,7 +10507,7 @@ var DebugGraphicsOverlay = ({
10283
10507
  };
10284
10508
 
10285
10509
  // src/components/WarningGraphicsOverlay.tsx
10286
- import { useEffect as useEffect6, useRef as useRef4 } from "react";
10510
+ import { useEffect as useEffect7, useRef as useRef5 } from "react";
10287
10511
  import { applyToPoint as applyToPoint7, identity as identity3 } from "transformation-matrix";
10288
10512
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
10289
10513
  var WarningGraphicsOverlay = ({
@@ -10292,8 +10516,8 @@ var WarningGraphicsOverlay = ({
10292
10516
  elements = []
10293
10517
  }) => {
10294
10518
  const [containerRef, { width, height }] = useMeasure_default();
10295
- const canvasRef = useRef4(null);
10296
- useEffect6(() => {
10519
+ const canvasRef = useRef5(null);
10520
+ useEffect7(() => {
10297
10521
  const canvas = canvasRef.current;
10298
10522
  if (!canvas || !width || !height) return;
10299
10523
  canvas.width = width;
@@ -10371,7 +10595,7 @@ var WarningGraphicsOverlay = ({
10371
10595
  };
10372
10596
 
10373
10597
  // src/components/DimensionOverlay.tsx
10374
- import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef5, useState as useState3 } from "react";
10598
+ import { useCallback as useCallback6, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef6, useState as useState4 } from "react";
10375
10599
  import { applyToPoint as applyToPoint8, identity as identity4, inverse as inverse2 } from "transformation-matrix";
10376
10600
 
10377
10601
  // src/lib/util/get-primitive-bounding-box.ts
@@ -10773,24 +10997,24 @@ var DimensionOverlay = ({
10773
10997
  primitives = []
10774
10998
  }) => {
10775
10999
  if (!transform) transform = identity4();
10776
- const [dimensionToolVisible, setDimensionToolVisible] = useState3(false);
10777
- const [dimensionToolStretching, setDimensionToolStretching] = useState3(false);
10778
- const [measureToolArmed, setMeasureToolArmed] = useState3(false);
10779
- const [activeSnapIds, setActiveSnapIds] = useState3({
11000
+ const [dimensionToolVisible, setDimensionToolVisible] = useState4(false);
11001
+ const [dimensionToolStretching, setDimensionToolStretching] = useState4(false);
11002
+ const [measureToolArmed, setMeasureToolArmed] = useState4(false);
11003
+ const [activeSnapIds, setActiveSnapIds] = useState4({
10780
11004
  start: null,
10781
11005
  end: null
10782
11006
  });
10783
11007
  const isMouseOverContainer = useGlobalStore((s) => s.is_mouse_over_container);
10784
- const disarmMeasure = useCallback3(() => {
11008
+ const disarmMeasure = useCallback6(() => {
10785
11009
  if (measureToolArmed) {
10786
11010
  setMeasureToolArmed(false);
10787
11011
  window.dispatchEvent(new Event("disarm-dimension-tool"));
10788
11012
  }
10789
11013
  }, [measureToolArmed]);
10790
- const [dStart, setDStart] = useState3({ x: 0, y: 0 });
10791
- const [dEnd, setDEnd] = useState3({ x: 0, y: 0 });
10792
- const mousePosRef = useRef5({ x: 0, y: 0 });
10793
- const containerRef = useRef5(null);
11014
+ const [dStart, setDStart] = useState4({ x: 0, y: 0 });
11015
+ const [dEnd, setDEnd] = useState4({ x: 0, y: 0 });
11016
+ const mousePosRef = useRef6({ x: 0, y: 0 });
11017
+ const containerRef = useRef6(null);
10794
11018
  const container = containerRef.current;
10795
11019
  const containerBounds = container?.getBoundingClientRect();
10796
11020
  const elementBoundingBoxes = useMemo4(() => {
@@ -10870,7 +11094,7 @@ var DimensionOverlay = ({
10870
11094
  screenPoint: applyToPoint8(transform, snap.point)
10871
11095
  }));
10872
11096
  }, [snappingPoints, transform]);
10873
- const findSnap = useCallback3(
11097
+ const findSnap = useCallback6(
10874
11098
  (rwPoint) => {
10875
11099
  if (snappingPointsWithScreen.length === 0) {
10876
11100
  return { point: rwPoint, id: null };
@@ -10897,7 +11121,7 @@ var DimensionOverlay = ({
10897
11121
  },
10898
11122
  [snappingPointsWithScreen, transform]
10899
11123
  );
10900
- useEffect7(() => {
11124
+ useEffect8(() => {
10901
11125
  const down = (e) => {
10902
11126
  const target = e.target;
10903
11127
  if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable) {
@@ -11241,7 +11465,7 @@ var DimensionOverlay = ({
11241
11465
  };
11242
11466
 
11243
11467
  // src/components/EditPlacementOverlay.tsx
11244
- import { useRef as useRef6, useState as useState4 } from "react";
11468
+ import { useRef as useRef7, useState as useState5 } from "react";
11245
11469
  import { applyToPoint as applyToPoint9, identity as identity5, inverse as inverse3 } from "transformation-matrix";
11246
11470
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
11247
11471
  var isInsideOf = (pcb_component, point, padding = 0) => {
@@ -11263,11 +11487,11 @@ var EditPlacementOverlay = ({
11263
11487
  onModifyEditEvent
11264
11488
  }) => {
11265
11489
  if (!transform) transform = identity5();
11266
- const containerRef = useRef6(null);
11267
- const [activePcbComponentId, setActivePcbComponent] = useState4(
11490
+ const containerRef = useRef7(null);
11491
+ const [activePcbComponentId, setActivePcbComponent] = useState5(
11268
11492
  null
11269
11493
  );
11270
- const [dragState, setDragState] = useState4(null);
11494
+ const [dragState, setDragState] = useState5(null);
11271
11495
  const isPcbComponentActive = activePcbComponentId !== null;
11272
11496
  const in_edit_mode = useGlobalStore((s) => s.in_edit_mode);
11273
11497
  const in_move_footprint_mode = useGlobalStore((s) => s.in_move_footprint_mode);
@@ -11383,7 +11607,7 @@ var EditPlacementOverlay = ({
11383
11607
  };
11384
11608
 
11385
11609
  // src/components/EditTraceHintOverlay.tsx
11386
- import { Fragment as Fragment2, useEffect as useEffect10, useRef as useRef7, useState as useState5 } from "react";
11610
+ import { Fragment as Fragment2, useEffect as useEffect11, useRef as useRef8, useState as useState6 } from "react";
11387
11611
  import {
11388
11612
  applyToPoint as applyToPoint10,
11389
11613
  identity as identity6,
@@ -11392,12 +11616,12 @@ import {
11392
11616
 
11393
11617
  // src/components/HotkeyActionMenu.tsx
11394
11618
  import { css } from "@emotion/css";
11395
- import { useEffect as useEffect9 } from "react";
11619
+ import { useEffect as useEffect10 } from "react";
11396
11620
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
11397
11621
  var HotkeyActionMenu = ({
11398
11622
  hotkeys
11399
11623
  }) => {
11400
- useEffect9(() => {
11624
+ useEffect10(() => {
11401
11625
  const handleKeyDown = (event) => {
11402
11626
  hotkeys.forEach((hotkey) => {
11403
11627
  if (event.key === hotkey.key) {
@@ -11506,12 +11730,12 @@ var EditTraceHintOverlay = ({
11506
11730
  onModifyEditEvent
11507
11731
  }) => {
11508
11732
  if (!transform) transform = identity6();
11509
- const containerRef = useRef7(null);
11733
+ const containerRef = useRef8(null);
11510
11734
  const containerBounds = containerRef.current?.getBoundingClientRect();
11511
- const [selectedElement, setSelectedElement] = useState5(null);
11735
+ const [selectedElement, setSelectedElement] = useState6(null);
11512
11736
  const toast = useToast();
11513
- const [dragState, setDragState] = useState5(null);
11514
- const [shouldCreateAsVia, setShouldCreateAsVia] = useState5(false);
11737
+ const [dragState, setDragState] = useState6(null);
11738
+ const [shouldCreateAsVia, setShouldCreateAsVia] = useState6(false);
11515
11739
  const isElementSelected = selectedElement !== null;
11516
11740
  const in_edit_trace_mode = useGlobalStore((s) => s.in_draw_trace_mode);
11517
11741
  const disabled = disabledProp || !in_edit_trace_mode;
@@ -11520,7 +11744,7 @@ var EditTraceHintOverlay = ({
11520
11744
  ogCenterScreen = applyToPoint10(transform, dragState?.originalCenter);
11521
11745
  dragEndScreen = applyToPoint10(transform, dragState?.dragEnd);
11522
11746
  }
11523
- useEffect10(() => {
11747
+ useEffect11(() => {
11524
11748
  if (!isElementSelected) return;
11525
11749
  function keyDown(e) {
11526
11750
  if (e.key === "Escape") {
@@ -11792,7 +12016,7 @@ var EditTraceHintOverlay = ({
11792
12016
  };
11793
12017
 
11794
12018
  // src/components/ErrorOverlay.tsx
11795
- import { useRef as useRef8, Fragment as Fragment3 } from "react";
12019
+ import { useRef as useRef9, Fragment as Fragment3 } from "react";
11796
12020
  import { css as css2 } from "@emotion/css";
11797
12021
  import { applyToPoint as applyToPoint11, identity as identity7 } from "transformation-matrix";
11798
12022
 
@@ -11951,7 +12175,7 @@ var ErrorOverlay = ({
11951
12175
  transform = identity7(),
11952
12176
  elements
11953
12177
  }) => {
11954
- const containerRef = useRef8(null);
12178
+ const containerRef = useRef9(null);
11955
12179
  const { isShowingDRCErrors, hoveredErrorId } = useGlobalStore((state) => ({
11956
12180
  isShowingDRCErrors: state.is_showing_drc_errors,
11957
12181
  hoveredErrorId: state.hovered_error_id
@@ -12317,11 +12541,11 @@ function ifSetsMatchExactly(set1, set2) {
12317
12541
  }
12318
12542
 
12319
12543
  // src/components/MouseElementTracker.tsx
12320
- import { useState as useState7, useMemo as useMemo5 } from "react";
12544
+ import { useState as useState8, useMemo as useMemo5 } from "react";
12321
12545
  import { applyToPoint as applyToPoint14, inverse as inverse5 } from "transformation-matrix";
12322
12546
 
12323
12547
  // src/components/ElementOverlayBox.tsx
12324
- import { useEffect as useEffect11, useState as useState6 } from "react";
12548
+ import { useEffect as useEffect12, useState as useState7 } from "react";
12325
12549
 
12326
12550
  // src/lib/get-trace-overlay-text.ts
12327
12551
  function getTraceOverlayInfo({
@@ -12439,9 +12663,9 @@ var HighlightedPrimitiveBoxWithText = ({
12439
12663
  mousePos,
12440
12664
  elements
12441
12665
  }) => {
12442
- const [finalState, setFinalState] = useState6(false);
12666
+ const [finalState, setFinalState] = useState7(false);
12443
12667
  const primitiveElement = primitive._element;
12444
- useEffect11(() => {
12668
+ useEffect12(() => {
12445
12669
  setTimeout(() => {
12446
12670
  setFinalState(true);
12447
12671
  }, 100);
@@ -13365,8 +13589,8 @@ var MouseElementTracker = ({
13365
13589
  primitives,
13366
13590
  onMouseHoverOverPrimitives
13367
13591
  }) => {
13368
- const [mousedPrimitives, setMousedPrimitives] = useState7([]);
13369
- const [mousePos, setMousePos] = useState7({ x: 0, y: 0 });
13592
+ const [mousedPrimitives, setMousedPrimitives] = useState8([]);
13593
+ const [mousePos, setMousePos] = useState8({ x: 0, y: 0 });
13370
13594
  const [containerRef, { width, height }] = useMeasure_default();
13371
13595
  const highlightedPrimitives = useMemo5(() => {
13372
13596
  const highlightedPrimitives2 = [];
@@ -13521,7 +13745,7 @@ var MouseElementTracker = ({
13521
13745
  // src/components/PcbGroupOverlay.tsx
13522
13746
  import { applyToPoint as applyToPoint15 } from "transformation-matrix";
13523
13747
  import { identity as identity8 } from "transformation-matrix";
13524
- import { useRef as useRef9, useEffect as useEffect12 } from "react";
13748
+ import { useRef as useRef10, useEffect as useEffect13 } from "react";
13525
13749
  import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
13526
13750
  var GROUP_COLORS = [
13527
13751
  "rgb(255, 100, 100)",
@@ -13542,7 +13766,7 @@ var PcbGroupOverlay = ({
13542
13766
  hoveredComponentIds = []
13543
13767
  }) => {
13544
13768
  const [containerRef, { width, height }] = useMeasure_default();
13545
- const canvasRef = useRef9(null);
13769
+ const canvasRef = useRef10(null);
13546
13770
  const {
13547
13771
  is_showing_pcb_groups,
13548
13772
  pcb_group_view_mode,
@@ -13552,7 +13776,7 @@ var PcbGroupOverlay = ({
13552
13776
  pcb_group_view_mode: s.pcb_group_view_mode,
13553
13777
  is_showing_group_anchor_offsets: s.is_showing_group_anchor_offsets
13554
13778
  }));
13555
- useEffect12(() => {
13779
+ useEffect13(() => {
13556
13780
  const canvas = canvasRef.current;
13557
13781
  if (!canvas || !width || !height) return;
13558
13782
  canvas.width = width;
@@ -13886,10 +14110,10 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
13886
14110
 
13887
14111
  // src/components/ToolbarOverlay.tsx
13888
14112
  import {
13889
- useEffect as useEffect15,
13890
- useState as useState9,
13891
- useCallback as useCallback4,
13892
- useRef as useRef11,
14113
+ useEffect as useEffect16,
14114
+ useState as useState10,
14115
+ useCallback as useCallback8,
14116
+ useRef as useRef13,
13893
14117
  useLayoutEffect as useLayoutEffect2
13894
14118
  } from "react";
13895
14119
  import { css as css3 } from "@emotion/css";
@@ -13897,7 +14121,7 @@ import { css as css3 } from "@emotion/css";
13897
14121
  // package.json
13898
14122
  var package_default = {
13899
14123
  name: "@tscircuit/pcb-viewer",
13900
- version: "1.11.336",
14124
+ version: "1.11.337",
13901
14125
  main: "dist/index.js",
13902
14126
  type: "module",
13903
14127
  repository: "tscircuit/pcb-viewer",
@@ -13962,20 +14186,20 @@ var package_default = {
13962
14186
  };
13963
14187
 
13964
14188
  // src/hooks/useHotKey.ts
13965
- import { useEffect as useEffect13, useRef as useRef10 } from "react";
14189
+ import { useEffect as useEffect14, useRef as useRef11 } from "react";
13966
14190
  var useHotKey = (key, onUse, containerRef) => {
13967
14191
  const isMouseOverContainer = useGlobalStore(
13968
14192
  (s) => s.is_mouse_over_container
13969
14193
  );
13970
- const isMouseOverContainerRef = useRef10(isMouseOverContainer);
13971
- const onUseRef = useRef10(onUse);
13972
- useEffect13(() => {
14194
+ const isMouseOverContainerRef = useRef11(isMouseOverContainer);
14195
+ const onUseRef = useRef11(onUse);
14196
+ useEffect14(() => {
13973
14197
  isMouseOverContainerRef.current = isMouseOverContainer;
13974
14198
  }, [isMouseOverContainer]);
13975
- useEffect13(() => {
14199
+ useEffect14(() => {
13976
14200
  onUseRef.current = onUse;
13977
14201
  }, [onUse]);
13978
- useEffect13(() => {
14202
+ useEffect14(() => {
13979
14203
  if (!key) return;
13980
14204
  const handleKeyDown = (event) => {
13981
14205
  const target = event.target;
@@ -14003,10 +14227,10 @@ var useHotKey = (key, onUse, containerRef) => {
14003
14227
  };
14004
14228
 
14005
14229
  // src/hooks/useIsSmallScreen.ts
14006
- import { useEffect as useEffect14, useState as useState8 } from "react";
14230
+ import { useEffect as useEffect15, useState as useState9 } from "react";
14007
14231
  var useIsSmallScreen = () => {
14008
- const [isSmallScreen, setIsSmallScreen] = useState8(false);
14009
- useEffect14(() => {
14232
+ const [isSmallScreen, setIsSmallScreen] = useState9(false);
14233
+ useEffect15(() => {
14010
14234
  const checkIsMobile = () => {
14011
14235
  setIsSmallScreen(window.innerWidth <= 768);
14012
14236
  };
@@ -14017,9 +14241,44 @@ var useIsSmallScreen = () => {
14017
14241
  return isSmallScreen;
14018
14242
  };
14019
14243
 
14244
+ // src/hooks/useMobileTouch.ts
14245
+ import {
14246
+ useCallback as useCallback7,
14247
+ useRef as useRef12
14248
+ } from "react";
14249
+ var useMobileTouch = (onClick, options = { stopPropagation: true }) => {
14250
+ const lastInteractionRef = useRef12(0);
14251
+ const handleInteraction = useCallback7(
14252
+ (e) => {
14253
+ if (options.stopPropagation) {
14254
+ e.stopPropagation();
14255
+ }
14256
+ const now = Date.now();
14257
+ if (now - lastInteractionRef.current < 300) return;
14258
+ lastInteractionRef.current = now;
14259
+ onClick?.(e);
14260
+ },
14261
+ [onClick, options.stopPropagation]
14262
+ );
14263
+ const onTouchEnd = useCallback7(
14264
+ (e) => {
14265
+ e.preventDefault();
14266
+ handleInteraction(e);
14267
+ },
14268
+ [handleInteraction]
14269
+ );
14270
+ const style = { touchAction: "manipulation" };
14271
+ return {
14272
+ onClick: handleInteraction,
14273
+ onTouchEnd,
14274
+ style
14275
+ };
14276
+ };
14277
+
14020
14278
  // src/components/ToolbarOverlay.tsx
14021
14279
  import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
14022
14280
  var LayerButton = ({ name, selected, onClick }) => {
14281
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14023
14282
  return /* @__PURE__ */ jsxs14(
14024
14283
  "div",
14025
14284
  {
@@ -14034,7 +14293,8 @@ var LayerButton = ({ name, selected, onClick }) => {
14034
14293
  background-color: rgba(255, 255, 255, 0.1);
14035
14294
  }
14036
14295
  `,
14037
- onClick,
14296
+ ...touchHandlers,
14297
+ style: touchStyle,
14038
14298
  children: [
14039
14299
  /* @__PURE__ */ jsx20("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
14040
14300
  /* @__PURE__ */ jsx20(
@@ -14057,43 +14317,40 @@ var ToolbarButton = ({
14057
14317
  isSmallScreen,
14058
14318
  onClick,
14059
14319
  ...props
14060
- }) => /* @__PURE__ */ jsx20(
14061
- "div",
14062
- {
14063
- ...props,
14064
- onClick,
14065
- onTouchEnd: (e) => {
14066
- e.preventDefault();
14067
- e.stopPropagation();
14068
- if (onClick) {
14069
- onClick(e);
14070
- }
14071
- },
14072
- style: {
14073
- backgroundColor: "#1F1F1F",
14074
- border: "1px solid #666",
14075
- margin: 0,
14076
- padding: 4,
14077
- paddingLeft: isSmallScreen ? 8 : 6,
14078
- paddingRight: isSmallScreen ? 8 : 6,
14079
- borderRadius: 2,
14080
- color: "#eee",
14081
- cursor: "pointer",
14082
- fontSize: 12,
14083
- height: "fit-content",
14084
- touchAction: "manipulation",
14085
- userSelect: "none",
14086
- whiteSpace: "nowrap",
14087
- ...props.style
14088
- },
14089
- children
14090
- }
14091
- );
14320
+ }) => {
14321
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14322
+ return /* @__PURE__ */ jsx20(
14323
+ "div",
14324
+ {
14325
+ ...props,
14326
+ ...touchHandlers,
14327
+ style: {
14328
+ backgroundColor: "#1F1F1F",
14329
+ border: "1px solid #666",
14330
+ margin: 0,
14331
+ padding: 4,
14332
+ paddingLeft: isSmallScreen ? 8 : 6,
14333
+ paddingRight: isSmallScreen ? 8 : 6,
14334
+ borderRadius: 2,
14335
+ color: "#eee",
14336
+ cursor: "pointer",
14337
+ fontSize: 12,
14338
+ height: "fit-content",
14339
+ userSelect: "none",
14340
+ whiteSpace: "nowrap",
14341
+ ...touchStyle,
14342
+ ...props.style
14343
+ },
14344
+ children
14345
+ }
14346
+ );
14347
+ };
14092
14348
  var CheckboxMenuItem = ({
14093
14349
  label,
14094
14350
  checked,
14095
14351
  onClick
14096
14352
  }) => {
14353
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14097
14354
  return /* @__PURE__ */ jsxs14(
14098
14355
  "div",
14099
14356
  {
@@ -14111,15 +14368,8 @@ var CheckboxMenuItem = ({
14111
14368
  background-color: rgba(255, 255, 255, 0.1);
14112
14369
  }
14113
14370
  `,
14114
- onClick: (e) => {
14115
- e.stopPropagation();
14116
- onClick();
14117
- },
14118
- onTouchEnd: (e) => {
14119
- e.preventDefault();
14120
- e.stopPropagation();
14121
- onClick();
14122
- },
14371
+ ...touchHandlers,
14372
+ style: touchStyle,
14123
14373
  children: [
14124
14374
  /* @__PURE__ */ jsx20("input", { type: "checkbox", checked, onChange: () => {
14125
14375
  }, readOnly: true }),
@@ -14129,6 +14379,7 @@ var CheckboxMenuItem = ({
14129
14379
  );
14130
14380
  };
14131
14381
  var RadioMenuItem = ({ label, checked, onClick }) => {
14382
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
14132
14383
  return /* @__PURE__ */ jsxs14(
14133
14384
  "div",
14134
14385
  {
@@ -14146,15 +14397,8 @@ var RadioMenuItem = ({ label, checked, onClick }) => {
14146
14397
  background-color: rgba(255, 255, 255, 0.1);
14147
14398
  }
14148
14399
  `,
14149
- onClick: (e) => {
14150
- e.stopPropagation();
14151
- onClick();
14152
- },
14153
- onTouchEnd: (e) => {
14154
- e.preventDefault();
14155
- e.stopPropagation();
14156
- onClick();
14157
- },
14400
+ ...touchHandlers,
14401
+ style: touchStyle,
14158
14402
  children: [
14159
14403
  /* @__PURE__ */ jsx20("input", { type: "radio", checked, onChange: () => {
14160
14404
  }, readOnly: true }),
@@ -14163,6 +14407,39 @@ var RadioMenuItem = ({ label, checked, onClick }) => {
14163
14407
  }
14164
14408
  );
14165
14409
  };
14410
+ var CopyErrorButton = ({
14411
+ errorId,
14412
+ errorMessage,
14413
+ copiedErrorId,
14414
+ onCopy
14415
+ }) => {
14416
+ const { style: touchStyle, ...touchHandlers } = useMobileTouch(
14417
+ () => onCopy(errorMessage, errorId)
14418
+ );
14419
+ return /* @__PURE__ */ jsx20(
14420
+ "button",
14421
+ {
14422
+ type: "button",
14423
+ "aria-label": copiedErrorId === errorId ? "Error message copied" : "Copy error message",
14424
+ style: {
14425
+ position: "absolute",
14426
+ top: 12,
14427
+ right: 16,
14428
+ cursor: "pointer",
14429
+ color: "#888",
14430
+ fontSize: 16,
14431
+ background: "none",
14432
+ border: "none",
14433
+ padding: 0,
14434
+ display: "flex",
14435
+ alignItems: "center",
14436
+ ...touchStyle
14437
+ },
14438
+ ...touchHandlers,
14439
+ 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" }) })
14440
+ }
14441
+ );
14442
+ };
14166
14443
  var ToolbarOverlay = ({ children, elements }) => {
14167
14444
  const isSmallScreen = useIsSmallScreen();
14168
14445
  const {
@@ -14215,13 +14492,15 @@ var ToolbarOverlay = ({ children, elements }) => {
14215
14492
  setPcbGroupViewMode: s.setPcbGroupViewMode,
14216
14493
  setHoveredErrorId: s.setHoveredErrorId
14217
14494
  }));
14218
- const [isViewMenuOpen, setViewMenuOpen] = useState9(false);
14219
- const [isLayerMenuOpen, setLayerMenuOpen] = useState9(false);
14220
- const [isErrorsOpen, setErrorsOpen] = useState9(false);
14221
- const [measureToolArmed, setMeasureToolArmed] = useState9(false);
14222
- const errorElementsRef = useRef11(/* @__PURE__ */ new Map());
14223
- const arrowElementsRef = useRef11(/* @__PURE__ */ new Map());
14224
- useEffect15(() => {
14495
+ const [isViewMenuOpen, setViewMenuOpen] = useState10(false);
14496
+ const [isLayerMenuOpen, setLayerMenuOpen] = useState10(false);
14497
+ const [isErrorsOpen, setErrorsOpen] = useState10(false);
14498
+ const [measureToolArmed, setMeasureToolArmed] = useState10(false);
14499
+ const [copiedErrorId, setCopiedErrorId] = useState10(null);
14500
+ const [, copyToClipboard] = useCopyToClipboard_default();
14501
+ const errorElementsRef = useRef13(/* @__PURE__ */ new Map());
14502
+ const arrowElementsRef = useRef13(/* @__PURE__ */ new Map());
14503
+ useEffect16(() => {
14225
14504
  const arm = () => setMeasureToolArmed(true);
14226
14505
  const disarm = () => setMeasureToolArmed(false);
14227
14506
  window.addEventListener("arm-dimension-tool", arm);
@@ -14241,8 +14520,8 @@ var ToolbarOverlay = ({ children, elements }) => {
14241
14520
  "bottom"
14242
14521
  ];
14243
14522
  const processedLayers = availableLayers;
14244
- const hasRunInitialMouseCheck = useRef11(false);
14245
- const hotkeyBoundaryRef = useRef11(null);
14523
+ const hasRunInitialMouseCheck = useRef13(false);
14524
+ const hotkeyBoundaryRef = useRef13(null);
14246
14525
  const hotKeyCallbacks = {
14247
14526
  "1": availableLayers[0] ? () => selectLayer(availableLayers[0]) : () => {
14248
14527
  },
@@ -14287,25 +14566,25 @@ var ToolbarOverlay = ({ children, elements }) => {
14287
14566
  document.removeEventListener("mousemove", checkMousePosition);
14288
14567
  };
14289
14568
  }, [setIsMouseOverContainer]);
14290
- const handleMouseEnter = useCallback4(() => {
14569
+ const handleMouseEnter = useCallback8(() => {
14291
14570
  setIsMouseOverContainer(true);
14292
14571
  }, [setIsMouseOverContainer]);
14293
- const handleMouseMove = useCallback4(() => {
14572
+ const handleMouseMove = useCallback8(() => {
14294
14573
  if (!isMouseOverContainer) {
14295
14574
  setIsMouseOverContainer(true);
14296
14575
  }
14297
14576
  }, [isMouseOverContainer, setIsMouseOverContainer]);
14298
- const handleMouseLeave = useCallback4(() => {
14577
+ const handleMouseLeave = useCallback8(() => {
14299
14578
  setIsMouseOverContainer(false);
14300
14579
  setLayerMenuOpen(false);
14301
14580
  setViewMenuOpen(false);
14302
14581
  setErrorsOpen(false);
14303
14582
  setHoveredErrorId(null);
14304
14583
  }, [setIsMouseOverContainer, setHoveredErrorId]);
14305
- const handleLayerMenuToggle = useCallback4(() => {
14584
+ const handleLayerMenuToggle = useCallback8(() => {
14306
14585
  setLayerMenuOpen(!isLayerMenuOpen);
14307
14586
  }, [isLayerMenuOpen]);
14308
- const handleErrorsToggle = useCallback4(() => {
14587
+ const handleErrorsToggle = useCallback8(() => {
14309
14588
  const newErrorsOpen = !isErrorsOpen;
14310
14589
  setErrorsOpen(newErrorsOpen);
14311
14590
  if (newErrorsOpen) {
@@ -14315,20 +14594,20 @@ var ToolbarOverlay = ({ children, elements }) => {
14315
14594
  setHoveredErrorId(null);
14316
14595
  }
14317
14596
  }, [isErrorsOpen, setHoveredErrorId]);
14318
- const handleEditTraceToggle = useCallback4(() => {
14597
+ const handleEditTraceToggle = useCallback8(() => {
14319
14598
  setEditMode(editModes.in_draw_trace_mode ? "off" : "draw_trace");
14320
14599
  }, [editModes.in_draw_trace_mode, setEditMode]);
14321
- const handleMoveComponentToggle = useCallback4(() => {
14600
+ const handleMoveComponentToggle = useCallback8(() => {
14322
14601
  setEditMode(editModes.in_move_footprint_mode ? "off" : "move_footprint");
14323
14602
  }, [editModes.in_move_footprint_mode, setEditMode]);
14324
- const handleRatsNestToggle = useCallback4(() => {
14603
+ const handleRatsNestToggle = useCallback8(() => {
14325
14604
  setIsShowingRatsNest(!viewSettings.is_showing_rats_nest);
14326
14605
  }, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest]);
14327
- const handleMeasureToolClick = useCallback4(() => {
14606
+ const handleMeasureToolClick = useCallback8(() => {
14328
14607
  setMeasureToolArmed(true);
14329
14608
  window.dispatchEvent(new Event("arm-dimension-tool"));
14330
14609
  }, []);
14331
- const handleViewMenuToggle = useCallback4(() => {
14610
+ const handleViewMenuToggle = useCallback8(() => {
14332
14611
  const newViewMenuOpen = !isViewMenuOpen;
14333
14612
  setViewMenuOpen(newViewMenuOpen);
14334
14613
  if (newViewMenuOpen) {
@@ -14573,7 +14852,7 @@ var ToolbarOverlay = ({ children, elements }) => {
14573
14852
  ]
14574
14853
  }
14575
14854
  ),
14576
- /* @__PURE__ */ jsx20(
14855
+ /* @__PURE__ */ jsxs14(
14577
14856
  "div",
14578
14857
  {
14579
14858
  ref: (el) => {
@@ -14584,30 +14863,48 @@ var ToolbarOverlay = ({ children, elements }) => {
14584
14863
  display: "none",
14585
14864
  padding: "12px 16px",
14586
14865
  backgroundColor: "#1a1a1a",
14587
- borderTop: "1px solid #444"
14866
+ borderTop: "1px solid #444",
14867
+ position: "relative"
14588
14868
  },
14589
- children: /* @__PURE__ */ jsx20(
14590
- "div",
14591
- {
14592
- style: {
14593
- fontSize: isSmallScreen ? "11px" : "12px",
14594
- color: "#ccc",
14595
- lineHeight: 1.5,
14596
- wordWrap: "break-word",
14597
- overflowWrap: "break-word",
14598
- hyphens: "auto",
14599
- userSelect: "text"
14600
- },
14601
- onMouseDown: (event) => event.stopPropagation(),
14602
- onClick: (event) => event.stopPropagation(),
14603
- children: e.message
14604
- }
14605
- )
14869
+ children: [
14870
+ /* @__PURE__ */ jsx20(
14871
+ "div",
14872
+ {
14873
+ style: {
14874
+ fontSize: isSmallScreen ? "11px" : "12px",
14875
+ color: "#ccc",
14876
+ lineHeight: 1.5,
14877
+ wordWrap: "break-word",
14878
+ overflowWrap: "break-word",
14879
+ hyphens: "auto",
14880
+ userSelect: "text",
14881
+ paddingRight: 30
14882
+ // Space for the copy icon
14883
+ },
14884
+ onMouseDown: (event) => event.stopPropagation(),
14885
+ onClick: (event) => event.stopPropagation(),
14886
+ children: e.message
14887
+ }
14888
+ ),
14889
+ /* @__PURE__ */ jsx20(
14890
+ CopyErrorButton,
14891
+ {
14892
+ errorId,
14893
+ errorMessage: e.message,
14894
+ copiedErrorId,
14895
+ onCopy: (msg, id) => {
14896
+ copyToClipboard(msg);
14897
+ setCopiedErrorId(id);
14898
+ setTimeout(() => setCopiedErrorId(null), 2e3);
14899
+ }
14900
+ }
14901
+ )
14902
+ ]
14606
14903
  }
14607
14904
  )
14608
14905
  ]
14609
14906
  },
14610
- i
14907
+ errorId
14611
14908
  );
14612
14909
  })
14613
14910
  }
@@ -14822,11 +15119,11 @@ var CanvasElementsRenderer = (props) => {
14822
15119
  );
14823
15120
  return [primitivesWithoutInteractionMetadata2, connectivityMap2];
14824
15121
  }, [elementsToRender, props.elements]);
14825
- const [hoverState, setHoverState] = useState10({
15122
+ const [hoverState, setHoverState] = useState11({
14826
15123
  drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
14827
15124
  primitiveIdsInMousedOverNet: []
14828
15125
  });
14829
- const [hoveredComponentIds, setHoveredComponentIds] = useState10([]);
15126
+ const [hoveredComponentIds, setHoveredComponentIds] = useState11([]);
14830
15127
  const errorRelatedIds = useMemo7(() => {
14831
15128
  if (!hoveredErrorId) return [];
14832
15129
  const errorElements = elements.filter(
@@ -14857,7 +15154,7 @@ var CanvasElementsRenderer = (props) => {
14857
15154
  primitiveIdsInMousedOverNet: combinedPrimitiveIds
14858
15155
  });
14859
15156
  }, [primitivesWithoutInteractionMetadata, hoverState, errorRelatedIds]);
14860
- const onMouseOverPrimitives = useCallback5(
15157
+ const onMouseOverPrimitives = useCallback9(
14861
15158
  (primitivesHoveredOver) => {
14862
15159
  const primitiveIdsInMousedOverNet = [];
14863
15160
  for (const primitive of primitivesHoveredOver) {
@@ -15033,11 +15330,11 @@ var PCBViewer = ({
15033
15330
  clickToInteractEnabled = false,
15034
15331
  disablePcbGroups = false
15035
15332
  }) => {
15036
- const [isInteractionEnabled, setIsInteractionEnabled] = useState11(
15333
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState12(
15037
15334
  !clickToInteractEnabled
15038
15335
  );
15039
15336
  const [ref, refDimensions] = useMeasure_default();
15040
- const [transform, setTransformInternal] = useState11(defaultTransform);
15337
+ const [transform, setTransformInternal] = useState12(defaultTransform);
15041
15338
  const {
15042
15339
  ref: transformRef,
15043
15340
  setTransform,
@@ -15047,10 +15344,10 @@ var PCBViewer = ({
15047
15344
  onSetTransform: setTransformInternal,
15048
15345
  enabled: isInteractionEnabled
15049
15346
  });
15050
- let [editEvents, setEditEvents] = useState11([]);
15347
+ let [editEvents, setEditEvents] = useState12([]);
15051
15348
  editEvents = editEventsProp ?? editEvents;
15052
- const initialRenderCompleted = useRef12(false);
15053
- const touchStartRef = useRef12(null);
15349
+ const initialRenderCompleted = useRef14(false);
15350
+ const touchStartRef = useRef14(null);
15054
15351
  const circuitJsonKey = useMemo8(
15055
15352
  () => calculateCircuitJsonKey(circuitJson),
15056
15353
  [circuitJson]
@@ -15076,7 +15373,7 @@ var PCBViewer = ({
15076
15373
  setTransform(targetTransform);
15077
15374
  return;
15078
15375
  };
15079
- useEffect16(() => {
15376
+ useEffect17(() => {
15080
15377
  if (!refDimensions?.width) return;
15081
15378
  if (!circuitJson) return;
15082
15379
  if (circuitJson.length === 0) return;
@@ -15085,7 +15382,7 @@ var PCBViewer = ({
15085
15382
  initialRenderCompleted.current = true;
15086
15383
  }
15087
15384
  }, [circuitJson, refDimensions]);
15088
- useEffect16(() => {
15385
+ useEffect17(() => {
15089
15386
  if (initialRenderCompleted.current === true) {
15090
15387
  resetTransform();
15091
15388
  }