@tscircuit/pcb-viewer 1.11.394 → 1.11.396

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
@@ -4,7 +4,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
8
14
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
15
  };
10
16
  var __copyProps = (to, from, except, desc) => {
@@ -918,6 +924,263 @@ var require_svgson_umd = __commonJS({
918
924
  }
919
925
  });
920
926
 
927
+ // node_modules/react-dom/cjs/react-dom.development.js
928
+ var require_react_dom_development = __commonJS({
929
+ "node_modules/react-dom/cjs/react-dom.development.js"(exports) {
930
+ "use strict";
931
+ (function() {
932
+ function noop2() {
933
+ }
934
+ function testStringCoercion(value) {
935
+ return "" + value;
936
+ }
937
+ function createPortal$1(children, containerInfo, implementation) {
938
+ var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
939
+ try {
940
+ testStringCoercion(key);
941
+ var JSCompiler_inline_result = false;
942
+ } catch (e) {
943
+ JSCompiler_inline_result = true;
944
+ }
945
+ JSCompiler_inline_result && (console.error(
946
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
947
+ "function" === typeof Symbol && Symbol.toStringTag && key[Symbol.toStringTag] || key.constructor.name || "Object"
948
+ ), testStringCoercion(key));
949
+ return {
950
+ $$typeof: REACT_PORTAL_TYPE,
951
+ key: null == key ? null : "" + key,
952
+ children,
953
+ containerInfo,
954
+ implementation
955
+ };
956
+ }
957
+ function getCrossOriginStringAs(as, input) {
958
+ if ("font" === as) return "";
959
+ if ("string" === typeof input)
960
+ return "use-credentials" === input ? input : "";
961
+ }
962
+ function getValueDescriptorExpectingObjectForWarning(thing) {
963
+ return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : 'something with type "' + typeof thing + '"';
964
+ }
965
+ function getValueDescriptorExpectingEnumForWarning(thing) {
966
+ return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "string" === typeof thing ? JSON.stringify(thing) : "number" === typeof thing ? "`" + thing + "`" : 'something with type "' + typeof thing + '"';
967
+ }
968
+ function resolveDispatcher() {
969
+ var dispatcher = ReactSharedInternals.H;
970
+ null === dispatcher && console.error(
971
+ "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem."
972
+ );
973
+ return dispatcher;
974
+ }
975
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
976
+ var React4 = __require("react"), Internals = {
977
+ d: {
978
+ f: noop2,
979
+ r: function() {
980
+ throw Error(
981
+ "Invalid form element. requestFormReset must be passed a form that was rendered by React."
982
+ );
983
+ },
984
+ D: noop2,
985
+ C: noop2,
986
+ L: noop2,
987
+ m: noop2,
988
+ X: noop2,
989
+ S: noop2,
990
+ M: noop2
991
+ },
992
+ p: 0,
993
+ findDOMNode: null
994
+ }, REACT_PORTAL_TYPE = Symbol.for("react.portal"), ReactSharedInternals = React4.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
995
+ "function" === typeof Map && null != Map.prototype && "function" === typeof Map.prototype.forEach && "function" === typeof Set && null != Set.prototype && "function" === typeof Set.prototype.clear && "function" === typeof Set.prototype.forEach || console.error(
996
+ "React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"
997
+ );
998
+ exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals;
999
+ exports.createPortal = function(children, container) {
1000
+ var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
1001
+ if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType)
1002
+ throw Error("Target container is not a DOM element.");
1003
+ return createPortal$1(children, container, null, key);
1004
+ };
1005
+ exports.flushSync = function(fn) {
1006
+ var previousTransition = ReactSharedInternals.T, previousUpdatePriority = Internals.p;
1007
+ try {
1008
+ if (ReactSharedInternals.T = null, Internals.p = 2, fn)
1009
+ return fn();
1010
+ } finally {
1011
+ ReactSharedInternals.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f() && console.error(
1012
+ "flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task."
1013
+ );
1014
+ }
1015
+ };
1016
+ exports.preconnect = function(href, options) {
1017
+ "string" === typeof href && href ? null != options && "object" !== typeof options ? console.error(
1018
+ "ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.",
1019
+ getValueDescriptorExpectingEnumForWarning(options)
1020
+ ) : null != options && "string" !== typeof options.crossOrigin && console.error(
1021
+ "ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.",
1022
+ getValueDescriptorExpectingObjectForWarning(options.crossOrigin)
1023
+ ) : console.error(
1024
+ "ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
1025
+ getValueDescriptorExpectingObjectForWarning(href)
1026
+ );
1027
+ "string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals.d.C(href, options));
1028
+ };
1029
+ exports.prefetchDNS = function(href) {
1030
+ if ("string" !== typeof href || !href)
1031
+ console.error(
1032
+ "ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
1033
+ getValueDescriptorExpectingObjectForWarning(href)
1034
+ );
1035
+ else if (1 < arguments.length) {
1036
+ var options = arguments[1];
1037
+ "object" === typeof options && options.hasOwnProperty("crossOrigin") ? console.error(
1038
+ "ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.",
1039
+ getValueDescriptorExpectingEnumForWarning(options)
1040
+ ) : console.error(
1041
+ "ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.",
1042
+ getValueDescriptorExpectingEnumForWarning(options)
1043
+ );
1044
+ }
1045
+ "string" === typeof href && Internals.d.D(href);
1046
+ };
1047
+ exports.preinit = function(href, options) {
1048
+ "string" === typeof href && href ? null == options || "object" !== typeof options ? console.error(
1049
+ "ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.",
1050
+ getValueDescriptorExpectingEnumForWarning(options)
1051
+ ) : "style" !== options.as && "script" !== options.as && console.error(
1052
+ 'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are "style" and "script".',
1053
+ getValueDescriptorExpectingEnumForWarning(options.as)
1054
+ ) : console.error(
1055
+ "ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
1056
+ getValueDescriptorExpectingObjectForWarning(href)
1057
+ );
1058
+ if ("string" === typeof href && options && "string" === typeof options.as) {
1059
+ var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
1060
+ "style" === as ? Internals.d.S(
1061
+ href,
1062
+ "string" === typeof options.precedence ? options.precedence : void 0,
1063
+ {
1064
+ crossOrigin,
1065
+ integrity,
1066
+ fetchPriority
1067
+ }
1068
+ ) : "script" === as && Internals.d.X(href, {
1069
+ crossOrigin,
1070
+ integrity,
1071
+ fetchPriority,
1072
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
1073
+ });
1074
+ }
1075
+ };
1076
+ exports.preinitModule = function(href, options) {
1077
+ var encountered = "";
1078
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
1079
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "script" !== options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingEnumForWarning(options.as) + ".");
1080
+ if (encountered)
1081
+ console.error(
1082
+ "ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s",
1083
+ encountered
1084
+ );
1085
+ else
1086
+ switch (encountered = options && "string" === typeof options.as ? options.as : "script", encountered) {
1087
+ case "script":
1088
+ break;
1089
+ default:
1090
+ encountered = getValueDescriptorExpectingEnumForWarning(encountered), console.error(
1091
+ 'ReactDOM.preinitModule(): Currently the only supported "as" type for this function is "script" but received "%s" instead. This warning was generated for `href` "%s". In the future other module types will be supported, aligning with the import-attributes proposal. Learn more here: (https://github.com/tc39/proposal-import-attributes)',
1092
+ encountered,
1093
+ href
1094
+ );
1095
+ }
1096
+ if ("string" === typeof href)
1097
+ if ("object" === typeof options && null !== options) {
1098
+ if (null == options.as || "script" === options.as)
1099
+ encountered = getCrossOriginStringAs(
1100
+ options.as,
1101
+ options.crossOrigin
1102
+ ), Internals.d.M(href, {
1103
+ crossOrigin: encountered,
1104
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
1105
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
1106
+ });
1107
+ } else null == options && Internals.d.M(href);
1108
+ };
1109
+ exports.preload = function(href, options) {
1110
+ var encountered = "";
1111
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
1112
+ null == options || "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : "string" === typeof options.as && options.as || (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
1113
+ encountered && console.error(
1114
+ 'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel="preload" as="..." />` tag.%s',
1115
+ encountered
1116
+ );
1117
+ if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
1118
+ encountered = options.as;
1119
+ var crossOrigin = getCrossOriginStringAs(
1120
+ encountered,
1121
+ options.crossOrigin
1122
+ );
1123
+ Internals.d.L(href, encountered, {
1124
+ crossOrigin,
1125
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
1126
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0,
1127
+ type: "string" === typeof options.type ? options.type : void 0,
1128
+ fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
1129
+ referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
1130
+ imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
1131
+ imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
1132
+ media: "string" === typeof options.media ? options.media : void 0
1133
+ });
1134
+ }
1135
+ };
1136
+ exports.preloadModule = function(href, options) {
1137
+ var encountered = "";
1138
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
1139
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
1140
+ encountered && console.error(
1141
+ 'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel="modulepreload" as="..." />` tag.%s',
1142
+ encountered
1143
+ );
1144
+ "string" === typeof href && (options ? (encountered = getCrossOriginStringAs(
1145
+ options.as,
1146
+ options.crossOrigin
1147
+ ), Internals.d.m(href, {
1148
+ as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
1149
+ crossOrigin: encountered,
1150
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0
1151
+ })) : Internals.d.m(href));
1152
+ };
1153
+ exports.requestFormReset = function(form) {
1154
+ Internals.d.r(form);
1155
+ };
1156
+ exports.unstable_batchedUpdates = function(fn, a) {
1157
+ return fn(a);
1158
+ };
1159
+ exports.useFormState = function(action, initialState, permalink) {
1160
+ return resolveDispatcher().useFormState(action, initialState, permalink);
1161
+ };
1162
+ exports.useFormStatus = function() {
1163
+ return resolveDispatcher().useHostTransitionStatus();
1164
+ };
1165
+ exports.version = "19.1.0";
1166
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
1167
+ })();
1168
+ }
1169
+ });
1170
+
1171
+ // node_modules/react-dom/index.js
1172
+ var require_react_dom = __commonJS({
1173
+ "node_modules/react-dom/index.js"(exports, module) {
1174
+ "use strict";
1175
+ if (false) {
1176
+ checkDCE();
1177
+ module.exports = null;
1178
+ } else {
1179
+ module.exports = require_react_dom_development();
1180
+ }
1181
+ }
1182
+ });
1183
+
921
1184
  // src/PCBViewer.tsx
922
1185
  import { applyEditEvents } from "@tscircuit/core";
923
1186
 
@@ -2233,6 +2496,8 @@ var setStoredString = (key, value) => {
2233
2496
  var DEFAULT_PCB_GROUP_VIEW_MODE = true ? "named_only" : "all";
2234
2497
  var createStore = (initialState = {}, disablePcbGroups = false) => createZustandStore(
2235
2498
  (set) => ({
2499
+ hidden_layer_opacity: 0.4,
2500
+ setHiddenLayerOpacity: (opacity) => set({ hidden_layer_opacity: Math.max(0, Math.min(1, opacity)) }),
2236
2501
  selected_layer: "top",
2237
2502
  pcb_viewer_id: `pcb_viewer_${Math.random().toString().slice(2, 10)}`,
2238
2503
  in_edit_mode: false,
@@ -2378,7 +2643,7 @@ var ToastContainer = () => {
2378
2643
  };
2379
2644
 
2380
2645
  // src/PCBViewer.tsx
2381
- import { useCallback as useCallback12, useEffect as useEffect18, useMemo as useMemo9, useRef as useRef15, useState as useState12 } from "react";
2646
+ import { useCallback as useCallback12, useEffect as useEffect19, useMemo as useMemo10, useRef as useRef16, useState as useState13 } from "react";
2382
2647
 
2383
2648
  // node_modules/react-use/esm/useMountedState.js
2384
2649
  import { useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
@@ -4182,7 +4447,7 @@ var animateTransform = ({
4182
4447
  };
4183
4448
 
4184
4449
  // src/components/CanvasElementsRenderer.tsx
4185
- import { useCallback as useCallback11, useEffect as useEffect17, useMemo as useMemo8, useRef as useRef14, useState as useState11 } from "react";
4450
+ import { useCallback as useCallback11, useEffect as useEffect18, useMemo as useMemo9, useRef as useRef15, useState as useState12 } from "react";
4186
4451
 
4187
4452
  // src/lib/Drawer.ts
4188
4453
  import colorParser from "color";
@@ -4516,6 +4781,7 @@ var Drawer = class {
4516
4781
  aperture;
4517
4782
  transform;
4518
4783
  foregroundLayer = "top";
4784
+ hiddenLayerOpacity = 0.4;
4519
4785
  lastPoint;
4520
4786
  constructor(canvasLayerMap) {
4521
4787
  this.canvasLayerMap = canvasLayerMap;
@@ -4790,11 +5056,19 @@ var Drawer = class {
4790
5056
  }
4791
5057
  return ctx;
4792
5058
  }
5059
+ getLayerOpacity(layer) {
5060
+ const side = this.foregroundLayer;
5061
+ const isSelectedSideDetail = (side === "top" || side === "bottom") && (layer.startsWith(`${side}_`) || layer.endsWith(`_${side}`));
5062
+ const isSharedLayer = ["board", "drill", "edge_cuts", "other"].includes(
5063
+ layer
5064
+ );
5065
+ return layer === side || isSelectedSideDetail || isSharedLayer ? 1 : this.hiddenLayerOpacity;
5066
+ }
4793
5067
  /**
4794
5068
  * Iterate over each canvas and set the z index based on the layer order, but
4795
5069
  * always render the foreground layer on top.
4796
5070
  *
4797
- * Also: Set the opacity of every non-foreground layer to 0.5
5071
+ * Fade inactive layers using the configured hidden-layer opacity.
4798
5072
  */
4799
5073
  orderAndFadeLayers() {
4800
5074
  const { canvasLayerMap, foregroundLayer } = this;
@@ -4811,18 +5085,6 @@ var Drawer = class {
4811
5085
  const associatedNotes = foregroundLayer === "top" ? "top_notes" : foregroundLayer === "bottom" ? "bottom_notes" : void 0;
4812
5086
  const associatedFabrication = foregroundLayer === "top" ? "top_fabrication" : foregroundLayer === "bottom" ? "bottom_fabrication" : void 0;
4813
5087
  const associatedCourtyard = foregroundLayer === "top" ? "top_courtyard" : foregroundLayer === "bottom" ? "bottom_courtyard" : void 0;
4814
- const opaqueLayers = /* @__PURE__ */ new Set([
4815
- foregroundLayer,
4816
- "drill",
4817
- "edge_cuts",
4818
- "other",
4819
- "board",
4820
- ...associatedSoldermask ? [associatedSoldermask] : [],
4821
- ...associatedSilkscreen ? [associatedSilkscreen] : [],
4822
- ...associatedNotes ? [associatedNotes] : [],
4823
- ...associatedFabrication ? [associatedFabrication] : [],
4824
- ...associatedCourtyard ? [associatedCourtyard] : []
4825
- ]);
4826
5088
  const layersToShiftToTop = [
4827
5089
  foregroundLayer,
4828
5090
  "edge_cuts",
@@ -4847,8 +5109,12 @@ var Drawer = class {
4847
5109
  const canvas = canvasLayerMap[layer];
4848
5110
  if (!canvas) return;
4849
5111
  canvas.style.zIndex = `${zIndexMap.topLayer - (order.length - i)}`;
4850
- canvas.style.opacity = opaqueLayers.has(layer) ? "1" : "0.5";
4851
5112
  });
5113
+ for (const [layer, canvas] of Object.entries(canvasLayerMap)) {
5114
+ const opacity = this.getLayerOpacity(layer);
5115
+ canvas.style.opacity = String(opacity);
5116
+ canvas.style.display = opacity === 0 ? "none" : "";
5117
+ }
4852
5118
  }
4853
5119
  applyAperture() {
4854
5120
  const { transform, aperture } = this;
@@ -6112,6 +6378,7 @@ var CanvasPrimitiveRenderer = ({
6112
6378
  height = 500
6113
6379
  }) => {
6114
6380
  const canvasRefs = useRef3({});
6381
+ const hiddenLayerOpacity = useGlobalStore((s) => s.hidden_layer_opacity);
6115
6382
  const selectedLayer = useGlobalStore((s) => s.selected_layer);
6116
6383
  const isShowingCopperPours = useGlobalStore((s) => s.is_showing_copper_pours);
6117
6384
  const isShowingSolderMask = useGlobalStore((s) => s.is_showing_solder_mask);
@@ -6135,16 +6402,27 @@ var CanvasPrimitiveRenderer = ({
6135
6402
  if (transform) drawer.transform = transform;
6136
6403
  drawer.clear();
6137
6404
  drawer.foregroundLayer = selectedLayer;
6405
+ drawer.hiddenLayerOpacity = hiddenLayerOpacity;
6406
+ const visibleCanvasRefs = Object.fromEntries(
6407
+ Object.entries(availableCanvasRefs).filter(
6408
+ ([layer]) => drawer.getLayerOpacity(layer) > 0
6409
+ )
6410
+ );
6138
6411
  const filteredPrimitives = getPrimitivesForDrawer({
6139
6412
  primitives,
6140
6413
  isShowingSolderMask,
6141
6414
  isShowingSilkscreen,
6142
6415
  isShowingFabricationNotes
6143
6416
  });
6144
- drawPrimitives(drawer, filteredPrimitives);
6417
+ drawPrimitives(
6418
+ drawer,
6419
+ filteredPrimitives.filter(
6420
+ (p) => drawer.getLayerOpacity(p.layer ?? "other") > 0
6421
+ )
6422
+ );
6145
6423
  if (transform) {
6146
6424
  const copperLayers = getCopperLayerRefsFromElements(elements).map((layer) => ({
6147
- canvas: canvasRefs.current[layer],
6425
+ canvas: visibleCanvasRefs[layer],
6148
6426
  layer,
6149
6427
  copperLayer: getCopperRenderLayer(layer)
6150
6428
  }));
@@ -6214,7 +6492,7 @@ var CanvasPrimitiveRenderer = ({
6214
6492
  const soldermaskLayer = selectedLayer === "bottom" ? "bottom" : "top";
6215
6493
  const drawSoldermaskTop = soldermaskLayer === "top";
6216
6494
  const drawSoldermaskBottom = soldermaskLayer === "bottom";
6217
- const topSoldermaskCanvas = canvasRefs.current.soldermask_top;
6495
+ const topSoldermaskCanvas = visibleCanvasRefs.soldermask_top;
6218
6496
  if (topSoldermaskCanvas && soldermaskLayer === "top") {
6219
6497
  drawSoldermaskElementsForLayer({
6220
6498
  canvas: topSoldermaskCanvas,
@@ -6226,7 +6504,7 @@ var CanvasPrimitiveRenderer = ({
6226
6504
  primitives
6227
6505
  });
6228
6506
  }
6229
- const bottomSoldermaskCanvas = canvasRefs.current.soldermask_bottom;
6507
+ const bottomSoldermaskCanvas = visibleCanvasRefs.soldermask_bottom;
6230
6508
  if (bottomSoldermaskCanvas && soldermaskLayer === "bottom") {
6231
6509
  drawSoldermaskElementsForLayer({
6232
6510
  canvas: bottomSoldermaskCanvas,
@@ -6239,7 +6517,7 @@ var CanvasPrimitiveRenderer = ({
6239
6517
  });
6240
6518
  }
6241
6519
  }
6242
- const drillCanvas = canvasRefs.current.drill;
6520
+ const drillCanvas = visibleCanvasRefs.drill;
6243
6521
  if (drillCanvas) {
6244
6522
  drawPcbHoleElementsForLayer({
6245
6523
  canvas: drillCanvas,
@@ -6249,7 +6527,7 @@ var CanvasPrimitiveRenderer = ({
6249
6527
  });
6250
6528
  }
6251
6529
  if (isShowingSilkscreen) {
6252
- const topSilkscreenCanvas = canvasRefs.current.top_silkscreen;
6530
+ const topSilkscreenCanvas = visibleCanvasRefs.top_silkscreen;
6253
6531
  if (topSilkscreenCanvas) {
6254
6532
  drawSilkscreenElementsForLayer({
6255
6533
  canvas: topSilkscreenCanvas,
@@ -6258,7 +6536,7 @@ var CanvasPrimitiveRenderer = ({
6258
6536
  realToCanvasMat: transform
6259
6537
  });
6260
6538
  }
6261
- const bottomSilkscreenCanvas = canvasRefs.current.bottom_silkscreen;
6539
+ const bottomSilkscreenCanvas = visibleCanvasRefs.bottom_silkscreen;
6262
6540
  if (bottomSilkscreenCanvas) {
6263
6541
  drawSilkscreenElementsForLayer({
6264
6542
  canvas: bottomSilkscreenCanvas,
@@ -6269,7 +6547,7 @@ var CanvasPrimitiveRenderer = ({
6269
6547
  }
6270
6548
  }
6271
6549
  if (isShowingFabricationNotes) {
6272
- const topFabCanvas = canvasRefs.current.top_fabrication;
6550
+ const topFabCanvas = visibleCanvasRefs.top_fabrication;
6273
6551
  if (topFabCanvas) {
6274
6552
  drawFabricationNoteElementsForLayer({
6275
6553
  canvas: topFabCanvas,
@@ -6278,7 +6556,7 @@ var CanvasPrimitiveRenderer = ({
6278
6556
  realToCanvasMat: transform
6279
6557
  });
6280
6558
  }
6281
- const bottomFabCanvas = canvasRefs.current.bottom_fabrication;
6559
+ const bottomFabCanvas = visibleCanvasRefs.bottom_fabrication;
6282
6560
  if (bottomFabCanvas) {
6283
6561
  drawFabricationNoteElementsForLayer({
6284
6562
  canvas: bottomFabCanvas,
@@ -6289,7 +6567,7 @@ var CanvasPrimitiveRenderer = ({
6289
6567
  }
6290
6568
  }
6291
6569
  if (isShowingPcbNotes) {
6292
- const bottomNotesCanvas = canvasRefs.current.bottom_notes;
6570
+ const bottomNotesCanvas = visibleCanvasRefs.bottom_notes;
6293
6571
  if (bottomNotesCanvas) {
6294
6572
  drawPcbNoteElementsForLayer({
6295
6573
  canvas: bottomNotesCanvas,
@@ -6298,7 +6576,7 @@ var CanvasPrimitiveRenderer = ({
6298
6576
  realToCanvasMat: transform
6299
6577
  });
6300
6578
  }
6301
- const topNotesCanvas = canvasRefs.current.top_notes;
6579
+ const topNotesCanvas = visibleCanvasRefs.top_notes;
6302
6580
  if (topNotesCanvas) {
6303
6581
  drawPcbNoteElementsForLayer({
6304
6582
  canvas: topNotesCanvas,
@@ -6309,7 +6587,7 @@ var CanvasPrimitiveRenderer = ({
6309
6587
  }
6310
6588
  }
6311
6589
  if (isShowingCourtyards) {
6312
- const topCourtyardCanvas = canvasRefs.current.top_courtyard;
6590
+ const topCourtyardCanvas = visibleCanvasRefs.top_courtyard;
6313
6591
  if (topCourtyardCanvas) {
6314
6592
  drawCourtyardElementsForLayer({
6315
6593
  canvas: topCourtyardCanvas,
@@ -6318,7 +6596,7 @@ var CanvasPrimitiveRenderer = ({
6318
6596
  realToCanvasMat: transform
6319
6597
  });
6320
6598
  }
6321
- const bottomCourtyardCanvas = canvasRefs.current.bottom_courtyard;
6599
+ const bottomCourtyardCanvas = visibleCanvasRefs.bottom_courtyard;
6322
6600
  if (bottomCourtyardCanvas) {
6323
6601
  drawCourtyardElementsForLayer({
6324
6602
  canvas: bottomCourtyardCanvas,
@@ -6328,7 +6606,7 @@ var CanvasPrimitiveRenderer = ({
6328
6606
  });
6329
6607
  }
6330
6608
  }
6331
- const boardCanvas = canvasRefs.current.board;
6609
+ const boardCanvas = visibleCanvasRefs.board;
6332
6610
  if (boardCanvas) {
6333
6611
  drawPcbPanelElements({
6334
6612
  canvas: boardCanvas,
@@ -6345,7 +6623,7 @@ var CanvasPrimitiveRenderer = ({
6345
6623
  drawSoldermask: isShowingSolderMask
6346
6624
  });
6347
6625
  }
6348
- const edgeCutsCanvas = canvasRefs.current.edge_cuts;
6626
+ const edgeCutsCanvas = visibleCanvasRefs.edge_cuts;
6349
6627
  if (edgeCutsCanvas) {
6350
6628
  drawPcbCutoutElementsForLayer({
6351
6629
  canvas: edgeCutsCanvas,
@@ -6370,6 +6648,7 @@ var CanvasPrimitiveRenderer = ({
6370
6648
  elements,
6371
6649
  transform,
6372
6650
  selectedLayer,
6651
+ hiddenLayerOpacity,
6373
6652
  isShowingCopperPours,
6374
6653
  isShowingSolderMask,
6375
6654
  isShowingFabricationNotes,
@@ -7299,7 +7578,7 @@ var DebugGraphicsOverlay = ({
7299
7578
  };
7300
7579
 
7301
7580
  // src/components/DimensionOverlay.tsx
7302
- import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef5, useState as useState4 } from "react";
7581
+ import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef5, useState as useState4 } from "react";
7303
7582
  import { applyToPoint as applyToPoint10, identity as identity3, inverse as inverse3 } from "transformation-matrix";
7304
7583
 
7305
7584
  // src/lib/util/get-primitive-bounding-box.ts
@@ -7674,10 +7953,55 @@ var getPrimitiveSnapPoints = (primitive) => {
7674
7953
  }
7675
7954
  };
7676
7955
 
7956
+ // src/components/DimensionSnapGuides.tsx
7957
+ import { memo, useMemo as useMemo4 } from "react";
7958
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
7959
+ var markerPath = ({ screenPoint: { x, y } }) => `M${x - 2.5},${y - 2.5}l5,5m0,-5l-5,5`;
7960
+ var DimensionSnapGuides = memo(function DimensionSnapGuides2({
7961
+ points,
7962
+ startId,
7963
+ endId
7964
+ }) {
7965
+ const { path, pointsById } = useMemo4(
7966
+ () => ({
7967
+ path: points.map(markerPath).join(""),
7968
+ pointsById: new Map(points.map((point) => [point.id, point]))
7969
+ }),
7970
+ [points]
7971
+ );
7972
+ const activePath = [.../* @__PURE__ */ new Set([startId, endId])].flatMap((id) => {
7973
+ const point = id === null ? void 0 : pointsById.get(id);
7974
+ return point ? [markerPath(point)] : [];
7975
+ }).join("");
7976
+ return /* @__PURE__ */ jsxs3(
7977
+ "svg",
7978
+ {
7979
+ "aria-hidden": "true",
7980
+ width: "100%",
7981
+ height: "100%",
7982
+ style: {
7983
+ position: "absolute",
7984
+ left: 0,
7985
+ top: 0,
7986
+ overflow: "visible",
7987
+ pointerEvents: "none",
7988
+ zIndex: zIndexMap.dimensionOverlay
7989
+ },
7990
+ fill: "none",
7991
+ strokeWidth: 1,
7992
+ children: [
7993
+ /* @__PURE__ */ jsx5("path", { d: path, stroke: "white" }),
7994
+ /* @__PURE__ */ jsx5("path", { d: activePath, stroke: "#66ccff" })
7995
+ ]
7996
+ }
7997
+ );
7998
+ });
7999
+
7677
8000
  // src/components/DimensionOverlay.tsx
7678
- import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
8001
+ import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
7679
8002
  var SNAP_THRESHOLD_PX = 16;
7680
- var SNAP_MARKER_SIZE = 5;
8003
+ var EMPTY_PRIMITIVES = [];
8004
+ var DEFAULT_TRANSFORM = identity3();
7681
8005
  var shouldExcludePrimitiveFromSnapping = (primitive) => {
7682
8006
  if (primitive.pcb_drawing_type === "text") return true;
7683
8007
  const element = primitive._element;
@@ -7698,11 +8022,11 @@ var DimensionOverlay = ({
7698
8022
  children,
7699
8023
  transform,
7700
8024
  focusOnHover = false,
7701
- primitives = [],
8025
+ primitives = EMPTY_PRIMITIVES,
7702
8026
  onBoundsSelected,
7703
8027
  cancelPanDrag
7704
8028
  }) => {
7705
- if (!transform) transform = identity3();
8029
+ if (!transform) transform = DEFAULT_TRANSFORM;
7706
8030
  const [dimensionToolVisible, setDimensionToolVisible] = useState4(false);
7707
8031
  const [dimensionToolStretching, setDimensionToolStretching] = useState4(false);
7708
8032
  const [measureToolArmed, setMeasureToolArmed] = useState4(false);
@@ -7734,7 +8058,7 @@ var DimensionOverlay = ({
7734
8058
  const containerRef = useRef5(null);
7735
8059
  const container = containerRef.current;
7736
8060
  const containerBounds = container?.getBoundingClientRect();
7737
- const elementBoundingBoxes = useMemo4(() => {
8061
+ const elementBoundingBoxes = useMemo5(() => {
7738
8062
  const boundingBoxes = /* @__PURE__ */ new Map();
7739
8063
  for (const primitive of primitives) {
7740
8064
  if (!primitive._element) continue;
@@ -7752,7 +8076,7 @@ var DimensionOverlay = ({
7752
8076
  }
7753
8077
  return boundingBoxes;
7754
8078
  }, [primitives]);
7755
- const primitiveSnappingPoints = useMemo4(() => {
8079
+ const primitiveSnappingPoints = useMemo5(() => {
7756
8080
  const snapPoints = [];
7757
8081
  for (const primitive of primitives) {
7758
8082
  if (!primitive._element) continue;
@@ -7769,7 +8093,7 @@ var DimensionOverlay = ({
7769
8093
  }
7770
8094
  return snapPoints;
7771
8095
  }, [primitives]);
7772
- const snappingPoints = useMemo4(() => {
8096
+ const snappingPoints = useMemo5(() => {
7773
8097
  const points = [];
7774
8098
  elementBoundingBoxes.forEach((bounds, element) => {
7775
8099
  if (!bounds) return;
@@ -7804,7 +8128,7 @@ var DimensionOverlay = ({
7804
8128
  });
7805
8129
  return points;
7806
8130
  }, [elementBoundingBoxes, primitiveSnappingPoints]);
7807
- const snappingPointsWithScreen = useMemo4(() => {
8131
+ const snappingPointsWithScreen = useMemo5(() => {
7808
8132
  return snappingPoints.map((snap, index) => ({
7809
8133
  ...snap,
7810
8134
  id: `${index}-${snap.anchor}`,
@@ -7956,7 +8280,7 @@ var DimensionOverlay = ({
7956
8280
  flipX: arrowScreenBounds.flipX,
7957
8281
  flipY: arrowScreenBounds.flipY
7958
8282
  });
7959
- return /* @__PURE__ */ jsxs3(
8283
+ return /* @__PURE__ */ jsxs4(
7960
8284
  "div",
7961
8285
  {
7962
8286
  ref: containerRef,
@@ -8041,8 +8365,8 @@ var DimensionOverlay = ({
8041
8365
  },
8042
8366
  children: [
8043
8367
  children,
8044
- boundsToolVisible && /* @__PURE__ */ jsxs3(Fragment, { children: [
8045
- /* @__PURE__ */ jsx5(
8368
+ boundsToolVisible && /* @__PURE__ */ jsxs4(Fragment, { children: [
8369
+ /* @__PURE__ */ jsx6(
8046
8370
  "svg",
8047
8371
  {
8048
8372
  style: {
@@ -8055,7 +8379,7 @@ var DimensionOverlay = ({
8055
8379
  },
8056
8380
  width: containerBounds.width,
8057
8381
  height: containerBounds.height,
8058
- children: /* @__PURE__ */ jsx5(
8382
+ children: /* @__PURE__ */ jsx6(
8059
8383
  "rect",
8060
8384
  {
8061
8385
  x: boundsScreenRect.left,
@@ -8070,7 +8394,7 @@ var DimensionOverlay = ({
8070
8394
  )
8071
8395
  }
8072
8396
  ),
8073
- /* @__PURE__ */ jsxs3(
8397
+ /* @__PURE__ */ jsxs4(
8074
8398
  "div",
8075
8399
  {
8076
8400
  style: {
@@ -8091,7 +8415,7 @@ var DimensionOverlay = ({
8091
8415
  ", minY:",
8092
8416
  " ",
8093
8417
  selectedBounds.minY.toFixed(2),
8094
- /* @__PURE__ */ jsx5("br", {}),
8418
+ /* @__PURE__ */ jsx6("br", {}),
8095
8419
  "maxX: ",
8096
8420
  selectedBounds.maxX.toFixed(2),
8097
8421
  ", maxY:",
@@ -8101,8 +8425,8 @@ var DimensionOverlay = ({
8101
8425
  }
8102
8426
  )
8103
8427
  ] }),
8104
- dimensionToolVisible && /* @__PURE__ */ jsxs3(Fragment, { children: [
8105
- diagonalLabel.show && /* @__PURE__ */ jsx5(
8428
+ dimensionToolVisible && /* @__PURE__ */ jsxs4(Fragment, { children: [
8429
+ diagonalLabel.show && /* @__PURE__ */ jsx6(
8106
8430
  "div",
8107
8431
  {
8108
8432
  style: {
@@ -8120,7 +8444,7 @@ var DimensionOverlay = ({
8120
8444
  children: diagonalLabel.distance.toFixed(2)
8121
8445
  }
8122
8446
  ),
8123
- /* @__PURE__ */ jsx5(
8447
+ /* @__PURE__ */ jsx6(
8124
8448
  "div",
8125
8449
  {
8126
8450
  style: {
@@ -8140,7 +8464,7 @@ var DimensionOverlay = ({
8140
8464
  children: Math.abs(dStart.x - dEnd.x).toFixed(2)
8141
8465
  }
8142
8466
  ),
8143
- /* @__PURE__ */ jsx5(
8467
+ /* @__PURE__ */ jsx6(
8144
8468
  "div",
8145
8469
  {
8146
8470
  style: {
@@ -8158,7 +8482,7 @@ var DimensionOverlay = ({
8158
8482
  fontFamily: "sans-serif",
8159
8483
  zIndex: zIndexMap.dimensionOverlay
8160
8484
  },
8161
- children: /* @__PURE__ */ jsx5(
8485
+ children: /* @__PURE__ */ jsx6(
8162
8486
  "div",
8163
8487
  {
8164
8488
  style: {
@@ -8170,7 +8494,7 @@ var DimensionOverlay = ({
8170
8494
  )
8171
8495
  }
8172
8496
  ),
8173
- /* @__PURE__ */ jsxs3(
8497
+ /* @__PURE__ */ jsxs4(
8174
8498
  "svg",
8175
8499
  {
8176
8500
  style: {
@@ -8184,7 +8508,7 @@ var DimensionOverlay = ({
8184
8508
  width: containerBounds.width,
8185
8509
  height: containerBounds.height,
8186
8510
  children: [
8187
- /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsx5(
8511
+ /* @__PURE__ */ jsx6("defs", { children: /* @__PURE__ */ jsx6(
8188
8512
  "marker",
8189
8513
  {
8190
8514
  id: "head",
@@ -8193,10 +8517,10 @@ var DimensionOverlay = ({
8193
8517
  markerHeight: "4",
8194
8518
  refX: "2",
8195
8519
  refY: "2",
8196
- children: /* @__PURE__ */ jsx5("path", { d: "M0,0 V4 L2,2 Z", fill: "red" })
8520
+ children: /* @__PURE__ */ jsx6("path", { d: "M0,0 V4 L2,2 Z", fill: "red" })
8197
8521
  }
8198
8522
  ) }),
8199
- /* @__PURE__ */ jsx5(
8523
+ /* @__PURE__ */ jsx6(
8200
8524
  "line",
8201
8525
  {
8202
8526
  x1: screenDStart.x,
@@ -8209,7 +8533,7 @@ var DimensionOverlay = ({
8209
8533
  stroke: "red"
8210
8534
  }
8211
8535
  ),
8212
- /* @__PURE__ */ jsx5(
8536
+ /* @__PURE__ */ jsx6(
8213
8537
  "line",
8214
8538
  {
8215
8539
  x1: screenDStart.x,
@@ -8222,7 +8546,7 @@ var DimensionOverlay = ({
8222
8546
  stroke: "red"
8223
8547
  }
8224
8548
  ),
8225
- /* @__PURE__ */ jsx5(
8549
+ /* @__PURE__ */ jsx6(
8226
8550
  "line",
8227
8551
  {
8228
8552
  x1: screenDEnd.x,
@@ -8238,50 +8562,15 @@ var DimensionOverlay = ({
8238
8562
  ]
8239
8563
  }
8240
8564
  ),
8241
- dimensionToolStretching && snappingPointsWithScreen.map((snap) => {
8242
- const isActive = snap.id === activeSnapIds.start || snap.id === activeSnapIds.end;
8243
- const half = SNAP_MARKER_SIZE / 2;
8244
- return /* @__PURE__ */ jsxs3(
8245
- "svg",
8246
- {
8247
- width: SNAP_MARKER_SIZE,
8248
- height: SNAP_MARKER_SIZE,
8249
- style: {
8250
- position: "absolute",
8251
- left: snap.screenPoint.x - half,
8252
- top: snap.screenPoint.y - half,
8253
- pointerEvents: "none",
8254
- zIndex: zIndexMap.dimensionOverlay
8255
- },
8256
- children: [
8257
- /* @__PURE__ */ jsx5(
8258
- "line",
8259
- {
8260
- x1: 0,
8261
- y1: 0,
8262
- x2: SNAP_MARKER_SIZE,
8263
- y2: SNAP_MARKER_SIZE,
8264
- stroke: isActive ? "#66ccff" : "white",
8265
- strokeWidth: 1
8266
- }
8267
- ),
8268
- /* @__PURE__ */ jsx5(
8269
- "line",
8270
- {
8271
- x1: SNAP_MARKER_SIZE,
8272
- y1: 0,
8273
- x2: 0,
8274
- y2: SNAP_MARKER_SIZE,
8275
- stroke: isActive ? "#66ccff" : "white",
8276
- strokeWidth: 1
8277
- }
8278
- )
8279
- ]
8280
- },
8281
- snap.id
8282
- );
8283
- }),
8284
- /* @__PURE__ */ jsxs3(
8565
+ dimensionToolStretching && /* @__PURE__ */ jsx6(
8566
+ DimensionSnapGuides,
8567
+ {
8568
+ points: snappingPointsWithScreen,
8569
+ startId: activeSnapIds.start,
8570
+ endId: activeSnapIds.end
8571
+ }
8572
+ ),
8573
+ /* @__PURE__ */ jsxs4(
8285
8574
  "div",
8286
8575
  {
8287
8576
  style: {
@@ -8299,13 +8588,13 @@ var DimensionOverlay = ({
8299
8588
  ",",
8300
8589
  dStart.y.toFixed(2),
8301
8590
  ")",
8302
- /* @__PURE__ */ jsx5("br", {}),
8591
+ /* @__PURE__ */ jsx6("br", {}),
8303
8592
  "(",
8304
8593
  dEnd.x.toFixed(2),
8305
8594
  ",",
8306
8595
  dEnd.y.toFixed(2),
8307
8596
  ")",
8308
- /* @__PURE__ */ jsx5("br", {}),
8597
+ /* @__PURE__ */ jsx6("br", {}),
8309
8598
  "dist:",
8310
8599
  " ",
8311
8600
  Math.sqrt(
@@ -8323,7 +8612,7 @@ var DimensionOverlay = ({
8323
8612
  // src/components/EditPlacementOverlay.tsx
8324
8613
  import { useRef as useRef6, useState as useState5 } from "react";
8325
8614
  import { applyToPoint as applyToPoint11, identity as identity4, inverse as inverse4 } from "transformation-matrix";
8326
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
8615
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
8327
8616
  var isInsideOf = (pcb_component, point, padding = 0) => {
8328
8617
  const halfWidth = pcb_component.width / 2;
8329
8618
  const halfHeight = pcb_component.height / 2;
@@ -8353,7 +8642,7 @@ var EditPlacementOverlay = ({
8353
8642
  const in_move_footprint_mode = useGlobalStore((s) => s.in_move_footprint_mode);
8354
8643
  const setIsMovingComponent = useGlobalStore((s) => s.setIsMovingComponent);
8355
8644
  const disabled = disabledProp || !in_move_footprint_mode;
8356
- return /* @__PURE__ */ jsxs4(
8645
+ return /* @__PURE__ */ jsxs5(
8357
8646
  "div",
8358
8647
  {
8359
8648
  ref: containerRef,
@@ -8439,7 +8728,7 @@ var EditPlacementOverlay = ({
8439
8728
  !disabled && soup.filter((e) => e.type === "pcb_component").map((e) => {
8440
8729
  if (!e?.center) return null;
8441
8730
  const projectedCenter = applyToPoint11(transform, e.center);
8442
- return /* @__PURE__ */ jsx6(
8731
+ return /* @__PURE__ */ jsx7(
8443
8732
  "div",
8444
8733
  {
8445
8734
  style: {
@@ -8502,10 +8791,10 @@ var getPopupPosition = (errorCenter, containerRef) => {
8502
8791
  };
8503
8792
 
8504
8793
  // src/components/FocusMarkerSVG.tsx
8505
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
8794
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
8506
8795
  var FocusMarkerSVG = ({
8507
8796
  center
8508
- }) => /* @__PURE__ */ jsxs5(
8797
+ }) => /* @__PURE__ */ jsxs6(
8509
8798
  "svg",
8510
8799
  {
8511
8800
  style: {
@@ -8519,7 +8808,7 @@ var FocusMarkerSVG = ({
8519
8808
  width: "100%",
8520
8809
  height: "100%",
8521
8810
  children: [
8522
- /* @__PURE__ */ jsx7(
8811
+ /* @__PURE__ */ jsx8(
8523
8812
  "circle",
8524
8813
  {
8525
8814
  cx: center.x,
@@ -8531,8 +8820,8 @@ var FocusMarkerSVG = ({
8531
8820
  opacity: 0.95
8532
8821
  }
8533
8822
  ),
8534
- /* @__PURE__ */ jsx7("circle", { cx: center.x, cy: center.y, r: 4.5, fill: "#ff6b6b", opacity: 0.95 }),
8535
- /* @__PURE__ */ jsx7(
8823
+ /* @__PURE__ */ jsx8("circle", { cx: center.x, cy: center.y, r: 4.5, fill: "#ff6b6b", opacity: 0.95 }),
8824
+ /* @__PURE__ */ jsx8(
8536
8825
  "line",
8537
8826
  {
8538
8827
  x1: center.x - 18,
@@ -8543,7 +8832,7 @@ var FocusMarkerSVG = ({
8543
8832
  strokeWidth: 2
8544
8833
  }
8545
8834
  ),
8546
- /* @__PURE__ */ jsx7(
8835
+ /* @__PURE__ */ jsx8(
8547
8836
  "line",
8548
8837
  {
8549
8838
  x1: center.x + 8,
@@ -8554,7 +8843,7 @@ var FocusMarkerSVG = ({
8554
8843
  strokeWidth: 2
8555
8844
  }
8556
8845
  ),
8557
- /* @__PURE__ */ jsx7(
8846
+ /* @__PURE__ */ jsx8(
8558
8847
  "line",
8559
8848
  {
8560
8849
  x1: center.x,
@@ -8565,7 +8854,7 @@ var FocusMarkerSVG = ({
8565
8854
  strokeWidth: 2
8566
8855
  }
8567
8856
  ),
8568
- /* @__PURE__ */ jsx7(
8857
+ /* @__PURE__ */ jsx8(
8569
8858
  "line",
8570
8859
  {
8571
8860
  x1: center.x,
@@ -8581,11 +8870,11 @@ var FocusMarkerSVG = ({
8581
8870
  );
8582
8871
 
8583
8872
  // src/components/ErrorOverlay.tsx
8584
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
8873
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
8585
8874
  var ErrorMarkerSVG = ({
8586
8875
  errorCenter,
8587
8876
  isHighlighted = false
8588
- }) => /* @__PURE__ */ jsx8(
8877
+ }) => /* @__PURE__ */ jsx9(
8589
8878
  "svg",
8590
8879
  {
8591
8880
  style: {
@@ -8598,7 +8887,7 @@ var ErrorMarkerSVG = ({
8598
8887
  },
8599
8888
  width: "100%",
8600
8889
  height: "100%",
8601
- children: /* @__PURE__ */ jsx8(
8890
+ children: /* @__PURE__ */ jsx9(
8602
8891
  "rect",
8603
8892
  {
8604
8893
  x: errorCenter.x - 7,
@@ -8642,7 +8931,7 @@ var ErrorOverlay = ({
8642
8931
  );
8643
8932
  const activeErrorId = focusedErrorId ?? hoveredErrorId;
8644
8933
  if (!elements) {
8645
- return /* @__PURE__ */ jsx8("div", { style: { position: "relative" }, ref: containerRef, children });
8934
+ return /* @__PURE__ */ jsx9("div", { style: { position: "relative" }, ref: containerRef, children });
8646
8935
  }
8647
8936
  const traceErrors = elements.filter(
8648
8937
  (el) => el.type === "pcb_trace_error" && !el.message?.includes("Multiple components found with name")
@@ -8675,7 +8964,7 @@ var ErrorOverlay = ({
8675
8964
  focusedErrorElement
8676
8965
  );
8677
8966
  }
8678
- return /* @__PURE__ */ jsxs6("div", { style: { position: "relative" }, ref: containerRef, children: [
8967
+ return /* @__PURE__ */ jsxs7("div", { style: { position: "relative" }, ref: containerRef, children: [
8679
8968
  children,
8680
8969
  traceErrors.map((el, index) => {
8681
8970
  const errorId = getErrorId(el, index);
@@ -8684,15 +8973,15 @@ var ErrorOverlay = ({
8684
8973
  const errorCenter = getScreenErrorCenter(el);
8685
8974
  if (!errorCenter) return null;
8686
8975
  const popupPosition = getPopupPosition(errorCenter, containerRef);
8687
- return /* @__PURE__ */ jsxs6(Fragment2, { children: [
8688
- /* @__PURE__ */ jsx8(
8976
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
8977
+ /* @__PURE__ */ jsx9(
8689
8978
  ErrorMarkerSVG,
8690
8979
  {
8691
8980
  errorCenter,
8692
8981
  isHighlighted
8693
8982
  }
8694
8983
  ),
8695
- /* @__PURE__ */ jsx8(
8984
+ /* @__PURE__ */ jsx9(
8696
8985
  "div",
8697
8986
  {
8698
8987
  style: {
@@ -8727,7 +9016,7 @@ var ErrorOverlay = ({
8727
9016
  }
8728
9017
  }
8729
9018
  ),
8730
- /* @__PURE__ */ jsx8(
9019
+ /* @__PURE__ */ jsx9(
8731
9020
  "div",
8732
9021
  {
8733
9022
  style: {
@@ -8745,7 +9034,7 @@ var ErrorOverlay = ({
8745
9034
  pointerEvents: "none",
8746
9035
  transform: popupPosition.transform
8747
9036
  },
8748
- children: /* @__PURE__ */ jsx8(
9037
+ children: /* @__PURE__ */ jsx9(
8749
9038
  "div",
8750
9039
  {
8751
9040
  className: `error-message ${errorMessageStyles}`,
@@ -8770,15 +9059,15 @@ var ErrorOverlay = ({
8770
9059
  { x: errorCenter.x, y: errorCenter.y },
8771
9060
  containerRef
8772
9061
  );
8773
- return /* @__PURE__ */ jsxs6(Fragment2, { children: [
8774
- /* @__PURE__ */ jsx8(
9062
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
9063
+ /* @__PURE__ */ jsx9(
8775
9064
  ErrorMarkerSVG,
8776
9065
  {
8777
9066
  errorCenter,
8778
9067
  isHighlighted
8779
9068
  }
8780
9069
  ),
8781
- /* @__PURE__ */ jsx8(
9070
+ /* @__PURE__ */ jsx9(
8782
9071
  "div",
8783
9072
  {
8784
9073
  style: {
@@ -8813,7 +9102,7 @@ var ErrorOverlay = ({
8813
9102
  }
8814
9103
  }
8815
9104
  ),
8816
- /* @__PURE__ */ jsx8(
9105
+ /* @__PURE__ */ jsx9(
8817
9106
  "div",
8818
9107
  {
8819
9108
  style: {
@@ -8831,7 +9120,7 @@ var ErrorOverlay = ({
8831
9120
  pointerEvents: "none",
8832
9121
  transform: popupPosition.transform
8833
9122
  },
8834
- children: /* @__PURE__ */ jsx8(
9123
+ children: /* @__PURE__ */ jsx9(
8835
9124
  "div",
8836
9125
  {
8837
9126
  className: `error-message ${errorMessageStyles}`,
@@ -8880,8 +9169,8 @@ var ErrorOverlay = ({
8880
9169
  Math.min(maxRadius, baseRadius * scale7)
8881
9170
  );
8882
9171
  const popupPosition = getPopupPosition(screenCenter, containerRef);
8883
- return /* @__PURE__ */ jsxs6(Fragment2, { children: [
8884
- /* @__PURE__ */ jsx8(
9172
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
9173
+ /* @__PURE__ */ jsx9(
8885
9174
  "svg",
8886
9175
  {
8887
9176
  style: {
@@ -8894,13 +9183,13 @@ var ErrorOverlay = ({
8894
9183
  },
8895
9184
  width: "100%",
8896
9185
  height: "100%",
8897
- children: isHighlighted ? /* @__PURE__ */ jsx8(
9186
+ children: isHighlighted ? /* @__PURE__ */ jsx9(
8898
9187
  "polygon",
8899
9188
  {
8900
9189
  points: `${screenCenter.x},${screenCenter.y - scaledRadius * 1.25} ${screenCenter.x + scaledRadius},${screenCenter.y} ${screenCenter.x},${screenCenter.y + scaledRadius * 1.25} ${screenCenter.x - scaledRadius},${screenCenter.y}`,
8901
9190
  fill: "#ff4444"
8902
9191
  }
8903
- ) : /* @__PURE__ */ jsx8(
9192
+ ) : /* @__PURE__ */ jsx9(
8904
9193
  "circle",
8905
9194
  {
8906
9195
  cx: screenCenter.x,
@@ -8914,7 +9203,7 @@ var ErrorOverlay = ({
8914
9203
  )
8915
9204
  }
8916
9205
  ),
8917
- /* @__PURE__ */ jsx8(
9206
+ /* @__PURE__ */ jsx9(
8918
9207
  "div",
8919
9208
  {
8920
9209
  style: {
@@ -8949,7 +9238,7 @@ var ErrorOverlay = ({
8949
9238
  }
8950
9239
  }
8951
9240
  ),
8952
- /* @__PURE__ */ jsx8(
9241
+ /* @__PURE__ */ jsx9(
8953
9242
  "div",
8954
9243
  {
8955
9244
  style: {
@@ -8967,7 +9256,7 @@ var ErrorOverlay = ({
8967
9256
  pointerEvents: "none",
8968
9257
  transform: popupPosition.transform
8969
9258
  },
8970
- children: /* @__PURE__ */ jsx8(
9259
+ children: /* @__PURE__ */ jsx9(
8971
9260
  "div",
8972
9261
  {
8973
9262
  className: `error-message ${errorMessageStyles}`,
@@ -8983,7 +9272,7 @@ var ErrorOverlay = ({
8983
9272
  ] }, `${errorId}_${compIndex}`);
8984
9273
  });
8985
9274
  }),
8986
- focusScreenCenter && /* @__PURE__ */ jsx8(FocusMarkerSVG, { center: focusScreenCenter })
9275
+ focusScreenCenter && /* @__PURE__ */ jsx9(FocusMarkerSVG, { center: focusScreenCenter })
8987
9276
  ] });
8988
9277
  };
8989
9278
 
@@ -8998,7 +9287,7 @@ function ifSetsMatchExactly(set1, set2) {
8998
9287
  }
8999
9288
 
9000
9289
  // src/components/MouseElementTracker.tsx
9001
- import { useEffect as useEffect10, useMemo as useMemo5, useState as useState7 } from "react";
9290
+ import { useEffect as useEffect10, useMemo as useMemo6, useState as useState7 } from "react";
9002
9291
  import { applyToPoint as applyToPoint15, inverse as inverse5 } from "transformation-matrix";
9003
9292
 
9004
9293
  // src/components/AnchorOffsetOverlay/common/guards.ts
@@ -9034,7 +9323,7 @@ var COLORS = {
9034
9323
  };
9035
9324
 
9036
9325
  // src/components/AnchorOffsetOverlay/AnchorOffsetOverlay.tsx
9037
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
9326
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
9038
9327
  var AnchorOffsetOverlay = ({
9039
9328
  targets,
9040
9329
  transform,
@@ -9057,7 +9346,7 @@ var AnchorOffsetOverlay = ({
9057
9346
  anchorScreens.set(target.anchor_id, screenPoint);
9058
9347
  }
9059
9348
  });
9060
- return /* @__PURE__ */ jsx9(
9349
+ return /* @__PURE__ */ jsx10(
9061
9350
  "div",
9062
9351
  {
9063
9352
  style: {
@@ -9070,7 +9359,7 @@ var AnchorOffsetOverlay = ({
9070
9359
  pointerEvents: "none",
9071
9360
  zIndex: zIndexMap.dimensionOverlay
9072
9361
  },
9073
- children: /* @__PURE__ */ jsxs7(
9362
+ children: /* @__PURE__ */ jsxs8(
9074
9363
  "svg",
9075
9364
  {
9076
9365
  style: {
@@ -9100,8 +9389,8 @@ var AnchorOffsetOverlay = ({
9100
9389
  const shouldShowYLabel = yLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL;
9101
9390
  const xLabelText = `${target.display_offset_x ?? offsetX.toFixed(2)}mm`;
9102
9391
  const yLabelText = `${target.display_offset_y ?? offsetY.toFixed(2)}mm`;
9103
- return /* @__PURE__ */ jsxs7("g", { children: [
9104
- /* @__PURE__ */ jsx9(
9392
+ return /* @__PURE__ */ jsxs8("g", { children: [
9393
+ /* @__PURE__ */ jsx10(
9105
9394
  "line",
9106
9395
  {
9107
9396
  x1: anchorMarkerScreen.x,
@@ -9113,7 +9402,7 @@ var AnchorOffsetOverlay = ({
9113
9402
  strokeDasharray: VISUAL_CONFIG.LINE_DASH_PATTERN
9114
9403
  }
9115
9404
  ),
9116
- /* @__PURE__ */ jsx9(
9405
+ /* @__PURE__ */ jsx10(
9117
9406
  "line",
9118
9407
  {
9119
9408
  x1: targetScreen.x,
@@ -9125,7 +9414,7 @@ var AnchorOffsetOverlay = ({
9125
9414
  strokeDasharray: VISUAL_CONFIG.LINE_DASH_PATTERN
9126
9415
  }
9127
9416
  ),
9128
- target.type === "component" || target.type === "board" ? /* @__PURE__ */ jsx9(
9417
+ target.type === "component" || target.type === "board" ? /* @__PURE__ */ jsx10(
9129
9418
  "circle",
9130
9419
  {
9131
9420
  cx: targetScreen.x,
@@ -9137,8 +9426,8 @@ var AnchorOffsetOverlay = ({
9137
9426
  }
9138
9427
  ) : (
9139
9428
  // assumes "group"
9140
- /* @__PURE__ */ jsxs7(Fragment3, { children: [
9141
- /* @__PURE__ */ jsx9(
9429
+ /* @__PURE__ */ jsxs8(Fragment3, { children: [
9430
+ /* @__PURE__ */ jsx10(
9142
9431
  "line",
9143
9432
  {
9144
9433
  x1: targetScreen.x - VISUAL_CONFIG.ANCHOR_MARKER_SIZE,
@@ -9149,7 +9438,7 @@ var AnchorOffsetOverlay = ({
9149
9438
  strokeWidth: VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH
9150
9439
  }
9151
9440
  ),
9152
- /* @__PURE__ */ jsx9(
9441
+ /* @__PURE__ */ jsx10(
9153
9442
  "line",
9154
9443
  {
9155
9444
  x1: targetScreen.x,
@@ -9162,7 +9451,7 @@ var AnchorOffsetOverlay = ({
9162
9451
  )
9163
9452
  ] })
9164
9453
  ),
9165
- shouldShowXLabel && /* @__PURE__ */ jsx9(
9454
+ shouldShowXLabel && /* @__PURE__ */ jsx10(
9166
9455
  "foreignObject",
9167
9456
  {
9168
9457
  x: Math.min(anchorMarkerScreen.x, targetScreen.x),
@@ -9170,10 +9459,10 @@ var AnchorOffsetOverlay = ({
9170
9459
  width: Math.abs(targetScreen.x - anchorMarkerScreen.x),
9171
9460
  height: 20,
9172
9461
  style: { overflow: "visible" },
9173
- children: /* @__PURE__ */ jsx9("div", { style: { ...labelStyle, textAlign: "center" }, children: xLabelText })
9462
+ children: /* @__PURE__ */ jsx10("div", { style: { ...labelStyle, textAlign: "center" }, children: xLabelText })
9174
9463
  }
9175
9464
  ),
9176
- shouldShowYLabel && /* @__PURE__ */ jsx9(
9465
+ shouldShowYLabel && /* @__PURE__ */ jsx10(
9177
9466
  "foreignObject",
9178
9467
  {
9179
9468
  x: targetScreen.x + yLabelOffset,
@@ -9181,7 +9470,7 @@ var AnchorOffsetOverlay = ({
9181
9470
  width: VISUAL_CONFIG.Y_LABEL_MIN_WIDTH,
9182
9471
  height: Math.abs(targetScreen.y - anchorMarkerScreen.y),
9183
9472
  style: { overflow: "visible" },
9184
- children: /* @__PURE__ */ jsx9(
9473
+ children: /* @__PURE__ */ jsx10(
9185
9474
  "div",
9186
9475
  {
9187
9476
  style: {
@@ -9200,8 +9489,8 @@ var AnchorOffsetOverlay = ({
9200
9489
  )
9201
9490
  ] }, target.id);
9202
9491
  }),
9203
- Array.from(anchorScreens.entries()).map(([anchorId, anchorScreen]) => /* @__PURE__ */ jsxs7("g", { children: [
9204
- /* @__PURE__ */ jsx9(
9492
+ Array.from(anchorScreens.entries()).map(([anchorId, anchorScreen]) => /* @__PURE__ */ jsxs8("g", { children: [
9493
+ /* @__PURE__ */ jsx10(
9205
9494
  "line",
9206
9495
  {
9207
9496
  x1: anchorScreen.x - VISUAL_CONFIG.ANCHOR_MARKER_SIZE,
@@ -9212,7 +9501,7 @@ var AnchorOffsetOverlay = ({
9212
9501
  strokeWidth: VISUAL_CONFIG.ANCHOR_MARKER_STROKE_WIDTH
9213
9502
  }
9214
9503
  ),
9215
- /* @__PURE__ */ jsx9(
9504
+ /* @__PURE__ */ jsx10(
9216
9505
  "line",
9217
9506
  {
9218
9507
  x1: anchorScreen.x,
@@ -9232,7 +9521,7 @@ var AnchorOffsetOverlay = ({
9232
9521
  };
9233
9522
 
9234
9523
  // src/components/AnchorOffsetOverlay/BoardAnchorOffsetOverlay.tsx
9235
- import { jsx as jsx10 } from "react/jsx-runtime";
9524
+ import { jsx as jsx11 } from "react/jsx-runtime";
9236
9525
  var BoardAnchorOffsetOverlay = ({
9237
9526
  elements,
9238
9527
  highlightedPrimitives,
@@ -9319,7 +9608,7 @@ var BoardAnchorOffsetOverlay = ({
9319
9608
  display_offset_y: target.group.display_offset_y
9320
9609
  };
9321
9610
  }).filter((t) => Boolean(t));
9322
- return /* @__PURE__ */ jsx10(
9611
+ return /* @__PURE__ */ jsx11(
9323
9612
  AnchorOffsetOverlay,
9324
9613
  {
9325
9614
  targets: sharedTargets,
@@ -9331,7 +9620,7 @@ var BoardAnchorOffsetOverlay = ({
9331
9620
  };
9332
9621
 
9333
9622
  // src/components/AnchorOffsetOverlay/GroupAnchorOffsetOverlay.tsx
9334
- import { jsx as jsx11 } from "react/jsx-runtime";
9623
+ import { jsx as jsx12 } from "react/jsx-runtime";
9335
9624
  var GroupAnchorOffsetOverlay = ({
9336
9625
  elements,
9337
9626
  highlightedPrimitives,
@@ -9447,7 +9736,7 @@ var GroupAnchorOffsetOverlay = ({
9447
9736
  display_offset_y: target.group.display_offset_y
9448
9737
  };
9449
9738
  }).filter((t) => Boolean(t));
9450
- return /* @__PURE__ */ jsx11(
9739
+ return /* @__PURE__ */ jsx12(
9451
9740
  AnchorOffsetOverlay,
9452
9741
  {
9453
9742
  targets: sharedTargets,
@@ -9460,7 +9749,7 @@ var GroupAnchorOffsetOverlay = ({
9460
9749
 
9461
9750
  // src/components/AnchorOffsetOverlay/ComponentBoundingBoxOverlay.tsx
9462
9751
  import { applyToPoint as applyToPoint14 } from "transformation-matrix";
9463
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
9752
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
9464
9753
  var calculateComponentBoundingBox = (component, elements) => {
9465
9754
  const componentId = component.pcb_component_id;
9466
9755
  const padsAndHoles = elements.filter(
@@ -9503,7 +9792,7 @@ var ComponentBoundingBoxOverlay = ({
9503
9792
  renderData.push({ component, bbox, group });
9504
9793
  }
9505
9794
  if (renderData.length === 0) return null;
9506
- return /* @__PURE__ */ jsx12(
9795
+ return /* @__PURE__ */ jsx13(
9507
9796
  "div",
9508
9797
  {
9509
9798
  style: {
@@ -9516,7 +9805,7 @@ var ComponentBoundingBoxOverlay = ({
9516
9805
  pointerEvents: "none",
9517
9806
  zIndex: zIndexMap.dimensionOverlay
9518
9807
  },
9519
- children: /* @__PURE__ */ jsx12(
9808
+ children: /* @__PURE__ */ jsx13(
9520
9809
  "svg",
9521
9810
  {
9522
9811
  style: { position: "absolute", left: 0, top: 0, pointerEvents: "none" },
@@ -9542,8 +9831,8 @@ var ComponentBoundingBoxOverlay = ({
9542
9831
  y: (bbox.minY + bbox.maxY) / 2
9543
9832
  };
9544
9833
  const componentCenterScreen = applyToPoint14(transform, componentCenter);
9545
- return /* @__PURE__ */ jsxs8("g", { children: [
9546
- /* @__PURE__ */ jsx12(
9834
+ return /* @__PURE__ */ jsxs9("g", { children: [
9835
+ /* @__PURE__ */ jsx13(
9547
9836
  "rect",
9548
9837
  {
9549
9838
  x: screenBbox.x,
@@ -9556,7 +9845,7 @@ var ComponentBoundingBoxOverlay = ({
9556
9845
  strokeDasharray: "4,4"
9557
9846
  }
9558
9847
  ),
9559
- /* @__PURE__ */ jsx12(
9848
+ /* @__PURE__ */ jsx13(
9560
9849
  "line",
9561
9850
  {
9562
9851
  x1: componentCenterScreen.x - 6,
@@ -9567,7 +9856,7 @@ var ComponentBoundingBoxOverlay = ({
9567
9856
  strokeWidth: 1.5
9568
9857
  }
9569
9858
  ),
9570
- /* @__PURE__ */ jsx12(
9859
+ /* @__PURE__ */ jsx13(
9571
9860
  "line",
9572
9861
  {
9573
9862
  x1: componentCenterScreen.x,
@@ -9578,7 +9867,7 @@ var ComponentBoundingBoxOverlay = ({
9578
9867
  strokeWidth: 1.5
9579
9868
  }
9580
9869
  ),
9581
- /* @__PURE__ */ jsx12(
9870
+ /* @__PURE__ */ jsx13(
9582
9871
  "circle",
9583
9872
  {
9584
9873
  cx: componentCenterScreen.x,
@@ -9598,7 +9887,7 @@ var ComponentBoundingBoxOverlay = ({
9598
9887
  };
9599
9888
 
9600
9889
  // src/components/AnchorOffsetOverlay/PanelAnchorOffsetOverlay.tsx
9601
- import { jsx as jsx13 } from "react/jsx-runtime";
9890
+ import { jsx as jsx14 } from "react/jsx-runtime";
9602
9891
  var PanelAnchorOffsetOverlay = ({
9603
9892
  elements,
9604
9893
  highlightedPrimitives,
@@ -9647,7 +9936,7 @@ var PanelAnchorOffsetOverlay = ({
9647
9936
  display_offset_y: target.board.display_offset_y
9648
9937
  };
9649
9938
  }).filter((t) => Boolean(t));
9650
- return /* @__PURE__ */ jsx13(
9939
+ return /* @__PURE__ */ jsx14(
9651
9940
  AnchorOffsetOverlay,
9652
9941
  {
9653
9942
  targets: sharedTargets,
@@ -9737,7 +10026,7 @@ function filterTracesIfMultiple(filterTraces) {
9737
10026
 
9738
10027
  // src/components/ElementOverlayBox.tsx
9739
10028
  import { useEffect as useEffect9, useState as useState6 } from "react";
9740
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
10029
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
9741
10030
  var containerStyle = {
9742
10031
  position: "absolute",
9743
10032
  left: 0,
@@ -9828,7 +10117,7 @@ var HighlightedPrimitiveBoxWithText = ({
9828
10117
  const traceTextContext = { primitiveElement, elements };
9829
10118
  const overlayInfo = getTraceOverlayInfo(traceTextContext);
9830
10119
  if (!overlayInfo) return null;
9831
- return /* @__PURE__ */ jsx14(
10120
+ return /* @__PURE__ */ jsx15(
9832
10121
  "div",
9833
10122
  {
9834
10123
  style: {
@@ -9839,7 +10128,7 @@ var HighlightedPrimitiveBoxWithText = ({
9839
10128
  color: color8,
9840
10129
  pointerEvents: "none"
9841
10130
  },
9842
- children: /* @__PURE__ */ jsxs9(
10131
+ children: /* @__PURE__ */ jsxs10(
9843
10132
  "div",
9844
10133
  {
9845
10134
  style: {
@@ -9856,8 +10145,8 @@ var HighlightedPrimitiveBoxWithText = ({
9856
10145
  whiteSpace: "nowrap"
9857
10146
  },
9858
10147
  children: [
9859
- overlayInfo.text && /* @__PURE__ */ jsx14("div", { children: overlayInfo.text }),
9860
- overlayInfo.name && /* @__PURE__ */ jsx14(
10148
+ overlayInfo.text && /* @__PURE__ */ jsx15("div", { children: overlayInfo.text }),
10149
+ overlayInfo.name && /* @__PURE__ */ jsx15(
9861
10150
  "div",
9862
10151
  {
9863
10152
  style: {
@@ -9876,7 +10165,7 @@ var HighlightedPrimitiveBoxWithText = ({
9876
10165
  if (label.trim().length === 0) {
9877
10166
  return null;
9878
10167
  }
9879
- return /* @__PURE__ */ jsx14(
10168
+ return /* @__PURE__ */ jsx15(
9880
10169
  "div",
9881
10170
  {
9882
10171
  style: {
@@ -9890,7 +10179,7 @@ var HighlightedPrimitiveBoxWithText = ({
9890
10179
  transform: `rotate(${-rotation}deg)`,
9891
10180
  transformOrigin: "center center"
9892
10181
  },
9893
- children: /* @__PURE__ */ jsx14(
10182
+ children: /* @__PURE__ */ jsx15(
9894
10183
  "div",
9895
10184
  {
9896
10185
  style: {
@@ -9906,7 +10195,7 @@ var HighlightedPrimitiveBoxWithText = ({
9906
10195
  opacity: finalState ? 1 : si === 0 ? 1 : 0,
9907
10196
  transition: "width 0.2s, height 0.2s, margin-left 0.2s, margin-top 0.2s, opacity 0.2s"
9908
10197
  },
9909
- children: /* @__PURE__ */ jsx14(
10198
+ children: /* @__PURE__ */ jsx15(
9910
10199
  "div",
9911
10200
  {
9912
10201
  style: {
@@ -9954,7 +10243,7 @@ var ElementOverlayBox = ({
9954
10243
  is_showing_multiple_traces_length,
9955
10244
  elements
9956
10245
  });
9957
- return /* @__PURE__ */ jsx14("div", { style: containerStyle, children: !is_moving_component && primitives.map((primitive) => /* @__PURE__ */ jsx14(
10246
+ return /* @__PURE__ */ jsx15("div", { style: containerStyle, children: !is_moving_component && primitives.map((primitive) => /* @__PURE__ */ jsx15(
9958
10247
  HighlightedPrimitiveBoxWithText,
9959
10248
  {
9960
10249
  primitive,
@@ -9966,7 +10255,7 @@ var ElementOverlayBox = ({
9966
10255
  };
9967
10256
 
9968
10257
  // src/components/MouseElementTracker.tsx
9969
- import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
10258
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
9970
10259
  var getPolygonBoundingBox = (points) => {
9971
10260
  if (points.length === 0) return null;
9972
10261
  let minX = points[0].x;
@@ -10089,7 +10378,7 @@ var MouseElementTracker = ({
10089
10378
  setMousedPrimitives([]);
10090
10379
  onMouseHoverOverPrimitives([]);
10091
10380
  }, [selectedLayer, onMouseHoverOverPrimitives]);
10092
- const highlightedPrimitives = useMemo5(() => {
10381
+ const highlightedPrimitives = useMemo6(() => {
10093
10382
  const highlightedPrimitives2 = [];
10094
10383
  for (const primitive of mousedPrimitives) {
10095
10384
  if (primitive._element?.type === "pcb_via") continue;
@@ -10169,7 +10458,7 @@ var MouseElementTracker = ({
10169
10458
  setMousedPrimitives(newMousedPrimitives);
10170
10459
  onMouseHoverOverPrimitives(newMousedPrimitives);
10171
10460
  };
10172
- return /* @__PURE__ */ jsxs10(
10461
+ return /* @__PURE__ */ jsxs11(
10173
10462
  "div",
10174
10463
  {
10175
10464
  ref: containerRef,
@@ -10193,7 +10482,7 @@ var MouseElementTracker = ({
10193
10482
  },
10194
10483
  children: [
10195
10484
  children,
10196
- /* @__PURE__ */ jsx15(
10485
+ /* @__PURE__ */ jsx16(
10197
10486
  ElementOverlayBox,
10198
10487
  {
10199
10488
  elements,
@@ -10201,8 +10490,8 @@ var MouseElementTracker = ({
10201
10490
  highlightedPrimitives
10202
10491
  }
10203
10492
  ),
10204
- transform && /* @__PURE__ */ jsxs10(Fragment4, { children: [
10205
- /* @__PURE__ */ jsx15(
10493
+ transform && /* @__PURE__ */ jsxs11(Fragment4, { children: [
10494
+ /* @__PURE__ */ jsx16(
10206
10495
  BoardAnchorOffsetOverlay,
10207
10496
  {
10208
10497
  elements,
@@ -10212,7 +10501,7 @@ var MouseElementTracker = ({
10212
10501
  containerHeight: height
10213
10502
  }
10214
10503
  ),
10215
- /* @__PURE__ */ jsx15(
10504
+ /* @__PURE__ */ jsx16(
10216
10505
  GroupAnchorOffsetOverlay,
10217
10506
  {
10218
10507
  elements,
@@ -10222,7 +10511,7 @@ var MouseElementTracker = ({
10222
10511
  containerHeight: height
10223
10512
  }
10224
10513
  ),
10225
- /* @__PURE__ */ jsx15(
10514
+ /* @__PURE__ */ jsx16(
10226
10515
  ComponentBoundingBoxOverlay,
10227
10516
  {
10228
10517
  elements,
@@ -10232,7 +10521,7 @@ var MouseElementTracker = ({
10232
10521
  containerHeight: height
10233
10522
  }
10234
10523
  ),
10235
- /* @__PURE__ */ jsx15(
10524
+ /* @__PURE__ */ jsx16(
10236
10525
  PanelAnchorOffsetOverlay,
10237
10526
  {
10238
10527
  elements,
@@ -10252,7 +10541,7 @@ var MouseElementTracker = ({
10252
10541
  import { applyToPoint as applyToPoint16 } from "transformation-matrix";
10253
10542
  import { identity as identity6 } from "transformation-matrix";
10254
10543
  import { useRef as useRef8, useEffect as useEffect11 } from "react";
10255
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
10544
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
10256
10545
  var GROUP_COLORS = [
10257
10546
  "rgb(255, 100, 100)",
10258
10547
  "rgb(100, 255, 100)",
@@ -10488,14 +10777,14 @@ var PcbGroupOverlay = ({
10488
10777
  is_showing_group_anchor_offsets,
10489
10778
  hoveredComponentIds
10490
10779
  ]);
10491
- return /* @__PURE__ */ jsxs11(
10780
+ return /* @__PURE__ */ jsxs12(
10492
10781
  "div",
10493
10782
  {
10494
10783
  ref: containerRef,
10495
10784
  style: { position: "relative", width: "100%", height: "100%" },
10496
10785
  children: [
10497
10786
  children,
10498
- /* @__PURE__ */ jsx16(
10787
+ /* @__PURE__ */ jsx17(
10499
10788
  "canvas",
10500
10789
  {
10501
10790
  ref: canvasRef,
@@ -10516,15 +10805,15 @@ var PcbGroupOverlay = ({
10516
10805
 
10517
10806
  // src/components/RatsNestOverlay.tsx
10518
10807
  import { applyToPoint as applyToPoint17, identity as identity7 } from "transformation-matrix";
10519
- import { useMemo as useMemo6 } from "react";
10520
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
10808
+ import { useMemo as useMemo7 } from "react";
10809
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
10521
10810
  var RatsNestOverlay = ({ transform, soup, children }) => {
10522
10811
  const isShowingRatsNest = useGlobalStore((s) => s.is_showing_rats_nest);
10523
- const { netMap, idToNetMap } = useMemo6(
10812
+ const { netMap, idToNetMap } = useMemo7(
10524
10813
  () => getFullConnectivityMapFromCircuitJson(soup || []),
10525
10814
  [soup]
10526
10815
  );
10527
- const ratsNestLines = useMemo6(() => {
10816
+ const ratsNestLines = useMemo7(() => {
10528
10817
  if (!soup || !isShowingRatsNest) return [];
10529
10818
  const getElementPosition = (id) => {
10530
10819
  const element = su(soup)[id.replace(/_\d+$/, "")].get(id);
@@ -10580,9 +10869,9 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
10580
10869
  }, [soup, netMap, idToNetMap, isShowingRatsNest]);
10581
10870
  if (!soup || !isShowingRatsNest) return children;
10582
10871
  if (!transform) transform = identity7();
10583
- return /* @__PURE__ */ jsxs12("div", { style: { position: "relative" }, children: [
10872
+ return /* @__PURE__ */ jsxs13("div", { style: { position: "relative" }, children: [
10584
10873
  children,
10585
- /* @__PURE__ */ jsx17(
10874
+ /* @__PURE__ */ jsx18(
10586
10875
  "svg",
10587
10876
  {
10588
10877
  style: {
@@ -10598,7 +10887,7 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
10598
10887
  children: ratsNestLines.map(({ key, startPoint, endPoint, isInNet }) => {
10599
10888
  const transformedStart = applyToPoint17(transform, startPoint);
10600
10889
  const transformedEnd = applyToPoint17(transform, endPoint);
10601
- return /* @__PURE__ */ jsx17(
10890
+ return /* @__PURE__ */ jsx18(
10602
10891
  "line",
10603
10892
  {
10604
10893
  x1: transformedStart.x,
@@ -10619,18 +10908,18 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
10619
10908
 
10620
10909
  // src/components/ToolbarOverlay.tsx
10621
10910
  import {
10622
- useEffect as useEffect15,
10623
- useState as useState10,
10911
+ useEffect as useEffect16,
10912
+ useState as useState11,
10624
10913
  useCallback as useCallback10,
10625
- useRef as useRef12,
10914
+ useRef as useRef13,
10626
10915
  useLayoutEffect as useLayoutEffect2
10627
10916
  } from "react";
10628
- import { css as css2 } from "@emotion/css";
10917
+ import { css as css3 } from "@emotion/css";
10629
10918
 
10630
10919
  // package.json
10631
10920
  var package_default = {
10632
10921
  name: "@tscircuit/pcb-viewer",
10633
- version: "1.11.393",
10922
+ version: "1.11.395",
10634
10923
  main: "dist/index.js",
10635
10924
  type: "module",
10636
10925
  repository: {
@@ -10663,6 +10952,7 @@ var package_default = {
10663
10952
  "@types/color": "^3.0.6",
10664
10953
  "@types/node": "18.7.23",
10665
10954
  "@types/react": "19",
10955
+ "@types/react-dom": "~19.1.0",
10666
10956
  "format-si-unit": "^0.0.12",
10667
10957
  next: "^14.1.4",
10668
10958
  "pixi.js": "^8.6.6",
@@ -10787,8 +11077,228 @@ var useMobileTouch = (onClick, options = { stopPropagation: true }) => {
10787
11077
  };
10788
11078
  };
10789
11079
 
11080
+ // src/components/VisibilityContextMenu.tsx
11081
+ var import_react_dom = __toESM(require_react_dom(), 1);
11082
+ import { css as css2 } from "@emotion/css";
11083
+ import { useEffect as useEffect14, useRef as useRef11, useState as useState9 } from "react";
11084
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
11085
+ var menuStyle = css2`
11086
+ background: #222;
11087
+ color: #eee;
11088
+ border: 1px solid #555;
11089
+ border-radius: 4px;
11090
+ padding: 4px;
11091
+ font: 12px sans-serif;
11092
+ box-shadow: 0 4px 16px #0008;
11093
+ `;
11094
+ var itemStyle = css2`
11095
+ display: block;
11096
+ width: 100%;
11097
+ padding: 8px;
11098
+ border: 0;
11099
+ border-radius: 2px;
11100
+ background: transparent;
11101
+ color: inherit;
11102
+ font: inherit;
11103
+ text-align: left;
11104
+ white-space: nowrap;
11105
+ cursor: pointer;
11106
+ &:hover, &:focus-visible { background: #444; }
11107
+ `;
11108
+ var VisibilityContextMenu = ({
11109
+ position,
11110
+ onClose
11111
+ }) => {
11112
+ const opacity = useGlobalStore((s) => s.hidden_layer_opacity);
11113
+ const setOpacity = useGlobalStore((s) => s.setHiddenLayerOpacity);
11114
+ const [visibilityOpen, setVisibilityOpen] = useState9(false);
11115
+ const [opacityOpen, setOpacityOpen] = useState9(false);
11116
+ const ref = useRef11(null);
11117
+ const stacked = window.innerWidth < 480;
11118
+ const openLeft = !stacked && position.x + 460 > window.innerWidth;
11119
+ const submenuStyle = stacked ? { position: "relative" } : {
11120
+ position: "absolute",
11121
+ top: 0,
11122
+ ...openLeft ? { right: "100%" } : { left: "100%" }
11123
+ };
11124
+ useEffect14(() => {
11125
+ const dismiss = (event) => {
11126
+ if (!ref.current?.contains(event.target)) onClose();
11127
+ };
11128
+ const onKeyDown = (event) => {
11129
+ if (event.key === "Escape") {
11130
+ event.preventDefault();
11131
+ onClose();
11132
+ }
11133
+ };
11134
+ ref.current?.querySelector("button")?.focus();
11135
+ window.addEventListener("pointerdown", dismiss, true);
11136
+ window.addEventListener("keydown", onKeyDown);
11137
+ window.addEventListener("resize", onClose);
11138
+ window.addEventListener("scroll", onClose, true);
11139
+ return () => {
11140
+ window.removeEventListener("pointerdown", dismiss, true);
11141
+ window.removeEventListener("keydown", onKeyDown);
11142
+ window.removeEventListener("resize", onClose);
11143
+ window.removeEventListener("scroll", onClose, true);
11144
+ };
11145
+ }, [onClose]);
11146
+ return (0, import_react_dom.createPortal)(
11147
+ /* @__PURE__ */ jsx19(
11148
+ "div",
11149
+ {
11150
+ ref,
11151
+ role: "menu",
11152
+ "aria-label": "PCB context menu",
11153
+ className: menuStyle,
11154
+ onContextMenu: (event) => {
11155
+ event.preventDefault();
11156
+ event.stopPropagation();
11157
+ },
11158
+ onPointerDown: (event) => event.stopPropagation(),
11159
+ onMouseDown: (event) => event.stopPropagation(),
11160
+ onClick: (event) => event.stopPropagation(),
11161
+ onKeyDown: (event) => {
11162
+ event.stopPropagation();
11163
+ const button = event.target.closest("button");
11164
+ if (!button) return;
11165
+ const menu = button.closest('[role="menu"]');
11166
+ const items = Array.from(menu.querySelectorAll("button")).filter(
11167
+ (item) => item.closest('[role="menu"]') === menu
11168
+ );
11169
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
11170
+ event.preventDefault();
11171
+ const step = event.key === "ArrowDown" ? 1 : -1;
11172
+ items[(items.indexOf(button) + step + items.length) % items.length]?.focus();
11173
+ } else if (event.key === "ArrowRight" && button.hasAttribute("aria-haspopup")) {
11174
+ event.preventDefault();
11175
+ button.click();
11176
+ requestAnimationFrame(
11177
+ () => button.parentElement?.querySelector('[role="menu"] button')?.focus()
11178
+ );
11179
+ } else if (event.key === "ArrowLeft") {
11180
+ event.preventDefault();
11181
+ menu.parentElement?.querySelector(":scope > button")?.focus();
11182
+ if (menu.getAttribute("aria-label") === "Hidden Layer Visibility")
11183
+ setOpacityOpen(false);
11184
+ else if (menu.getAttribute("aria-label") === "Visibility")
11185
+ setVisibilityOpen(false);
11186
+ } else if (event.key === "Escape") {
11187
+ event.preventDefault();
11188
+ onClose();
11189
+ }
11190
+ },
11191
+ style: {
11192
+ position: "fixed",
11193
+ zIndex: 1e4,
11194
+ left: Math.max(
11195
+ openLeft ? 310 : 4,
11196
+ Math.min(position.x, window.innerWidth - (stacked ? 248 : 148))
11197
+ ),
11198
+ top: Math.max(
11199
+ 4,
11200
+ Math.min(position.y, window.innerHeight - (stacked ? 340 : 260))
11201
+ ),
11202
+ width: stacked ? 230 : 130,
11203
+ maxHeight: window.innerHeight - 8,
11204
+ ...stacked ? { overflowY: "auto" } : {}
11205
+ },
11206
+ children: /* @__PURE__ */ jsxs14(
11207
+ "div",
11208
+ {
11209
+ style: { position: "relative" },
11210
+ onMouseEnter: () => setVisibilityOpen(true),
11211
+ children: [
11212
+ /* @__PURE__ */ jsx19(
11213
+ "button",
11214
+ {
11215
+ type: "button",
11216
+ role: "menuitem",
11217
+ "aria-haspopup": "menu",
11218
+ "aria-expanded": visibilityOpen,
11219
+ className: itemStyle,
11220
+ onClick: () => setVisibilityOpen(true),
11221
+ children: "Visibility \u25B8"
11222
+ }
11223
+ ),
11224
+ visibilityOpen && /* @__PURE__ */ jsx19(
11225
+ "div",
11226
+ {
11227
+ role: "menu",
11228
+ "aria-label": "Visibility",
11229
+ className: menuStyle,
11230
+ style: submenuStyle,
11231
+ children: /* @__PURE__ */ jsxs14(
11232
+ "div",
11233
+ {
11234
+ style: { position: "relative" },
11235
+ onMouseEnter: () => setOpacityOpen(true),
11236
+ children: [
11237
+ /* @__PURE__ */ jsx19(
11238
+ "button",
11239
+ {
11240
+ type: "button",
11241
+ role: "menuitem",
11242
+ "aria-haspopup": "menu",
11243
+ "aria-expanded": opacityOpen,
11244
+ className: itemStyle,
11245
+ onClick: () => setOpacityOpen(true),
11246
+ children: "Hidden Layer Visibility \u25B8"
11247
+ }
11248
+ ),
11249
+ opacityOpen && /* @__PURE__ */ jsx19(
11250
+ "div",
11251
+ {
11252
+ role: "menu",
11253
+ "aria-label": "Hidden Layer Visibility",
11254
+ className: menuStyle,
11255
+ style: {
11256
+ minWidth: 80,
11257
+ ...submenuStyle
11258
+ },
11259
+ children: [0, 0.1, 0.2, 0.4, 0.6, 0.8, 1].map((value) => /* @__PURE__ */ jsxs14(
11260
+ "button",
11261
+ {
11262
+ type: "button",
11263
+ role: "menuitemradio",
11264
+ "aria-checked": opacity === value,
11265
+ className: itemStyle,
11266
+ onClick: () => {
11267
+ setOpacity(value);
11268
+ onClose();
11269
+ },
11270
+ children: [
11271
+ /* @__PURE__ */ jsx19(
11272
+ "span",
11273
+ {
11274
+ "aria-hidden": "true",
11275
+ style: { display: "inline-block", width: 16 },
11276
+ children: opacity === value ? "\u2713" : ""
11277
+ }
11278
+ ),
11279
+ value === 0 ? "Hide" : `${value * 100}%`
11280
+ ]
11281
+ },
11282
+ value
11283
+ ))
11284
+ }
11285
+ )
11286
+ ]
11287
+ }
11288
+ )
11289
+ }
11290
+ )
11291
+ ]
11292
+ }
11293
+ )
11294
+ }
11295
+ ),
11296
+ document.body
11297
+ );
11298
+ };
11299
+
10790
11300
  // src/components/ToolbarButton.tsx
10791
- import { jsx as jsx18 } from "react/jsx-runtime";
11301
+ import { jsx as jsx20 } from "react/jsx-runtime";
10792
11302
  var ToolbarButton = ({
10793
11303
  children,
10794
11304
  isSmallScreen,
@@ -10796,7 +11306,7 @@ var ToolbarButton = ({
10796
11306
  ...props
10797
11307
  }) => {
10798
11308
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
10799
- return /* @__PURE__ */ jsx18(
11309
+ return /* @__PURE__ */ jsx20(
10800
11310
  "div",
10801
11311
  {
10802
11312
  ...props,
@@ -10824,7 +11334,7 @@ var ToolbarButton = ({
10824
11334
  };
10825
11335
 
10826
11336
  // src/components/ToolbarErrorDropdown.tsx
10827
- import { useCallback as useCallback9, useMemo as useMemo7, useState as useState9 } from "react";
11337
+ import { useCallback as useCallback9, useMemo as useMemo8, useState as useState10 } from "react";
10828
11338
 
10829
11339
  // src/lib/util/group-errors-by-type.ts
10830
11340
  var groupErrorsByType = (errors) => {
@@ -10846,16 +11356,16 @@ var groupErrorsByType = (errors) => {
10846
11356
  };
10847
11357
 
10848
11358
  // src/components/useToolbarErrorFocus.ts
10849
- import { useCallback as useCallback8, useEffect as useEffect14, useRef as useRef11 } from "react";
11359
+ import { useCallback as useCallback8, useEffect as useEffect15, useRef as useRef12 } from "react";
10850
11360
  var useToolbarErrorFocus = ({
10851
11361
  onClose,
10852
11362
  setHoveredErrorId,
10853
11363
  setFocusedErrorId,
10854
11364
  highlightDurationMs = 3e3
10855
11365
  }) => {
10856
- const clearHighlightTimeoutRef = useRef11(null);
10857
- const focusRequestRef = useRef11(null);
10858
- const selectedErrorIdRef = useRef11(null);
11366
+ const clearHighlightTimeoutRef = useRef12(null);
11367
+ const focusRequestRef = useRef12(null);
11368
+ const selectedErrorIdRef = useRef12(null);
10859
11369
  const clearPendingSelection = useCallback8(() => {
10860
11370
  if (clearHighlightTimeoutRef.current !== null) {
10861
11371
  window.clearTimeout(clearHighlightTimeoutRef.current);
@@ -10866,7 +11376,7 @@ var useToolbarErrorFocus = ({
10866
11376
  focusRequestRef.current = null;
10867
11377
  }
10868
11378
  }, []);
10869
- useEffect14(() => clearPendingSelection, [clearPendingSelection]);
11379
+ useEffect15(() => clearPendingSelection, [clearPendingSelection]);
10870
11380
  const handleErrorSelect = useCallback8(
10871
11381
  (errorId) => {
10872
11382
  clearPendingSelection();
@@ -10904,7 +11414,7 @@ var useToolbarErrorFocus = ({
10904
11414
  };
10905
11415
 
10906
11416
  // src/components/ToolbarErrorDropdown.tsx
10907
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
11417
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
10908
11418
  var CopyErrorButton = ({
10909
11419
  errorId,
10910
11420
  errorMessage,
@@ -10914,7 +11424,7 @@ var CopyErrorButton = ({
10914
11424
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(
10915
11425
  () => onCopy(errorMessage, errorId)
10916
11426
  );
10917
- return /* @__PURE__ */ jsx19(
11427
+ return /* @__PURE__ */ jsx21(
10918
11428
  "button",
10919
11429
  {
10920
11430
  type: "button",
@@ -10934,7 +11444,7 @@ var CopyErrorButton = ({
10934
11444
  ...touchStyle
10935
11445
  },
10936
11446
  ...touchHandlers,
10937
- children: copiedErrorId === errorId ? /* @__PURE__ */ jsx19("span", { style: { color: "#4caf50", fontSize: 12 }, children: "Copied!" }) : /* @__PURE__ */ jsx19("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx19("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" }) })
11447
+ 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" }) })
10938
11448
  }
10939
11449
  );
10940
11450
  };
@@ -10947,11 +11457,11 @@ var ToolbarErrorDropdown = ({
10947
11457
  setHoveredErrorId,
10948
11458
  setFocusedErrorId
10949
11459
  }) => {
10950
- const [copiedErrorId, setCopiedErrorId] = useState9(null);
10951
- const [collapsedErrorGroups, setCollapsedErrorGroups] = useState9(
11460
+ const [copiedErrorId, setCopiedErrorId] = useState10(null);
11461
+ const [collapsedErrorGroups, setCollapsedErrorGroups] = useState10(
10952
11462
  /* @__PURE__ */ new Set()
10953
11463
  );
10954
- const [expandedErrorIds, setExpandedErrorIds] = useState9(
11464
+ const [expandedErrorIds, setExpandedErrorIds] = useState10(
10955
11465
  /* @__PURE__ */ new Set()
10956
11466
  );
10957
11467
  const [, copyToClipboard] = useCopyToClipboard_default();
@@ -10960,14 +11470,14 @@ var ToolbarErrorDropdown = ({
10960
11470
  setHoveredErrorId,
10961
11471
  setFocusedErrorId
10962
11472
  });
10963
- const errorElements = useMemo7(
11473
+ const errorElements = useMemo8(
10964
11474
  () => elements?.filter(
10965
11475
  (el) => el.type.includes("error")
10966
11476
  ) ?? [],
10967
11477
  [elements]
10968
11478
  );
10969
11479
  const errorCount = errorElements.length;
10970
- const groupedErrorElements = useMemo7(
11480
+ const groupedErrorElements = useMemo8(
10971
11481
  () => groupErrorsByType(errorElements),
10972
11482
  [errorElements]
10973
11483
  );
@@ -10993,20 +11503,20 @@ var ToolbarErrorDropdown = ({
10993
11503
  return next;
10994
11504
  });
10995
11505
  }, []);
10996
- return /* @__PURE__ */ jsxs13("div", { style: { position: "relative" }, children: [
10997
- /* @__PURE__ */ jsx19(
11506
+ return /* @__PURE__ */ jsxs15("div", { style: { position: "relative" }, children: [
11507
+ /* @__PURE__ */ jsx21(
10998
11508
  ToolbarButton,
10999
11509
  {
11000
11510
  isSmallScreen,
11001
11511
  style: errorCount > 0 ? { color: "red" } : void 0,
11002
11512
  onClick: onToggle,
11003
- children: /* @__PURE__ */ jsxs13("div", { children: [
11513
+ children: /* @__PURE__ */ jsxs15("div", { children: [
11004
11514
  errorCount,
11005
11515
  " errors"
11006
11516
  ] })
11007
11517
  }
11008
11518
  ),
11009
- isOpen && errorCount > 0 && /* @__PURE__ */ jsx19(
11519
+ isOpen && errorCount > 0 && /* @__PURE__ */ jsx21(
11010
11520
  "div",
11011
11521
  {
11012
11522
  style: {
@@ -11026,14 +11536,14 @@ var ToolbarErrorDropdown = ({
11026
11536
  },
11027
11537
  children: groupedErrorElements.map(({ errorType, errors }, groupIndex) => {
11028
11538
  const isGroupCollapsed = collapsedErrorGroups.has(errorType);
11029
- return /* @__PURE__ */ jsxs13(
11539
+ return /* @__PURE__ */ jsxs15(
11030
11540
  "div",
11031
11541
  {
11032
11542
  style: {
11033
11543
  borderBottom: groupIndex < groupedErrorElements.length - 1 ? "1px solid #444" : "none"
11034
11544
  },
11035
11545
  children: [
11036
- /* @__PURE__ */ jsxs13(
11546
+ /* @__PURE__ */ jsxs15(
11037
11547
  "div",
11038
11548
  {
11039
11549
  style: {
@@ -11070,7 +11580,7 @@ var ToolbarErrorDropdown = ({
11070
11580
  toggleErrorGroup(errorType);
11071
11581
  },
11072
11582
  children: [
11073
- /* @__PURE__ */ jsxs13(
11583
+ /* @__PURE__ */ jsxs15(
11074
11584
  "div",
11075
11585
  {
11076
11586
  style: {
@@ -11080,7 +11590,7 @@ var ToolbarErrorDropdown = ({
11080
11590
  color: "#ff6b6b"
11081
11591
  },
11082
11592
  children: [
11083
- /* @__PURE__ */ jsx19(
11593
+ /* @__PURE__ */ jsx21(
11084
11594
  "div",
11085
11595
  {
11086
11596
  style: {
@@ -11093,7 +11603,7 @@ var ToolbarErrorDropdown = ({
11093
11603
  children: "\u203A"
11094
11604
  }
11095
11605
  ),
11096
- /* @__PURE__ */ jsx19(
11606
+ /* @__PURE__ */ jsx21(
11097
11607
  "div",
11098
11608
  {
11099
11609
  style: {
@@ -11106,7 +11616,7 @@ var ToolbarErrorDropdown = ({
11106
11616
  ]
11107
11617
  }
11108
11618
  ),
11109
- /* @__PURE__ */ jsx19(
11619
+ /* @__PURE__ */ jsx21(
11110
11620
  "div",
11111
11621
  {
11112
11622
  style: {
@@ -11124,14 +11634,14 @@ var ToolbarErrorDropdown = ({
11124
11634
  !isGroupCollapsed && errors.map(({ error, index, errorId }) => {
11125
11635
  const isExpanded = expandedErrorIds.has(errorId);
11126
11636
  const errorMessage = error.message ?? "No error message";
11127
- return /* @__PURE__ */ jsxs13(
11637
+ return /* @__PURE__ */ jsxs15(
11128
11638
  "div",
11129
11639
  {
11130
11640
  style: {
11131
11641
  borderTop: "1px solid #3a3a3a"
11132
11642
  },
11133
11643
  children: [
11134
- /* @__PURE__ */ jsxs13(
11644
+ /* @__PURE__ */ jsxs15(
11135
11645
  "div",
11136
11646
  {
11137
11647
  style: {
@@ -11170,7 +11680,7 @@ var ToolbarErrorDropdown = ({
11170
11680
  handleErrorSelect(errorId);
11171
11681
  },
11172
11682
  children: [
11173
- /* @__PURE__ */ jsx19(
11683
+ /* @__PURE__ */ jsx21(
11174
11684
  "div",
11175
11685
  {
11176
11686
  style: {
@@ -11186,7 +11696,7 @@ var ToolbarErrorDropdown = ({
11186
11696
  children: errorMessage
11187
11697
  }
11188
11698
  ),
11189
- /* @__PURE__ */ jsx19(
11699
+ /* @__PURE__ */ jsx21(
11190
11700
  "button",
11191
11701
  {
11192
11702
  type: "button",
@@ -11218,7 +11728,7 @@ var ToolbarErrorDropdown = ({
11218
11728
  ]
11219
11729
  }
11220
11730
  ),
11221
- isExpanded && /* @__PURE__ */ jsxs13(
11731
+ isExpanded && /* @__PURE__ */ jsxs15(
11222
11732
  "div",
11223
11733
  {
11224
11734
  "data-error-id": index,
@@ -11230,7 +11740,7 @@ var ToolbarErrorDropdown = ({
11230
11740
  position: "relative"
11231
11741
  },
11232
11742
  children: [
11233
- /* @__PURE__ */ jsx19(
11743
+ /* @__PURE__ */ jsx21(
11234
11744
  "div",
11235
11745
  {
11236
11746
  style: {
@@ -11248,7 +11758,7 @@ var ToolbarErrorDropdown = ({
11248
11758
  children: errorMessage
11249
11759
  }
11250
11760
  ),
11251
- /* @__PURE__ */ jsx19(
11761
+ /* @__PURE__ */ jsx21(
11252
11762
  CopyErrorButton,
11253
11763
  {
11254
11764
  errorId,
@@ -11280,13 +11790,13 @@ var ToolbarErrorDropdown = ({
11280
11790
  };
11281
11791
 
11282
11792
  // src/components/ToolbarOverlay.tsx
11283
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
11793
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
11284
11794
  var LayerButton = ({ name, selected, onClick }) => {
11285
11795
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
11286
- return /* @__PURE__ */ jsxs14(
11796
+ return /* @__PURE__ */ jsxs16(
11287
11797
  "div",
11288
11798
  {
11289
- className: css2`
11799
+ className: css3`
11290
11800
  margin-top: 2px;
11291
11801
  padding: 4px;
11292
11802
  padding-left: 8px;
@@ -11300,8 +11810,8 @@ var LayerButton = ({ name, selected, onClick }) => {
11300
11810
  ...touchHandlers,
11301
11811
  style: touchStyle,
11302
11812
  children: [
11303
- /* @__PURE__ */ jsx20("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
11304
- /* @__PURE__ */ jsx20(
11813
+ /* @__PURE__ */ jsx22("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
11814
+ /* @__PURE__ */ jsx22(
11305
11815
  "span",
11306
11816
  {
11307
11817
  style: {
@@ -11322,10 +11832,10 @@ var CheckboxMenuItem = ({
11322
11832
  onClick
11323
11833
  }) => {
11324
11834
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
11325
- return /* @__PURE__ */ jsxs14(
11835
+ return /* @__PURE__ */ jsxs16(
11326
11836
  "div",
11327
11837
  {
11328
- className: css2`
11838
+ className: css3`
11329
11839
  margin-top: 2px;
11330
11840
  padding: 4px;
11331
11841
  padding-left: 8px;
@@ -11342,19 +11852,19 @@ var CheckboxMenuItem = ({
11342
11852
  ...touchHandlers,
11343
11853
  style: touchStyle,
11344
11854
  children: [
11345
- /* @__PURE__ */ jsx20("input", { type: "checkbox", checked, onChange: () => {
11855
+ /* @__PURE__ */ jsx22("input", { type: "checkbox", checked, onChange: () => {
11346
11856
  }, readOnly: true }),
11347
- /* @__PURE__ */ jsx20("span", { style: { color: "#eee" }, children: label })
11857
+ /* @__PURE__ */ jsx22("span", { style: { color: "#eee" }, children: label })
11348
11858
  ]
11349
11859
  }
11350
11860
  );
11351
11861
  };
11352
11862
  var RadioMenuItem = ({ label, checked, onClick }) => {
11353
11863
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
11354
- return /* @__PURE__ */ jsxs14(
11864
+ return /* @__PURE__ */ jsxs16(
11355
11865
  "div",
11356
11866
  {
11357
- className: css2`
11867
+ className: css3`
11358
11868
  margin-top: 2px;
11359
11869
  padding: 4px;
11360
11870
  padding-left: 8px;
@@ -11371,9 +11881,9 @@ var RadioMenuItem = ({ label, checked, onClick }) => {
11371
11881
  ...touchHandlers,
11372
11882
  style: touchStyle,
11373
11883
  children: [
11374
- /* @__PURE__ */ jsx20("input", { type: "radio", checked, onChange: () => {
11884
+ /* @__PURE__ */ jsx22("input", { type: "radio", checked, onChange: () => {
11375
11885
  }, readOnly: true }),
11376
- /* @__PURE__ */ jsx20("span", { style: { color: "#eee" }, children: label })
11886
+ /* @__PURE__ */ jsx22("span", { style: { color: "#eee" }, children: label })
11377
11887
  ]
11378
11888
  }
11379
11889
  );
@@ -11440,12 +11950,14 @@ var ToolbarOverlay = ({ children, elements }) => {
11440
11950
  setHoveredErrorId: s.setHoveredErrorId,
11441
11951
  setFocusedErrorId: s.setFocusedErrorId
11442
11952
  }));
11443
- const [isViewMenuOpen, setViewMenuOpen] = useState10(false);
11444
- const [isLayerMenuOpen, setLayerMenuOpen] = useState10(false);
11445
- const [isErrorsOpen, setErrorsOpen] = useState10(false);
11446
- const [measureToolArmed, setMeasureToolArmed] = useState10(false);
11447
- const [boundsToolArmed, setBoundsToolArmed] = useState10(false);
11448
- useEffect15(() => {
11953
+ const [contextMenuPosition, setContextMenuPosition] = useState11(null);
11954
+ const closeContextMenu = useCallback10(() => setContextMenuPosition(null), []);
11955
+ const [isViewMenuOpen, setViewMenuOpen] = useState11(false);
11956
+ const [isLayerMenuOpen, setLayerMenuOpen] = useState11(false);
11957
+ const [isErrorsOpen, setErrorsOpen] = useState11(false);
11958
+ const [measureToolArmed, setMeasureToolArmed] = useState11(false);
11959
+ const [boundsToolArmed, setBoundsToolArmed] = useState11(false);
11960
+ useEffect16(() => {
11449
11961
  const arm = () => setMeasureToolArmed(true);
11450
11962
  const disarm = () => setMeasureToolArmed(false);
11451
11963
  const armBounds = () => setBoundsToolArmed(true);
@@ -11463,8 +11975,8 @@ var ToolbarOverlay = ({ children, elements }) => {
11463
11975
  }, []);
11464
11976
  const availableLayers = getCopperLayerRefsFromElements(elements ?? []);
11465
11977
  const processedLayers = availableLayers;
11466
- const hasRunInitialMouseCheck = useRef12(false);
11467
- const hotkeyBoundaryRef = useRef12(null);
11978
+ const hasRunInitialMouseCheck = useRef13(false);
11979
+ const hotkeyBoundaryRef = useRef13(null);
11468
11980
  const hotKeyCallbacks = {
11469
11981
  "1": availableLayers[0] ? () => selectLayer(availableLayers[0]) : () => {
11470
11982
  },
@@ -11571,17 +12083,29 @@ var ToolbarOverlay = ({ children, elements }) => {
11571
12083
  },
11572
12084
  []
11573
12085
  );
11574
- return /* @__PURE__ */ jsxs14(
12086
+ return /* @__PURE__ */ jsxs16(
11575
12087
  "div",
11576
12088
  {
11577
12089
  ref: hotkeyBoundaryRef,
12090
+ onContextMenu: (event) => {
12091
+ event.preventDefault();
12092
+ event.stopPropagation();
12093
+ setContextMenuPosition({ x: event.clientX, y: event.clientY });
12094
+ },
11578
12095
  style: { position: "relative", zIndex: "999 !important" },
11579
12096
  onMouseEnter: handleMouseEnter,
11580
12097
  onMouseLeave: handleMouseLeave,
11581
12098
  onMouseMove: handleMouseMove,
11582
12099
  children: [
11583
12100
  children,
11584
- /* @__PURE__ */ jsxs14(
12101
+ contextMenuPosition && /* @__PURE__ */ jsx22(
12102
+ VisibilityContextMenu,
12103
+ {
12104
+ position: contextMenuPosition,
12105
+ onClose: closeContextMenu
12106
+ }
12107
+ ),
12108
+ /* @__PURE__ */ jsxs16(
11585
12109
  "div",
11586
12110
  {
11587
12111
  style: {
@@ -11602,7 +12126,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11602
12126
  ]
11603
12127
  }
11604
12128
  ),
11605
- /* @__PURE__ */ jsxs14(
12129
+ /* @__PURE__ */ jsxs16(
11606
12130
  "div",
11607
12131
  {
11608
12132
  "data-toolbar-overlay": true,
@@ -11633,7 +12157,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11633
12157
  fontFamily: "sans-serif"
11634
12158
  },
11635
12159
  children: [
11636
- /* @__PURE__ */ jsxs14(
12160
+ /* @__PURE__ */ jsxs16(
11637
12161
  ToolbarButton,
11638
12162
  {
11639
12163
  isSmallScreen,
@@ -11644,10 +12168,10 @@ var ToolbarOverlay = ({ children, elements }) => {
11644
12168
  }
11645
12169
  },
11646
12170
  children: [
11647
- /* @__PURE__ */ jsxs14("div", { children: [
12171
+ /* @__PURE__ */ jsxs16("div", { children: [
11648
12172
  "layer:",
11649
12173
  " ",
11650
- /* @__PURE__ */ jsx20(
12174
+ /* @__PURE__ */ jsx22(
11651
12175
  "span",
11652
12176
  {
11653
12177
  style: {
@@ -11659,7 +12183,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11659
12183
  }
11660
12184
  )
11661
12185
  ] }),
11662
- isLayerMenuOpen && /* @__PURE__ */ jsx20("div", { style: { marginTop: 4, minWidth: 120 }, children: processedLayers.map((layer) => /* @__PURE__ */ jsx20(
12186
+ isLayerMenuOpen && /* @__PURE__ */ jsx22("div", { style: { marginTop: 4, minWidth: 120 }, children: processedLayers.map((layer) => /* @__PURE__ */ jsx22(
11663
12187
  LayerButton,
11664
12188
  {
11665
12189
  name: layer,
@@ -11673,7 +12197,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11673
12197
  ]
11674
12198
  }
11675
12199
  ),
11676
- /* @__PURE__ */ jsx20(
12200
+ /* @__PURE__ */ jsx22(
11677
12201
  ToolbarErrorDropdown,
11678
12202
  {
11679
12203
  elements,
@@ -11685,43 +12209,43 @@ var ToolbarOverlay = ({ children, elements }) => {
11685
12209
  setFocusedErrorId
11686
12210
  }
11687
12211
  ),
11688
- /* @__PURE__ */ jsx20(
12212
+ /* @__PURE__ */ jsx22(
11689
12213
  ToolbarButton,
11690
12214
  {
11691
12215
  isSmallScreen,
11692
12216
  style: {},
11693
12217
  onClick: handleRatsNestToggle,
11694
- children: /* @__PURE__ */ jsxs14("div", { children: [
12218
+ children: /* @__PURE__ */ jsxs16("div", { children: [
11695
12219
  viewSettings.is_showing_rats_nest ? "\u2716 " : "",
11696
12220
  "Rats Nest"
11697
12221
  ] })
11698
12222
  }
11699
12223
  ),
11700
- /* @__PURE__ */ jsx20(
12224
+ /* @__PURE__ */ jsx22(
11701
12225
  ToolbarButton,
11702
12226
  {
11703
12227
  isSmallScreen,
11704
12228
  style: measureToolArmed ? { backgroundColor: "#444" } : {},
11705
12229
  onClick: handleMeasureToolClick,
11706
- children: /* @__PURE__ */ jsx20("div", { children: "\u{1F4CF}" })
12230
+ children: /* @__PURE__ */ jsx22("div", { children: "\u{1F4CF}" })
11707
12231
  }
11708
12232
  ),
11709
- /* @__PURE__ */ jsx20(
12233
+ /* @__PURE__ */ jsx22(
11710
12234
  ToolbarButton,
11711
12235
  {
11712
12236
  isSmallScreen,
11713
12237
  style: boundsToolArmed ? { backgroundColor: "#444" } : {},
11714
12238
  onClick: handleBoundsToolClick,
11715
- children: /* @__PURE__ */ jsx20("div", { children: "Bounds" })
12239
+ children: /* @__PURE__ */ jsx22("div", { children: "Bounds" })
11716
12240
  }
11717
12241
  ),
11718
- /* @__PURE__ */ jsx20(
12242
+ /* @__PURE__ */ jsx22(
11719
12243
  ToolbarButton,
11720
12244
  {
11721
12245
  isSmallScreen,
11722
12246
  onClick: handleViewMenuToggle,
11723
- children: /* @__PURE__ */ jsxs14("div", { children: [
11724
- /* @__PURE__ */ jsxs14(
12247
+ children: /* @__PURE__ */ jsxs16("div", { children: [
12248
+ /* @__PURE__ */ jsxs16(
11725
12249
  "div",
11726
12250
  {
11727
12251
  style: {
@@ -11731,7 +12255,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11731
12255
  },
11732
12256
  children: [
11733
12257
  "View",
11734
- /* @__PURE__ */ jsx20(
12258
+ /* @__PURE__ */ jsx22(
11735
12259
  "span",
11736
12260
  {
11737
12261
  style: {
@@ -11746,8 +12270,8 @@ var ToolbarOverlay = ({ children, elements }) => {
11746
12270
  ]
11747
12271
  }
11748
12272
  ),
11749
- isViewMenuOpen && /* @__PURE__ */ jsxs14("div", { style: { marginTop: 4, minWidth: 120 }, children: [
11750
- /* @__PURE__ */ jsx20(
12273
+ isViewMenuOpen && /* @__PURE__ */ jsxs16("div", { style: { marginTop: 4, minWidth: 120 }, children: [
12274
+ /* @__PURE__ */ jsx22(
11751
12275
  CheckboxMenuItem,
11752
12276
  {
11753
12277
  label: "Show All Trace Lengths",
@@ -11759,7 +12283,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11759
12283
  }
11760
12284
  }
11761
12285
  ),
11762
- /* @__PURE__ */ jsx20(
12286
+ /* @__PURE__ */ jsx22(
11763
12287
  CheckboxMenuItem,
11764
12288
  {
11765
12289
  label: "Show Autorouting Animation",
@@ -11771,7 +12295,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11771
12295
  }
11772
12296
  }
11773
12297
  ),
11774
- /* @__PURE__ */ jsx20(
12298
+ /* @__PURE__ */ jsx22(
11775
12299
  CheckboxMenuItem,
11776
12300
  {
11777
12301
  label: "Show DRC Errors",
@@ -11781,7 +12305,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11781
12305
  }
11782
12306
  }
11783
12307
  ),
11784
- /* @__PURE__ */ jsx20(
12308
+ /* @__PURE__ */ jsx22(
11785
12309
  CheckboxMenuItem,
11786
12310
  {
11787
12311
  label: "Show DRC Warnings",
@@ -11793,7 +12317,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11793
12317
  }
11794
12318
  }
11795
12319
  ),
11796
- /* @__PURE__ */ jsx20(
12320
+ /* @__PURE__ */ jsx22(
11797
12321
  CheckboxMenuItem,
11798
12322
  {
11799
12323
  label: "Show Copper Pours",
@@ -11805,7 +12329,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11805
12329
  }
11806
12330
  }
11807
12331
  ),
11808
- /* @__PURE__ */ jsx20(
12332
+ /* @__PURE__ */ jsx22(
11809
12333
  CheckboxMenuItem,
11810
12334
  {
11811
12335
  label: "Show Courtyards",
@@ -11815,7 +12339,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11815
12339
  }
11816
12340
  }
11817
12341
  ),
11818
- /* @__PURE__ */ jsx20(
12342
+ /* @__PURE__ */ jsx22(
11819
12343
  CheckboxMenuItem,
11820
12344
  {
11821
12345
  label: "Show Solder Mask",
@@ -11825,7 +12349,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11825
12349
  }
11826
12350
  }
11827
12351
  ),
11828
- /* @__PURE__ */ jsx20(
12352
+ /* @__PURE__ */ jsx22(
11829
12353
  CheckboxMenuItem,
11830
12354
  {
11831
12355
  label: "Show Silkscreen",
@@ -11835,7 +12359,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11835
12359
  }
11836
12360
  }
11837
12361
  ),
11838
- /* @__PURE__ */ jsx20(
12362
+ /* @__PURE__ */ jsx22(
11839
12363
  CheckboxMenuItem,
11840
12364
  {
11841
12365
  label: "Show Fabrication Notes",
@@ -11847,7 +12371,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11847
12371
  }
11848
12372
  }
11849
12373
  ),
11850
- /* @__PURE__ */ jsx20(
12374
+ /* @__PURE__ */ jsx22(
11851
12375
  CheckboxMenuItem,
11852
12376
  {
11853
12377
  label: "Show PCB Notes",
@@ -11857,7 +12381,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11857
12381
  }
11858
12382
  }
11859
12383
  ),
11860
- /* @__PURE__ */ jsx20(
12384
+ /* @__PURE__ */ jsx22(
11861
12385
  CheckboxMenuItem,
11862
12386
  {
11863
12387
  label: "Show Group Anchor Offsets",
@@ -11869,7 +12393,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11869
12393
  }
11870
12394
  }
11871
12395
  ),
11872
- /* @__PURE__ */ jsx20(
12396
+ /* @__PURE__ */ jsx22(
11873
12397
  CheckboxMenuItem,
11874
12398
  {
11875
12399
  label: "Show PCB Groups",
@@ -11879,8 +12403,8 @@ var ToolbarOverlay = ({ children, elements }) => {
11879
12403
  }
11880
12404
  }
11881
12405
  ),
11882
- viewSettings.is_showing_pcb_groups && /* @__PURE__ */ jsxs14("div", { style: { marginLeft: 16 }, children: [
11883
- /* @__PURE__ */ jsx20(
12406
+ viewSettings.is_showing_pcb_groups && /* @__PURE__ */ jsxs16("div", { style: { marginLeft: 16 }, children: [
12407
+ /* @__PURE__ */ jsx22(
11884
12408
  RadioMenuItem,
11885
12409
  {
11886
12410
  label: "Show All Groups",
@@ -11890,7 +12414,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11890
12414
  }
11891
12415
  }
11892
12416
  ),
11893
- /* @__PURE__ */ jsx20(
12417
+ /* @__PURE__ */ jsx22(
11894
12418
  RadioMenuItem,
11895
12419
  {
11896
12420
  label: "Show Named Groups",
@@ -11914,7 +12438,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11914
12438
  };
11915
12439
 
11916
12440
  // src/components/WarningGraphicsOverlay.tsx
11917
- import { useEffect as useEffect16, useRef as useRef13 } from "react";
12441
+ import { useEffect as useEffect17, useRef as useRef14 } from "react";
11918
12442
  import { applyToPoint as applyToPoint18, identity as identity8 } from "transformation-matrix";
11919
12443
 
11920
12444
  // src/lib/util/get-pcb-warning-highlight.ts
@@ -11927,18 +12451,18 @@ var getPcbWarningHighlightLabel = (warning) => {
11927
12451
  };
11928
12452
 
11929
12453
  // src/components/WarningGraphicsOverlay.tsx
11930
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
12454
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
11931
12455
  var WarningGraphicsOverlay = ({
11932
12456
  children,
11933
12457
  transform = identity8(),
11934
12458
  elements = []
11935
12459
  }) => {
11936
12460
  const [containerRef, { width, height }] = useMeasure_default();
11937
- const canvasRef = useRef13(null);
12461
+ const canvasRef = useRef14(null);
11938
12462
  const isShowingDrcWarnings = useGlobalStore(
11939
12463
  (state) => state.is_showing_drc_warnings
11940
12464
  );
11941
- useEffect16(() => {
12465
+ useEffect17(() => {
11942
12466
  const canvas = canvasRef.current;
11943
12467
  if (!canvas || !width || !height) return;
11944
12468
  canvas.width = width;
@@ -11989,7 +12513,7 @@ var WarningGraphicsOverlay = ({
11989
12513
  });
11990
12514
  }, [elements, transform, width, height, isShowingDrcWarnings]);
11991
12515
  if (!isShowingDrcWarnings) {
11992
- return /* @__PURE__ */ jsx21(
12516
+ return /* @__PURE__ */ jsx23(
11993
12517
  "div",
11994
12518
  {
11995
12519
  ref: containerRef,
@@ -11998,14 +12522,14 @@ var WarningGraphicsOverlay = ({
11998
12522
  }
11999
12523
  );
12000
12524
  }
12001
- return /* @__PURE__ */ jsxs15(
12525
+ return /* @__PURE__ */ jsxs17(
12002
12526
  "div",
12003
12527
  {
12004
12528
  ref: containerRef,
12005
12529
  style: { position: "relative", width: "100%", height: "100%" },
12006
12530
  children: [
12007
12531
  children,
12008
- /* @__PURE__ */ jsx21(
12532
+ /* @__PURE__ */ jsx23(
12009
12533
  "canvas",
12010
12534
  {
12011
12535
  ref: canvasRef,
@@ -12024,7 +12548,7 @@ var WarningGraphicsOverlay = ({
12024
12548
  };
12025
12549
 
12026
12550
  // src/components/CanvasElementsRenderer.tsx
12027
- import { jsx as jsx22 } from "react/jsx-runtime";
12551
+ import { jsx as jsx24 } from "react/jsx-runtime";
12028
12552
  var CanvasElementsRenderer = (props) => {
12029
12553
  const { transform, elements } = props;
12030
12554
  const {
@@ -12039,11 +12563,11 @@ var CanvasElementsRenderer = (props) => {
12039
12563
  selectedLayer: state.selected_layer
12040
12564
  }));
12041
12565
  const activeErrorId = focusedErrorId ?? hoveredErrorId;
12042
- const elementsToRender = useMemo8(
12566
+ const elementsToRender = useMemo9(
12043
12567
  () => isShowingCopperPours ? elements : elements.filter((elm) => elm.type !== "pcb_copper_pour"),
12044
12568
  [elements, isShowingCopperPours]
12045
12569
  );
12046
- const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo8(() => {
12570
+ const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo9(() => {
12047
12571
  const primitivesWithoutInteractionMetadata2 = elementsToRender.flatMap(
12048
12572
  (elm) => convertElementToPrimitives(elm, props.elements)
12049
12573
  );
@@ -12052,18 +12576,18 @@ var CanvasElementsRenderer = (props) => {
12052
12576
  );
12053
12577
  return [primitivesWithoutInteractionMetadata2, connectivityMap2];
12054
12578
  }, [elementsToRender, props.elements]);
12055
- const [hoverState, setHoverState] = useState11({
12579
+ const [hoverState, setHoverState] = useState12({
12056
12580
  drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
12057
12581
  primitiveIdsInMousedOverNet: []
12058
12582
  });
12059
- const [hoveredComponentIds, setHoveredComponentIds] = useState11([]);
12060
- const currentTransformRef = useRef14(transform ?? null);
12061
- const zoomAnimationFrameRef = useRef14(null);
12062
- const elementIndexes = useMemo8(
12583
+ const [hoveredComponentIds, setHoveredComponentIds] = useState12([]);
12584
+ const currentTransformRef = useRef15(transform ?? null);
12585
+ const zoomAnimationFrameRef = useRef15(null);
12586
+ const elementIndexes = useMemo9(
12063
12587
  () => buildErrorPreviewElementIndexes(elements),
12064
12588
  [elements]
12065
12589
  );
12066
- const errorRelatedIds = useMemo8(() => {
12590
+ const errorRelatedIds = useMemo9(() => {
12067
12591
  if (!activeErrorId) return [];
12068
12592
  const errorElements = elements.filter(
12069
12593
  (el) => el.type.includes("error")
@@ -12074,17 +12598,17 @@ var CanvasElementsRenderer = (props) => {
12074
12598
  if (!activeError) return [];
12075
12599
  return getRelatedIdsForError(activeError);
12076
12600
  }, [activeErrorId, elements]);
12077
- useEffect17(() => {
12601
+ useEffect18(() => {
12078
12602
  if (transform) {
12079
12603
  currentTransformRef.current = transform;
12080
12604
  }
12081
12605
  }, [transform]);
12082
- useEffect17(() => {
12606
+ useEffect18(() => {
12083
12607
  return () => {
12084
12608
  cancelTransformAnimation(zoomAnimationFrameRef.current);
12085
12609
  };
12086
12610
  }, []);
12087
- useEffect17(() => {
12611
+ useEffect18(() => {
12088
12612
  if (!props.width || !props.height || !props.setTransform || !focusedErrorId)
12089
12613
  return;
12090
12614
  const focusedError = findErrorElementById(elements, focusedErrorId);
@@ -12122,7 +12646,7 @@ var CanvasElementsRenderer = (props) => {
12122
12646
  props.setTransform,
12123
12647
  props.width
12124
12648
  ]);
12125
- const primitives = useMemo8(() => {
12649
+ const primitives = useMemo9(() => {
12126
12650
  const combinedPrimitiveIds = [
12127
12651
  ...hoverState.primitiveIdsInMousedOverNet,
12128
12652
  ...errorRelatedIds
@@ -12166,7 +12690,7 @@ var CanvasElementsRenderer = (props) => {
12166
12690
  },
12167
12691
  [connectivityMap]
12168
12692
  );
12169
- return /* @__PURE__ */ jsx22(
12693
+ return /* @__PURE__ */ jsx24(
12170
12694
  MouseElementTracker,
12171
12695
  {
12172
12696
  elements: elementsToRender,
@@ -12174,7 +12698,7 @@ var CanvasElementsRenderer = (props) => {
12174
12698
  primitives: primitivesWithoutInteractionMetadata,
12175
12699
  selectedLayer,
12176
12700
  onMouseHoverOverPrimitives: onMouseOverPrimitives,
12177
- children: /* @__PURE__ */ jsx22(
12701
+ children: /* @__PURE__ */ jsx24(
12178
12702
  EditPlacementOverlay,
12179
12703
  {
12180
12704
  disabled: !props.allowEditing,
@@ -12183,7 +12707,7 @@ var CanvasElementsRenderer = (props) => {
12183
12707
  cancelPanDrag: props.cancelPanDrag,
12184
12708
  onCreateEditEvent: props.onCreateEditEvent,
12185
12709
  onModifyEditEvent: props.onModifyEditEvent,
12186
- children: /* @__PURE__ */ jsx22(
12710
+ children: /* @__PURE__ */ jsx24(
12187
12711
  DimensionOverlay,
12188
12712
  {
12189
12713
  transform,
@@ -12191,23 +12715,23 @@ var CanvasElementsRenderer = (props) => {
12191
12715
  primitives: primitivesWithoutInteractionMetadata,
12192
12716
  onBoundsSelected: props.onBoundsSelected,
12193
12717
  cancelPanDrag: props.cancelPanDrag,
12194
- children: /* @__PURE__ */ jsx22(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx22(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx22(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx22(
12718
+ children: /* @__PURE__ */ jsx24(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx24(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx24(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx24(
12195
12719
  PcbGroupOverlay,
12196
12720
  {
12197
12721
  transform,
12198
12722
  elements,
12199
12723
  hoveredComponentIds,
12200
- children: /* @__PURE__ */ jsx22(
12724
+ children: /* @__PURE__ */ jsx24(
12201
12725
  DebugGraphicsOverlay,
12202
12726
  {
12203
12727
  transform,
12204
12728
  debugGraphics: props.debugGraphics,
12205
- children: /* @__PURE__ */ jsx22(
12729
+ children: /* @__PURE__ */ jsx24(
12206
12730
  WarningGraphicsOverlay,
12207
12731
  {
12208
12732
  transform,
12209
12733
  elements,
12210
- children: /* @__PURE__ */ jsx22(
12734
+ children: /* @__PURE__ */ jsx24(
12211
12735
  CanvasPrimitiveRenderer,
12212
12736
  {
12213
12737
  transform,
@@ -12287,7 +12811,7 @@ var calculateBoardSizeKey = (circuitJson) => {
12287
12811
  };
12288
12812
 
12289
12813
  // src/PCBViewer.tsx
12290
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
12814
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
12291
12815
  var defaultTransform = compose8(translate12(400, 300), scale6(40, -40));
12292
12816
  var PCBViewer = ({
12293
12817
  circuitJson,
@@ -12302,11 +12826,11 @@ var PCBViewer = ({
12302
12826
  clickToInteractEnabled = false,
12303
12827
  disablePcbGroups = false
12304
12828
  }) => {
12305
- const [isInteractionEnabled, setIsInteractionEnabled] = useState12(
12829
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState13(
12306
12830
  !clickToInteractEnabled
12307
12831
  );
12308
12832
  const [ref, refDimensions] = useMeasure_default();
12309
- const [transform, setTransformInternal] = useState12(defaultTransform);
12833
+ const [transform, setTransformInternal] = useState13(defaultTransform);
12310
12834
  const shouldAllowCanvasInteraction = useCallback12(
12311
12835
  (event) => {
12312
12836
  const target = event.target;
@@ -12325,11 +12849,11 @@ var PCBViewer = ({
12325
12849
  enabled: isInteractionEnabled,
12326
12850
  shouldDrag: shouldAllowCanvasInteraction
12327
12851
  });
12328
- let [editEvents, setEditEvents] = useState12([]);
12852
+ let [editEvents, setEditEvents] = useState13([]);
12329
12853
  editEvents = editEventsProp ?? editEvents;
12330
- const initialRenderCompleted = useRef15(false);
12331
- const touchStartRef = useRef15(null);
12332
- const circuitJsonKey = useMemo9(
12854
+ const initialRenderCompleted = useRef16(false);
12855
+ const touchStartRef = useRef16(null);
12856
+ const circuitJsonKey = useMemo10(
12333
12857
  () => calculateCircuitJsonKey(circuitJson),
12334
12858
  [circuitJson]
12335
12859
  );
@@ -12354,7 +12878,7 @@ var PCBViewer = ({
12354
12878
  setTransform(targetTransform);
12355
12879
  return;
12356
12880
  };
12357
- useEffect18(() => {
12881
+ useEffect19(() => {
12358
12882
  if (!refDimensions?.width) return;
12359
12883
  if (!circuitJson) return;
12360
12884
  if (circuitJson.length === 0) return;
@@ -12363,17 +12887,17 @@ var PCBViewer = ({
12363
12887
  initialRenderCompleted.current = true;
12364
12888
  }
12365
12889
  }, [circuitJson, refDimensions]);
12366
- useEffect18(() => {
12890
+ useEffect19(() => {
12367
12891
  if (initialRenderCompleted.current === true) {
12368
12892
  resetTransform();
12369
12893
  }
12370
12894
  }, [boardSizeKey]);
12371
- const pcbElmsPreEdit = useMemo9(() => {
12895
+ const pcbElmsPreEdit = useMemo10(() => {
12372
12896
  return circuitJson?.filter(
12373
12897
  (e) => e.type.startsWith("pcb_") || e.type.startsWith("source_")
12374
12898
  ) ?? [];
12375
12899
  }, [circuitJsonKey]);
12376
- const elements = useMemo9(() => {
12900
+ const elements = useMemo10(() => {
12377
12901
  return applyEditEvents({
12378
12902
  circuitJson: pcbElmsPreEdit,
12379
12903
  editEvents
@@ -12390,27 +12914,27 @@ var PCBViewer = ({
12390
12914
  setEditEvents(newEditEvents);
12391
12915
  onEditEventsChanged?.(newEditEvents);
12392
12916
  };
12393
- const mergedInitialState = useMemo9(
12917
+ const mergedInitialState = useMemo10(
12394
12918
  () => ({
12395
12919
  ...initialState,
12396
12920
  ...disablePcbGroups && { is_showing_pcb_groups: false }
12397
12921
  }),
12398
12922
  [initialState, disablePcbGroups]
12399
12923
  );
12400
- return /* @__PURE__ */ jsxs16(
12924
+ return /* @__PURE__ */ jsxs18(
12401
12925
  "div",
12402
12926
  {
12403
12927
  ref: transformRef,
12404
12928
  style: { position: "relative" },
12405
12929
  onContextMenu: (event) => event.preventDefault(),
12406
12930
  children: [
12407
- /* @__PURE__ */ jsx23("div", { ref, children: /* @__PURE__ */ jsxs16(
12931
+ /* @__PURE__ */ jsx25("div", { ref, children: /* @__PURE__ */ jsxs18(
12408
12932
  ContextProviders,
12409
12933
  {
12410
12934
  initialState: mergedInitialState,
12411
12935
  disablePcbGroups,
12412
12936
  children: [
12413
- /* @__PURE__ */ jsx23(
12937
+ /* @__PURE__ */ jsx25(
12414
12938
  CanvasElementsRenderer,
12415
12939
  {
12416
12940
  transform,
@@ -12437,11 +12961,11 @@ var PCBViewer = ({
12437
12961
  },
12438
12962
  refDimensions.width
12439
12963
  ),
12440
- /* @__PURE__ */ jsx23(ToastContainer, {})
12964
+ /* @__PURE__ */ jsx25(ToastContainer, {})
12441
12965
  ]
12442
12966
  }
12443
12967
  ) }),
12444
- clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx23(
12968
+ clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx25(
12445
12969
  "div",
12446
12970
  {
12447
12971
  onClick: () => {
@@ -12478,7 +13002,7 @@ var PCBViewer = ({
12478
13002
  justifyContent: "center",
12479
13003
  touchAction: "pan-x pan-y pinch-zoom"
12480
13004
  },
12481
- children: /* @__PURE__ */ jsx23(
13005
+ children: /* @__PURE__ */ jsx25(
12482
13006
  "div",
12483
13007
  {
12484
13008
  style: {
@@ -12511,5 +13035,16 @@ svgson/dist/svgson.umd.js:
12511
13035
  * @author Feross Aboukhadijeh <https://feross.org>
12512
13036
  * @license MIT
12513
13037
  *)
13038
+
13039
+ react-dom/cjs/react-dom.development.js:
13040
+ (**
13041
+ * @license React
13042
+ * react-dom.development.js
13043
+ *
13044
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
13045
+ *
13046
+ * This source code is licensed under the MIT license found in the
13047
+ * LICENSE file in the root directory of this source tree.
13048
+ *)
12514
13049
  */
12515
13050
  //# sourceMappingURL=index.js.map