@tscircuit/pcb-viewer 1.11.394 → 1.11.395

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 useMemo9, 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 useMemo8, 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,
@@ -10619,18 +10898,18 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
10619
10898
 
10620
10899
  // src/components/ToolbarOverlay.tsx
10621
10900
  import {
10622
- useEffect as useEffect15,
10623
- useState as useState10,
10901
+ useEffect as useEffect16,
10902
+ useState as useState11,
10624
10903
  useCallback as useCallback10,
10625
- useRef as useRef12,
10904
+ useRef as useRef13,
10626
10905
  useLayoutEffect as useLayoutEffect2
10627
10906
  } from "react";
10628
- import { css as css2 } from "@emotion/css";
10907
+ import { css as css3 } from "@emotion/css";
10629
10908
 
10630
10909
  // package.json
10631
10910
  var package_default = {
10632
10911
  name: "@tscircuit/pcb-viewer",
10633
- version: "1.11.393",
10912
+ version: "1.11.394",
10634
10913
  main: "dist/index.js",
10635
10914
  type: "module",
10636
10915
  repository: {
@@ -10663,6 +10942,7 @@ var package_default = {
10663
10942
  "@types/color": "^3.0.6",
10664
10943
  "@types/node": "18.7.23",
10665
10944
  "@types/react": "19",
10945
+ "@types/react-dom": "~19.1.0",
10666
10946
  "format-si-unit": "^0.0.12",
10667
10947
  next: "^14.1.4",
10668
10948
  "pixi.js": "^8.6.6",
@@ -10787,8 +11067,228 @@ var useMobileTouch = (onClick, options = { stopPropagation: true }) => {
10787
11067
  };
10788
11068
  };
10789
11069
 
11070
+ // src/components/VisibilityContextMenu.tsx
11071
+ var import_react_dom = __toESM(require_react_dom(), 1);
11072
+ import { css as css2 } from "@emotion/css";
11073
+ import { useEffect as useEffect14, useRef as useRef11, useState as useState9 } from "react";
11074
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
11075
+ var menuStyle = css2`
11076
+ background: #222;
11077
+ color: #eee;
11078
+ border: 1px solid #555;
11079
+ border-radius: 4px;
11080
+ padding: 4px;
11081
+ font: 12px sans-serif;
11082
+ box-shadow: 0 4px 16px #0008;
11083
+ `;
11084
+ var itemStyle = css2`
11085
+ display: block;
11086
+ width: 100%;
11087
+ padding: 8px;
11088
+ border: 0;
11089
+ border-radius: 2px;
11090
+ background: transparent;
11091
+ color: inherit;
11092
+ font: inherit;
11093
+ text-align: left;
11094
+ white-space: nowrap;
11095
+ cursor: pointer;
11096
+ &:hover, &:focus-visible { background: #444; }
11097
+ `;
11098
+ var VisibilityContextMenu = ({
11099
+ position,
11100
+ onClose
11101
+ }) => {
11102
+ const opacity = useGlobalStore((s) => s.hidden_layer_opacity);
11103
+ const setOpacity = useGlobalStore((s) => s.setHiddenLayerOpacity);
11104
+ const [visibilityOpen, setVisibilityOpen] = useState9(false);
11105
+ const [opacityOpen, setOpacityOpen] = useState9(false);
11106
+ const ref = useRef11(null);
11107
+ const stacked = window.innerWidth < 480;
11108
+ const openLeft = !stacked && position.x + 460 > window.innerWidth;
11109
+ const submenuStyle = stacked ? { position: "relative" } : {
11110
+ position: "absolute",
11111
+ top: 0,
11112
+ ...openLeft ? { right: "100%" } : { left: "100%" }
11113
+ };
11114
+ useEffect14(() => {
11115
+ const dismiss = (event) => {
11116
+ if (!ref.current?.contains(event.target)) onClose();
11117
+ };
11118
+ const onKeyDown = (event) => {
11119
+ if (event.key === "Escape") {
11120
+ event.preventDefault();
11121
+ onClose();
11122
+ }
11123
+ };
11124
+ ref.current?.querySelector("button")?.focus();
11125
+ window.addEventListener("pointerdown", dismiss, true);
11126
+ window.addEventListener("keydown", onKeyDown);
11127
+ window.addEventListener("resize", onClose);
11128
+ window.addEventListener("scroll", onClose, true);
11129
+ return () => {
11130
+ window.removeEventListener("pointerdown", dismiss, true);
11131
+ window.removeEventListener("keydown", onKeyDown);
11132
+ window.removeEventListener("resize", onClose);
11133
+ window.removeEventListener("scroll", onClose, true);
11134
+ };
11135
+ }, [onClose]);
11136
+ return (0, import_react_dom.createPortal)(
11137
+ /* @__PURE__ */ jsx18(
11138
+ "div",
11139
+ {
11140
+ ref,
11141
+ role: "menu",
11142
+ "aria-label": "PCB context menu",
11143
+ className: menuStyle,
11144
+ onContextMenu: (event) => {
11145
+ event.preventDefault();
11146
+ event.stopPropagation();
11147
+ },
11148
+ onPointerDown: (event) => event.stopPropagation(),
11149
+ onMouseDown: (event) => event.stopPropagation(),
11150
+ onClick: (event) => event.stopPropagation(),
11151
+ onKeyDown: (event) => {
11152
+ event.stopPropagation();
11153
+ const button = event.target.closest("button");
11154
+ if (!button) return;
11155
+ const menu = button.closest('[role="menu"]');
11156
+ const items = Array.from(menu.querySelectorAll("button")).filter(
11157
+ (item) => item.closest('[role="menu"]') === menu
11158
+ );
11159
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
11160
+ event.preventDefault();
11161
+ const step = event.key === "ArrowDown" ? 1 : -1;
11162
+ items[(items.indexOf(button) + step + items.length) % items.length]?.focus();
11163
+ } else if (event.key === "ArrowRight" && button.hasAttribute("aria-haspopup")) {
11164
+ event.preventDefault();
11165
+ button.click();
11166
+ requestAnimationFrame(
11167
+ () => button.parentElement?.querySelector('[role="menu"] button')?.focus()
11168
+ );
11169
+ } else if (event.key === "ArrowLeft") {
11170
+ event.preventDefault();
11171
+ menu.parentElement?.querySelector(":scope > button")?.focus();
11172
+ if (menu.getAttribute("aria-label") === "Hidden Layer Visibility")
11173
+ setOpacityOpen(false);
11174
+ else if (menu.getAttribute("aria-label") === "Visibility")
11175
+ setVisibilityOpen(false);
11176
+ } else if (event.key === "Escape") {
11177
+ event.preventDefault();
11178
+ onClose();
11179
+ }
11180
+ },
11181
+ style: {
11182
+ position: "fixed",
11183
+ zIndex: 1e4,
11184
+ left: Math.max(
11185
+ openLeft ? 310 : 4,
11186
+ Math.min(position.x, window.innerWidth - (stacked ? 248 : 148))
11187
+ ),
11188
+ top: Math.max(
11189
+ 4,
11190
+ Math.min(position.y, window.innerHeight - (stacked ? 340 : 260))
11191
+ ),
11192
+ width: stacked ? 230 : 130,
11193
+ maxHeight: window.innerHeight - 8,
11194
+ ...stacked ? { overflowY: "auto" } : {}
11195
+ },
11196
+ children: /* @__PURE__ */ jsxs13(
11197
+ "div",
11198
+ {
11199
+ style: { position: "relative" },
11200
+ onMouseEnter: () => setVisibilityOpen(true),
11201
+ children: [
11202
+ /* @__PURE__ */ jsx18(
11203
+ "button",
11204
+ {
11205
+ type: "button",
11206
+ role: "menuitem",
11207
+ "aria-haspopup": "menu",
11208
+ "aria-expanded": visibilityOpen,
11209
+ className: itemStyle,
11210
+ onClick: () => setVisibilityOpen(true),
11211
+ children: "Visibility \u25B8"
11212
+ }
11213
+ ),
11214
+ visibilityOpen && /* @__PURE__ */ jsx18(
11215
+ "div",
11216
+ {
11217
+ role: "menu",
11218
+ "aria-label": "Visibility",
11219
+ className: menuStyle,
11220
+ style: submenuStyle,
11221
+ children: /* @__PURE__ */ jsxs13(
11222
+ "div",
11223
+ {
11224
+ style: { position: "relative" },
11225
+ onMouseEnter: () => setOpacityOpen(true),
11226
+ children: [
11227
+ /* @__PURE__ */ jsx18(
11228
+ "button",
11229
+ {
11230
+ type: "button",
11231
+ role: "menuitem",
11232
+ "aria-haspopup": "menu",
11233
+ "aria-expanded": opacityOpen,
11234
+ className: itemStyle,
11235
+ onClick: () => setOpacityOpen(true),
11236
+ children: "Hidden Layer Visibility \u25B8"
11237
+ }
11238
+ ),
11239
+ opacityOpen && /* @__PURE__ */ jsx18(
11240
+ "div",
11241
+ {
11242
+ role: "menu",
11243
+ "aria-label": "Hidden Layer Visibility",
11244
+ className: menuStyle,
11245
+ style: {
11246
+ minWidth: 80,
11247
+ ...submenuStyle
11248
+ },
11249
+ children: [0, 0.1, 0.2, 0.4, 0.6, 0.8, 1].map((value) => /* @__PURE__ */ jsxs13(
11250
+ "button",
11251
+ {
11252
+ type: "button",
11253
+ role: "menuitemradio",
11254
+ "aria-checked": opacity === value,
11255
+ className: itemStyle,
11256
+ onClick: () => {
11257
+ setOpacity(value);
11258
+ onClose();
11259
+ },
11260
+ children: [
11261
+ /* @__PURE__ */ jsx18(
11262
+ "span",
11263
+ {
11264
+ "aria-hidden": "true",
11265
+ style: { display: "inline-block", width: 16 },
11266
+ children: opacity === value ? "\u2713" : ""
11267
+ }
11268
+ ),
11269
+ value === 0 ? "Hide" : `${value * 100}%`
11270
+ ]
11271
+ },
11272
+ value
11273
+ ))
11274
+ }
11275
+ )
11276
+ ]
11277
+ }
11278
+ )
11279
+ }
11280
+ )
11281
+ ]
11282
+ }
11283
+ )
11284
+ }
11285
+ ),
11286
+ document.body
11287
+ );
11288
+ };
11289
+
10790
11290
  // src/components/ToolbarButton.tsx
10791
- import { jsx as jsx18 } from "react/jsx-runtime";
11291
+ import { jsx as jsx19 } from "react/jsx-runtime";
10792
11292
  var ToolbarButton = ({
10793
11293
  children,
10794
11294
  isSmallScreen,
@@ -10796,7 +11296,7 @@ var ToolbarButton = ({
10796
11296
  ...props
10797
11297
  }) => {
10798
11298
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
10799
- return /* @__PURE__ */ jsx18(
11299
+ return /* @__PURE__ */ jsx19(
10800
11300
  "div",
10801
11301
  {
10802
11302
  ...props,
@@ -10824,7 +11324,7 @@ var ToolbarButton = ({
10824
11324
  };
10825
11325
 
10826
11326
  // src/components/ToolbarErrorDropdown.tsx
10827
- import { useCallback as useCallback9, useMemo as useMemo7, useState as useState9 } from "react";
11327
+ import { useCallback as useCallback9, useMemo as useMemo7, useState as useState10 } from "react";
10828
11328
 
10829
11329
  // src/lib/util/group-errors-by-type.ts
10830
11330
  var groupErrorsByType = (errors) => {
@@ -10846,16 +11346,16 @@ var groupErrorsByType = (errors) => {
10846
11346
  };
10847
11347
 
10848
11348
  // src/components/useToolbarErrorFocus.ts
10849
- import { useCallback as useCallback8, useEffect as useEffect14, useRef as useRef11 } from "react";
11349
+ import { useCallback as useCallback8, useEffect as useEffect15, useRef as useRef12 } from "react";
10850
11350
  var useToolbarErrorFocus = ({
10851
11351
  onClose,
10852
11352
  setHoveredErrorId,
10853
11353
  setFocusedErrorId,
10854
11354
  highlightDurationMs = 3e3
10855
11355
  }) => {
10856
- const clearHighlightTimeoutRef = useRef11(null);
10857
- const focusRequestRef = useRef11(null);
10858
- const selectedErrorIdRef = useRef11(null);
11356
+ const clearHighlightTimeoutRef = useRef12(null);
11357
+ const focusRequestRef = useRef12(null);
11358
+ const selectedErrorIdRef = useRef12(null);
10859
11359
  const clearPendingSelection = useCallback8(() => {
10860
11360
  if (clearHighlightTimeoutRef.current !== null) {
10861
11361
  window.clearTimeout(clearHighlightTimeoutRef.current);
@@ -10866,7 +11366,7 @@ var useToolbarErrorFocus = ({
10866
11366
  focusRequestRef.current = null;
10867
11367
  }
10868
11368
  }, []);
10869
- useEffect14(() => clearPendingSelection, [clearPendingSelection]);
11369
+ useEffect15(() => clearPendingSelection, [clearPendingSelection]);
10870
11370
  const handleErrorSelect = useCallback8(
10871
11371
  (errorId) => {
10872
11372
  clearPendingSelection();
@@ -10904,7 +11404,7 @@ var useToolbarErrorFocus = ({
10904
11404
  };
10905
11405
 
10906
11406
  // src/components/ToolbarErrorDropdown.tsx
10907
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
11407
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
10908
11408
  var CopyErrorButton = ({
10909
11409
  errorId,
10910
11410
  errorMessage,
@@ -10914,7 +11414,7 @@ var CopyErrorButton = ({
10914
11414
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(
10915
11415
  () => onCopy(errorMessage, errorId)
10916
11416
  );
10917
- return /* @__PURE__ */ jsx19(
11417
+ return /* @__PURE__ */ jsx20(
10918
11418
  "button",
10919
11419
  {
10920
11420
  type: "button",
@@ -10934,7 +11434,7 @@ var CopyErrorButton = ({
10934
11434
  ...touchStyle
10935
11435
  },
10936
11436
  ...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" }) })
11437
+ children: copiedErrorId === errorId ? /* @__PURE__ */ jsx20("span", { style: { color: "#4caf50", fontSize: 12 }, children: "Copied!" }) : /* @__PURE__ */ jsx20("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx20("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" }) })
10938
11438
  }
10939
11439
  );
10940
11440
  };
@@ -10947,11 +11447,11 @@ var ToolbarErrorDropdown = ({
10947
11447
  setHoveredErrorId,
10948
11448
  setFocusedErrorId
10949
11449
  }) => {
10950
- const [copiedErrorId, setCopiedErrorId] = useState9(null);
10951
- const [collapsedErrorGroups, setCollapsedErrorGroups] = useState9(
11450
+ const [copiedErrorId, setCopiedErrorId] = useState10(null);
11451
+ const [collapsedErrorGroups, setCollapsedErrorGroups] = useState10(
10952
11452
  /* @__PURE__ */ new Set()
10953
11453
  );
10954
- const [expandedErrorIds, setExpandedErrorIds] = useState9(
11454
+ const [expandedErrorIds, setExpandedErrorIds] = useState10(
10955
11455
  /* @__PURE__ */ new Set()
10956
11456
  );
10957
11457
  const [, copyToClipboard] = useCopyToClipboard_default();
@@ -10993,20 +11493,20 @@ var ToolbarErrorDropdown = ({
10993
11493
  return next;
10994
11494
  });
10995
11495
  }, []);
10996
- return /* @__PURE__ */ jsxs13("div", { style: { position: "relative" }, children: [
10997
- /* @__PURE__ */ jsx19(
11496
+ return /* @__PURE__ */ jsxs14("div", { style: { position: "relative" }, children: [
11497
+ /* @__PURE__ */ jsx20(
10998
11498
  ToolbarButton,
10999
11499
  {
11000
11500
  isSmallScreen,
11001
11501
  style: errorCount > 0 ? { color: "red" } : void 0,
11002
11502
  onClick: onToggle,
11003
- children: /* @__PURE__ */ jsxs13("div", { children: [
11503
+ children: /* @__PURE__ */ jsxs14("div", { children: [
11004
11504
  errorCount,
11005
11505
  " errors"
11006
11506
  ] })
11007
11507
  }
11008
11508
  ),
11009
- isOpen && errorCount > 0 && /* @__PURE__ */ jsx19(
11509
+ isOpen && errorCount > 0 && /* @__PURE__ */ jsx20(
11010
11510
  "div",
11011
11511
  {
11012
11512
  style: {
@@ -11026,14 +11526,14 @@ var ToolbarErrorDropdown = ({
11026
11526
  },
11027
11527
  children: groupedErrorElements.map(({ errorType, errors }, groupIndex) => {
11028
11528
  const isGroupCollapsed = collapsedErrorGroups.has(errorType);
11029
- return /* @__PURE__ */ jsxs13(
11529
+ return /* @__PURE__ */ jsxs14(
11030
11530
  "div",
11031
11531
  {
11032
11532
  style: {
11033
11533
  borderBottom: groupIndex < groupedErrorElements.length - 1 ? "1px solid #444" : "none"
11034
11534
  },
11035
11535
  children: [
11036
- /* @__PURE__ */ jsxs13(
11536
+ /* @__PURE__ */ jsxs14(
11037
11537
  "div",
11038
11538
  {
11039
11539
  style: {
@@ -11070,7 +11570,7 @@ var ToolbarErrorDropdown = ({
11070
11570
  toggleErrorGroup(errorType);
11071
11571
  },
11072
11572
  children: [
11073
- /* @__PURE__ */ jsxs13(
11573
+ /* @__PURE__ */ jsxs14(
11074
11574
  "div",
11075
11575
  {
11076
11576
  style: {
@@ -11080,7 +11580,7 @@ var ToolbarErrorDropdown = ({
11080
11580
  color: "#ff6b6b"
11081
11581
  },
11082
11582
  children: [
11083
- /* @__PURE__ */ jsx19(
11583
+ /* @__PURE__ */ jsx20(
11084
11584
  "div",
11085
11585
  {
11086
11586
  style: {
@@ -11093,7 +11593,7 @@ var ToolbarErrorDropdown = ({
11093
11593
  children: "\u203A"
11094
11594
  }
11095
11595
  ),
11096
- /* @__PURE__ */ jsx19(
11596
+ /* @__PURE__ */ jsx20(
11097
11597
  "div",
11098
11598
  {
11099
11599
  style: {
@@ -11106,7 +11606,7 @@ var ToolbarErrorDropdown = ({
11106
11606
  ]
11107
11607
  }
11108
11608
  ),
11109
- /* @__PURE__ */ jsx19(
11609
+ /* @__PURE__ */ jsx20(
11110
11610
  "div",
11111
11611
  {
11112
11612
  style: {
@@ -11124,14 +11624,14 @@ var ToolbarErrorDropdown = ({
11124
11624
  !isGroupCollapsed && errors.map(({ error, index, errorId }) => {
11125
11625
  const isExpanded = expandedErrorIds.has(errorId);
11126
11626
  const errorMessage = error.message ?? "No error message";
11127
- return /* @__PURE__ */ jsxs13(
11627
+ return /* @__PURE__ */ jsxs14(
11128
11628
  "div",
11129
11629
  {
11130
11630
  style: {
11131
11631
  borderTop: "1px solid #3a3a3a"
11132
11632
  },
11133
11633
  children: [
11134
- /* @__PURE__ */ jsxs13(
11634
+ /* @__PURE__ */ jsxs14(
11135
11635
  "div",
11136
11636
  {
11137
11637
  style: {
@@ -11170,7 +11670,7 @@ var ToolbarErrorDropdown = ({
11170
11670
  handleErrorSelect(errorId);
11171
11671
  },
11172
11672
  children: [
11173
- /* @__PURE__ */ jsx19(
11673
+ /* @__PURE__ */ jsx20(
11174
11674
  "div",
11175
11675
  {
11176
11676
  style: {
@@ -11186,7 +11686,7 @@ var ToolbarErrorDropdown = ({
11186
11686
  children: errorMessage
11187
11687
  }
11188
11688
  ),
11189
- /* @__PURE__ */ jsx19(
11689
+ /* @__PURE__ */ jsx20(
11190
11690
  "button",
11191
11691
  {
11192
11692
  type: "button",
@@ -11218,7 +11718,7 @@ var ToolbarErrorDropdown = ({
11218
11718
  ]
11219
11719
  }
11220
11720
  ),
11221
- isExpanded && /* @__PURE__ */ jsxs13(
11721
+ isExpanded && /* @__PURE__ */ jsxs14(
11222
11722
  "div",
11223
11723
  {
11224
11724
  "data-error-id": index,
@@ -11230,7 +11730,7 @@ var ToolbarErrorDropdown = ({
11230
11730
  position: "relative"
11231
11731
  },
11232
11732
  children: [
11233
- /* @__PURE__ */ jsx19(
11733
+ /* @__PURE__ */ jsx20(
11234
11734
  "div",
11235
11735
  {
11236
11736
  style: {
@@ -11248,7 +11748,7 @@ var ToolbarErrorDropdown = ({
11248
11748
  children: errorMessage
11249
11749
  }
11250
11750
  ),
11251
- /* @__PURE__ */ jsx19(
11751
+ /* @__PURE__ */ jsx20(
11252
11752
  CopyErrorButton,
11253
11753
  {
11254
11754
  errorId,
@@ -11280,13 +11780,13 @@ var ToolbarErrorDropdown = ({
11280
11780
  };
11281
11781
 
11282
11782
  // src/components/ToolbarOverlay.tsx
11283
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
11783
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
11284
11784
  var LayerButton = ({ name, selected, onClick }) => {
11285
11785
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
11286
- return /* @__PURE__ */ jsxs14(
11786
+ return /* @__PURE__ */ jsxs15(
11287
11787
  "div",
11288
11788
  {
11289
- className: css2`
11789
+ className: css3`
11290
11790
  margin-top: 2px;
11291
11791
  padding: 4px;
11292
11792
  padding-left: 8px;
@@ -11300,8 +11800,8 @@ var LayerButton = ({ name, selected, onClick }) => {
11300
11800
  ...touchHandlers,
11301
11801
  style: touchStyle,
11302
11802
  children: [
11303
- /* @__PURE__ */ jsx20("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
11304
- /* @__PURE__ */ jsx20(
11803
+ /* @__PURE__ */ jsx21("span", { style: { marginRight: 2, opacity: selected ? 1 : 0 }, children: "\u2022" }),
11804
+ /* @__PURE__ */ jsx21(
11305
11805
  "span",
11306
11806
  {
11307
11807
  style: {
@@ -11322,10 +11822,10 @@ var CheckboxMenuItem = ({
11322
11822
  onClick
11323
11823
  }) => {
11324
11824
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
11325
- return /* @__PURE__ */ jsxs14(
11825
+ return /* @__PURE__ */ jsxs15(
11326
11826
  "div",
11327
11827
  {
11328
- className: css2`
11828
+ className: css3`
11329
11829
  margin-top: 2px;
11330
11830
  padding: 4px;
11331
11831
  padding-left: 8px;
@@ -11342,19 +11842,19 @@ var CheckboxMenuItem = ({
11342
11842
  ...touchHandlers,
11343
11843
  style: touchStyle,
11344
11844
  children: [
11345
- /* @__PURE__ */ jsx20("input", { type: "checkbox", checked, onChange: () => {
11845
+ /* @__PURE__ */ jsx21("input", { type: "checkbox", checked, onChange: () => {
11346
11846
  }, readOnly: true }),
11347
- /* @__PURE__ */ jsx20("span", { style: { color: "#eee" }, children: label })
11847
+ /* @__PURE__ */ jsx21("span", { style: { color: "#eee" }, children: label })
11348
11848
  ]
11349
11849
  }
11350
11850
  );
11351
11851
  };
11352
11852
  var RadioMenuItem = ({ label, checked, onClick }) => {
11353
11853
  const { style: touchStyle, ...touchHandlers } = useMobileTouch(onClick);
11354
- return /* @__PURE__ */ jsxs14(
11854
+ return /* @__PURE__ */ jsxs15(
11355
11855
  "div",
11356
11856
  {
11357
- className: css2`
11857
+ className: css3`
11358
11858
  margin-top: 2px;
11359
11859
  padding: 4px;
11360
11860
  padding-left: 8px;
@@ -11371,9 +11871,9 @@ var RadioMenuItem = ({ label, checked, onClick }) => {
11371
11871
  ...touchHandlers,
11372
11872
  style: touchStyle,
11373
11873
  children: [
11374
- /* @__PURE__ */ jsx20("input", { type: "radio", checked, onChange: () => {
11874
+ /* @__PURE__ */ jsx21("input", { type: "radio", checked, onChange: () => {
11375
11875
  }, readOnly: true }),
11376
- /* @__PURE__ */ jsx20("span", { style: { color: "#eee" }, children: label })
11876
+ /* @__PURE__ */ jsx21("span", { style: { color: "#eee" }, children: label })
11377
11877
  ]
11378
11878
  }
11379
11879
  );
@@ -11440,12 +11940,14 @@ var ToolbarOverlay = ({ children, elements }) => {
11440
11940
  setHoveredErrorId: s.setHoveredErrorId,
11441
11941
  setFocusedErrorId: s.setFocusedErrorId
11442
11942
  }));
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(() => {
11943
+ const [contextMenuPosition, setContextMenuPosition] = useState11(null);
11944
+ const closeContextMenu = useCallback10(() => setContextMenuPosition(null), []);
11945
+ const [isViewMenuOpen, setViewMenuOpen] = useState11(false);
11946
+ const [isLayerMenuOpen, setLayerMenuOpen] = useState11(false);
11947
+ const [isErrorsOpen, setErrorsOpen] = useState11(false);
11948
+ const [measureToolArmed, setMeasureToolArmed] = useState11(false);
11949
+ const [boundsToolArmed, setBoundsToolArmed] = useState11(false);
11950
+ useEffect16(() => {
11449
11951
  const arm = () => setMeasureToolArmed(true);
11450
11952
  const disarm = () => setMeasureToolArmed(false);
11451
11953
  const armBounds = () => setBoundsToolArmed(true);
@@ -11463,8 +11965,8 @@ var ToolbarOverlay = ({ children, elements }) => {
11463
11965
  }, []);
11464
11966
  const availableLayers = getCopperLayerRefsFromElements(elements ?? []);
11465
11967
  const processedLayers = availableLayers;
11466
- const hasRunInitialMouseCheck = useRef12(false);
11467
- const hotkeyBoundaryRef = useRef12(null);
11968
+ const hasRunInitialMouseCheck = useRef13(false);
11969
+ const hotkeyBoundaryRef = useRef13(null);
11468
11970
  const hotKeyCallbacks = {
11469
11971
  "1": availableLayers[0] ? () => selectLayer(availableLayers[0]) : () => {
11470
11972
  },
@@ -11571,17 +12073,29 @@ var ToolbarOverlay = ({ children, elements }) => {
11571
12073
  },
11572
12074
  []
11573
12075
  );
11574
- return /* @__PURE__ */ jsxs14(
12076
+ return /* @__PURE__ */ jsxs15(
11575
12077
  "div",
11576
12078
  {
11577
12079
  ref: hotkeyBoundaryRef,
12080
+ onContextMenu: (event) => {
12081
+ event.preventDefault();
12082
+ event.stopPropagation();
12083
+ setContextMenuPosition({ x: event.clientX, y: event.clientY });
12084
+ },
11578
12085
  style: { position: "relative", zIndex: "999 !important" },
11579
12086
  onMouseEnter: handleMouseEnter,
11580
12087
  onMouseLeave: handleMouseLeave,
11581
12088
  onMouseMove: handleMouseMove,
11582
12089
  children: [
11583
12090
  children,
11584
- /* @__PURE__ */ jsxs14(
12091
+ contextMenuPosition && /* @__PURE__ */ jsx21(
12092
+ VisibilityContextMenu,
12093
+ {
12094
+ position: contextMenuPosition,
12095
+ onClose: closeContextMenu
12096
+ }
12097
+ ),
12098
+ /* @__PURE__ */ jsxs15(
11585
12099
  "div",
11586
12100
  {
11587
12101
  style: {
@@ -11602,7 +12116,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11602
12116
  ]
11603
12117
  }
11604
12118
  ),
11605
- /* @__PURE__ */ jsxs14(
12119
+ /* @__PURE__ */ jsxs15(
11606
12120
  "div",
11607
12121
  {
11608
12122
  "data-toolbar-overlay": true,
@@ -11633,7 +12147,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11633
12147
  fontFamily: "sans-serif"
11634
12148
  },
11635
12149
  children: [
11636
- /* @__PURE__ */ jsxs14(
12150
+ /* @__PURE__ */ jsxs15(
11637
12151
  ToolbarButton,
11638
12152
  {
11639
12153
  isSmallScreen,
@@ -11644,10 +12158,10 @@ var ToolbarOverlay = ({ children, elements }) => {
11644
12158
  }
11645
12159
  },
11646
12160
  children: [
11647
- /* @__PURE__ */ jsxs14("div", { children: [
12161
+ /* @__PURE__ */ jsxs15("div", { children: [
11648
12162
  "layer:",
11649
12163
  " ",
11650
- /* @__PURE__ */ jsx20(
12164
+ /* @__PURE__ */ jsx21(
11651
12165
  "span",
11652
12166
  {
11653
12167
  style: {
@@ -11659,7 +12173,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11659
12173
  }
11660
12174
  )
11661
12175
  ] }),
11662
- isLayerMenuOpen && /* @__PURE__ */ jsx20("div", { style: { marginTop: 4, minWidth: 120 }, children: processedLayers.map((layer) => /* @__PURE__ */ jsx20(
12176
+ isLayerMenuOpen && /* @__PURE__ */ jsx21("div", { style: { marginTop: 4, minWidth: 120 }, children: processedLayers.map((layer) => /* @__PURE__ */ jsx21(
11663
12177
  LayerButton,
11664
12178
  {
11665
12179
  name: layer,
@@ -11673,7 +12187,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11673
12187
  ]
11674
12188
  }
11675
12189
  ),
11676
- /* @__PURE__ */ jsx20(
12190
+ /* @__PURE__ */ jsx21(
11677
12191
  ToolbarErrorDropdown,
11678
12192
  {
11679
12193
  elements,
@@ -11685,43 +12199,43 @@ var ToolbarOverlay = ({ children, elements }) => {
11685
12199
  setFocusedErrorId
11686
12200
  }
11687
12201
  ),
11688
- /* @__PURE__ */ jsx20(
12202
+ /* @__PURE__ */ jsx21(
11689
12203
  ToolbarButton,
11690
12204
  {
11691
12205
  isSmallScreen,
11692
12206
  style: {},
11693
12207
  onClick: handleRatsNestToggle,
11694
- children: /* @__PURE__ */ jsxs14("div", { children: [
12208
+ children: /* @__PURE__ */ jsxs15("div", { children: [
11695
12209
  viewSettings.is_showing_rats_nest ? "\u2716 " : "",
11696
12210
  "Rats Nest"
11697
12211
  ] })
11698
12212
  }
11699
12213
  ),
11700
- /* @__PURE__ */ jsx20(
12214
+ /* @__PURE__ */ jsx21(
11701
12215
  ToolbarButton,
11702
12216
  {
11703
12217
  isSmallScreen,
11704
12218
  style: measureToolArmed ? { backgroundColor: "#444" } : {},
11705
12219
  onClick: handleMeasureToolClick,
11706
- children: /* @__PURE__ */ jsx20("div", { children: "\u{1F4CF}" })
12220
+ children: /* @__PURE__ */ jsx21("div", { children: "\u{1F4CF}" })
11707
12221
  }
11708
12222
  ),
11709
- /* @__PURE__ */ jsx20(
12223
+ /* @__PURE__ */ jsx21(
11710
12224
  ToolbarButton,
11711
12225
  {
11712
12226
  isSmallScreen,
11713
12227
  style: boundsToolArmed ? { backgroundColor: "#444" } : {},
11714
12228
  onClick: handleBoundsToolClick,
11715
- children: /* @__PURE__ */ jsx20("div", { children: "Bounds" })
12229
+ children: /* @__PURE__ */ jsx21("div", { children: "Bounds" })
11716
12230
  }
11717
12231
  ),
11718
- /* @__PURE__ */ jsx20(
12232
+ /* @__PURE__ */ jsx21(
11719
12233
  ToolbarButton,
11720
12234
  {
11721
12235
  isSmallScreen,
11722
12236
  onClick: handleViewMenuToggle,
11723
- children: /* @__PURE__ */ jsxs14("div", { children: [
11724
- /* @__PURE__ */ jsxs14(
12237
+ children: /* @__PURE__ */ jsxs15("div", { children: [
12238
+ /* @__PURE__ */ jsxs15(
11725
12239
  "div",
11726
12240
  {
11727
12241
  style: {
@@ -11731,7 +12245,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11731
12245
  },
11732
12246
  children: [
11733
12247
  "View",
11734
- /* @__PURE__ */ jsx20(
12248
+ /* @__PURE__ */ jsx21(
11735
12249
  "span",
11736
12250
  {
11737
12251
  style: {
@@ -11746,8 +12260,8 @@ var ToolbarOverlay = ({ children, elements }) => {
11746
12260
  ]
11747
12261
  }
11748
12262
  ),
11749
- isViewMenuOpen && /* @__PURE__ */ jsxs14("div", { style: { marginTop: 4, minWidth: 120 }, children: [
11750
- /* @__PURE__ */ jsx20(
12263
+ isViewMenuOpen && /* @__PURE__ */ jsxs15("div", { style: { marginTop: 4, minWidth: 120 }, children: [
12264
+ /* @__PURE__ */ jsx21(
11751
12265
  CheckboxMenuItem,
11752
12266
  {
11753
12267
  label: "Show All Trace Lengths",
@@ -11759,7 +12273,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11759
12273
  }
11760
12274
  }
11761
12275
  ),
11762
- /* @__PURE__ */ jsx20(
12276
+ /* @__PURE__ */ jsx21(
11763
12277
  CheckboxMenuItem,
11764
12278
  {
11765
12279
  label: "Show Autorouting Animation",
@@ -11771,7 +12285,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11771
12285
  }
11772
12286
  }
11773
12287
  ),
11774
- /* @__PURE__ */ jsx20(
12288
+ /* @__PURE__ */ jsx21(
11775
12289
  CheckboxMenuItem,
11776
12290
  {
11777
12291
  label: "Show DRC Errors",
@@ -11781,7 +12295,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11781
12295
  }
11782
12296
  }
11783
12297
  ),
11784
- /* @__PURE__ */ jsx20(
12298
+ /* @__PURE__ */ jsx21(
11785
12299
  CheckboxMenuItem,
11786
12300
  {
11787
12301
  label: "Show DRC Warnings",
@@ -11793,7 +12307,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11793
12307
  }
11794
12308
  }
11795
12309
  ),
11796
- /* @__PURE__ */ jsx20(
12310
+ /* @__PURE__ */ jsx21(
11797
12311
  CheckboxMenuItem,
11798
12312
  {
11799
12313
  label: "Show Copper Pours",
@@ -11805,7 +12319,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11805
12319
  }
11806
12320
  }
11807
12321
  ),
11808
- /* @__PURE__ */ jsx20(
12322
+ /* @__PURE__ */ jsx21(
11809
12323
  CheckboxMenuItem,
11810
12324
  {
11811
12325
  label: "Show Courtyards",
@@ -11815,7 +12329,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11815
12329
  }
11816
12330
  }
11817
12331
  ),
11818
- /* @__PURE__ */ jsx20(
12332
+ /* @__PURE__ */ jsx21(
11819
12333
  CheckboxMenuItem,
11820
12334
  {
11821
12335
  label: "Show Solder Mask",
@@ -11825,7 +12339,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11825
12339
  }
11826
12340
  }
11827
12341
  ),
11828
- /* @__PURE__ */ jsx20(
12342
+ /* @__PURE__ */ jsx21(
11829
12343
  CheckboxMenuItem,
11830
12344
  {
11831
12345
  label: "Show Silkscreen",
@@ -11835,7 +12349,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11835
12349
  }
11836
12350
  }
11837
12351
  ),
11838
- /* @__PURE__ */ jsx20(
12352
+ /* @__PURE__ */ jsx21(
11839
12353
  CheckboxMenuItem,
11840
12354
  {
11841
12355
  label: "Show Fabrication Notes",
@@ -11847,7 +12361,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11847
12361
  }
11848
12362
  }
11849
12363
  ),
11850
- /* @__PURE__ */ jsx20(
12364
+ /* @__PURE__ */ jsx21(
11851
12365
  CheckboxMenuItem,
11852
12366
  {
11853
12367
  label: "Show PCB Notes",
@@ -11857,7 +12371,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11857
12371
  }
11858
12372
  }
11859
12373
  ),
11860
- /* @__PURE__ */ jsx20(
12374
+ /* @__PURE__ */ jsx21(
11861
12375
  CheckboxMenuItem,
11862
12376
  {
11863
12377
  label: "Show Group Anchor Offsets",
@@ -11869,7 +12383,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11869
12383
  }
11870
12384
  }
11871
12385
  ),
11872
- /* @__PURE__ */ jsx20(
12386
+ /* @__PURE__ */ jsx21(
11873
12387
  CheckboxMenuItem,
11874
12388
  {
11875
12389
  label: "Show PCB Groups",
@@ -11879,8 +12393,8 @@ var ToolbarOverlay = ({ children, elements }) => {
11879
12393
  }
11880
12394
  }
11881
12395
  ),
11882
- viewSettings.is_showing_pcb_groups && /* @__PURE__ */ jsxs14("div", { style: { marginLeft: 16 }, children: [
11883
- /* @__PURE__ */ jsx20(
12396
+ viewSettings.is_showing_pcb_groups && /* @__PURE__ */ jsxs15("div", { style: { marginLeft: 16 }, children: [
12397
+ /* @__PURE__ */ jsx21(
11884
12398
  RadioMenuItem,
11885
12399
  {
11886
12400
  label: "Show All Groups",
@@ -11890,7 +12404,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11890
12404
  }
11891
12405
  }
11892
12406
  ),
11893
- /* @__PURE__ */ jsx20(
12407
+ /* @__PURE__ */ jsx21(
11894
12408
  RadioMenuItem,
11895
12409
  {
11896
12410
  label: "Show Named Groups",
@@ -11914,7 +12428,7 @@ var ToolbarOverlay = ({ children, elements }) => {
11914
12428
  };
11915
12429
 
11916
12430
  // src/components/WarningGraphicsOverlay.tsx
11917
- import { useEffect as useEffect16, useRef as useRef13 } from "react";
12431
+ import { useEffect as useEffect17, useRef as useRef14 } from "react";
11918
12432
  import { applyToPoint as applyToPoint18, identity as identity8 } from "transformation-matrix";
11919
12433
 
11920
12434
  // src/lib/util/get-pcb-warning-highlight.ts
@@ -11927,18 +12441,18 @@ var getPcbWarningHighlightLabel = (warning) => {
11927
12441
  };
11928
12442
 
11929
12443
  // src/components/WarningGraphicsOverlay.tsx
11930
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
12444
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
11931
12445
  var WarningGraphicsOverlay = ({
11932
12446
  children,
11933
12447
  transform = identity8(),
11934
12448
  elements = []
11935
12449
  }) => {
11936
12450
  const [containerRef, { width, height }] = useMeasure_default();
11937
- const canvasRef = useRef13(null);
12451
+ const canvasRef = useRef14(null);
11938
12452
  const isShowingDrcWarnings = useGlobalStore(
11939
12453
  (state) => state.is_showing_drc_warnings
11940
12454
  );
11941
- useEffect16(() => {
12455
+ useEffect17(() => {
11942
12456
  const canvas = canvasRef.current;
11943
12457
  if (!canvas || !width || !height) return;
11944
12458
  canvas.width = width;
@@ -11989,7 +12503,7 @@ var WarningGraphicsOverlay = ({
11989
12503
  });
11990
12504
  }, [elements, transform, width, height, isShowingDrcWarnings]);
11991
12505
  if (!isShowingDrcWarnings) {
11992
- return /* @__PURE__ */ jsx21(
12506
+ return /* @__PURE__ */ jsx22(
11993
12507
  "div",
11994
12508
  {
11995
12509
  ref: containerRef,
@@ -11998,14 +12512,14 @@ var WarningGraphicsOverlay = ({
11998
12512
  }
11999
12513
  );
12000
12514
  }
12001
- return /* @__PURE__ */ jsxs15(
12515
+ return /* @__PURE__ */ jsxs16(
12002
12516
  "div",
12003
12517
  {
12004
12518
  ref: containerRef,
12005
12519
  style: { position: "relative", width: "100%", height: "100%" },
12006
12520
  children: [
12007
12521
  children,
12008
- /* @__PURE__ */ jsx21(
12522
+ /* @__PURE__ */ jsx22(
12009
12523
  "canvas",
12010
12524
  {
12011
12525
  ref: canvasRef,
@@ -12024,7 +12538,7 @@ var WarningGraphicsOverlay = ({
12024
12538
  };
12025
12539
 
12026
12540
  // src/components/CanvasElementsRenderer.tsx
12027
- import { jsx as jsx22 } from "react/jsx-runtime";
12541
+ import { jsx as jsx23 } from "react/jsx-runtime";
12028
12542
  var CanvasElementsRenderer = (props) => {
12029
12543
  const { transform, elements } = props;
12030
12544
  const {
@@ -12052,13 +12566,13 @@ var CanvasElementsRenderer = (props) => {
12052
12566
  );
12053
12567
  return [primitivesWithoutInteractionMetadata2, connectivityMap2];
12054
12568
  }, [elementsToRender, props.elements]);
12055
- const [hoverState, setHoverState] = useState11({
12569
+ const [hoverState, setHoverState] = useState12({
12056
12570
  drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
12057
12571
  primitiveIdsInMousedOverNet: []
12058
12572
  });
12059
- const [hoveredComponentIds, setHoveredComponentIds] = useState11([]);
12060
- const currentTransformRef = useRef14(transform ?? null);
12061
- const zoomAnimationFrameRef = useRef14(null);
12573
+ const [hoveredComponentIds, setHoveredComponentIds] = useState12([]);
12574
+ const currentTransformRef = useRef15(transform ?? null);
12575
+ const zoomAnimationFrameRef = useRef15(null);
12062
12576
  const elementIndexes = useMemo8(
12063
12577
  () => buildErrorPreviewElementIndexes(elements),
12064
12578
  [elements]
@@ -12074,17 +12588,17 @@ var CanvasElementsRenderer = (props) => {
12074
12588
  if (!activeError) return [];
12075
12589
  return getRelatedIdsForError(activeError);
12076
12590
  }, [activeErrorId, elements]);
12077
- useEffect17(() => {
12591
+ useEffect18(() => {
12078
12592
  if (transform) {
12079
12593
  currentTransformRef.current = transform;
12080
12594
  }
12081
12595
  }, [transform]);
12082
- useEffect17(() => {
12596
+ useEffect18(() => {
12083
12597
  return () => {
12084
12598
  cancelTransformAnimation(zoomAnimationFrameRef.current);
12085
12599
  };
12086
12600
  }, []);
12087
- useEffect17(() => {
12601
+ useEffect18(() => {
12088
12602
  if (!props.width || !props.height || !props.setTransform || !focusedErrorId)
12089
12603
  return;
12090
12604
  const focusedError = findErrorElementById(elements, focusedErrorId);
@@ -12166,7 +12680,7 @@ var CanvasElementsRenderer = (props) => {
12166
12680
  },
12167
12681
  [connectivityMap]
12168
12682
  );
12169
- return /* @__PURE__ */ jsx22(
12683
+ return /* @__PURE__ */ jsx23(
12170
12684
  MouseElementTracker,
12171
12685
  {
12172
12686
  elements: elementsToRender,
@@ -12174,7 +12688,7 @@ var CanvasElementsRenderer = (props) => {
12174
12688
  primitives: primitivesWithoutInteractionMetadata,
12175
12689
  selectedLayer,
12176
12690
  onMouseHoverOverPrimitives: onMouseOverPrimitives,
12177
- children: /* @__PURE__ */ jsx22(
12691
+ children: /* @__PURE__ */ jsx23(
12178
12692
  EditPlacementOverlay,
12179
12693
  {
12180
12694
  disabled: !props.allowEditing,
@@ -12183,7 +12697,7 @@ var CanvasElementsRenderer = (props) => {
12183
12697
  cancelPanDrag: props.cancelPanDrag,
12184
12698
  onCreateEditEvent: props.onCreateEditEvent,
12185
12699
  onModifyEditEvent: props.onModifyEditEvent,
12186
- children: /* @__PURE__ */ jsx22(
12700
+ children: /* @__PURE__ */ jsx23(
12187
12701
  DimensionOverlay,
12188
12702
  {
12189
12703
  transform,
@@ -12191,23 +12705,23 @@ var CanvasElementsRenderer = (props) => {
12191
12705
  primitives: primitivesWithoutInteractionMetadata,
12192
12706
  onBoundsSelected: props.onBoundsSelected,
12193
12707
  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(
12708
+ children: /* @__PURE__ */ jsx23(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx23(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx23(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx23(
12195
12709
  PcbGroupOverlay,
12196
12710
  {
12197
12711
  transform,
12198
12712
  elements,
12199
12713
  hoveredComponentIds,
12200
- children: /* @__PURE__ */ jsx22(
12714
+ children: /* @__PURE__ */ jsx23(
12201
12715
  DebugGraphicsOverlay,
12202
12716
  {
12203
12717
  transform,
12204
12718
  debugGraphics: props.debugGraphics,
12205
- children: /* @__PURE__ */ jsx22(
12719
+ children: /* @__PURE__ */ jsx23(
12206
12720
  WarningGraphicsOverlay,
12207
12721
  {
12208
12722
  transform,
12209
12723
  elements,
12210
- children: /* @__PURE__ */ jsx22(
12724
+ children: /* @__PURE__ */ jsx23(
12211
12725
  CanvasPrimitiveRenderer,
12212
12726
  {
12213
12727
  transform,
@@ -12287,7 +12801,7 @@ var calculateBoardSizeKey = (circuitJson) => {
12287
12801
  };
12288
12802
 
12289
12803
  // src/PCBViewer.tsx
12290
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
12804
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
12291
12805
  var defaultTransform = compose8(translate12(400, 300), scale6(40, -40));
12292
12806
  var PCBViewer = ({
12293
12807
  circuitJson,
@@ -12302,11 +12816,11 @@ var PCBViewer = ({
12302
12816
  clickToInteractEnabled = false,
12303
12817
  disablePcbGroups = false
12304
12818
  }) => {
12305
- const [isInteractionEnabled, setIsInteractionEnabled] = useState12(
12819
+ const [isInteractionEnabled, setIsInteractionEnabled] = useState13(
12306
12820
  !clickToInteractEnabled
12307
12821
  );
12308
12822
  const [ref, refDimensions] = useMeasure_default();
12309
- const [transform, setTransformInternal] = useState12(defaultTransform);
12823
+ const [transform, setTransformInternal] = useState13(defaultTransform);
12310
12824
  const shouldAllowCanvasInteraction = useCallback12(
12311
12825
  (event) => {
12312
12826
  const target = event.target;
@@ -12325,10 +12839,10 @@ var PCBViewer = ({
12325
12839
  enabled: isInteractionEnabled,
12326
12840
  shouldDrag: shouldAllowCanvasInteraction
12327
12841
  });
12328
- let [editEvents, setEditEvents] = useState12([]);
12842
+ let [editEvents, setEditEvents] = useState13([]);
12329
12843
  editEvents = editEventsProp ?? editEvents;
12330
- const initialRenderCompleted = useRef15(false);
12331
- const touchStartRef = useRef15(null);
12844
+ const initialRenderCompleted = useRef16(false);
12845
+ const touchStartRef = useRef16(null);
12332
12846
  const circuitJsonKey = useMemo9(
12333
12847
  () => calculateCircuitJsonKey(circuitJson),
12334
12848
  [circuitJson]
@@ -12354,7 +12868,7 @@ var PCBViewer = ({
12354
12868
  setTransform(targetTransform);
12355
12869
  return;
12356
12870
  };
12357
- useEffect18(() => {
12871
+ useEffect19(() => {
12358
12872
  if (!refDimensions?.width) return;
12359
12873
  if (!circuitJson) return;
12360
12874
  if (circuitJson.length === 0) return;
@@ -12363,7 +12877,7 @@ var PCBViewer = ({
12363
12877
  initialRenderCompleted.current = true;
12364
12878
  }
12365
12879
  }, [circuitJson, refDimensions]);
12366
- useEffect18(() => {
12880
+ useEffect19(() => {
12367
12881
  if (initialRenderCompleted.current === true) {
12368
12882
  resetTransform();
12369
12883
  }
@@ -12397,20 +12911,20 @@ var PCBViewer = ({
12397
12911
  }),
12398
12912
  [initialState, disablePcbGroups]
12399
12913
  );
12400
- return /* @__PURE__ */ jsxs16(
12914
+ return /* @__PURE__ */ jsxs17(
12401
12915
  "div",
12402
12916
  {
12403
12917
  ref: transformRef,
12404
12918
  style: { position: "relative" },
12405
12919
  onContextMenu: (event) => event.preventDefault(),
12406
12920
  children: [
12407
- /* @__PURE__ */ jsx23("div", { ref, children: /* @__PURE__ */ jsxs16(
12921
+ /* @__PURE__ */ jsx24("div", { ref, children: /* @__PURE__ */ jsxs17(
12408
12922
  ContextProviders,
12409
12923
  {
12410
12924
  initialState: mergedInitialState,
12411
12925
  disablePcbGroups,
12412
12926
  children: [
12413
- /* @__PURE__ */ jsx23(
12927
+ /* @__PURE__ */ jsx24(
12414
12928
  CanvasElementsRenderer,
12415
12929
  {
12416
12930
  transform,
@@ -12437,11 +12951,11 @@ var PCBViewer = ({
12437
12951
  },
12438
12952
  refDimensions.width
12439
12953
  ),
12440
- /* @__PURE__ */ jsx23(ToastContainer, {})
12954
+ /* @__PURE__ */ jsx24(ToastContainer, {})
12441
12955
  ]
12442
12956
  }
12443
12957
  ) }),
12444
- clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx23(
12958
+ clickToInteractEnabled && !isInteractionEnabled && /* @__PURE__ */ jsx24(
12445
12959
  "div",
12446
12960
  {
12447
12961
  onClick: () => {
@@ -12478,7 +12992,7 @@ var PCBViewer = ({
12478
12992
  justifyContent: "center",
12479
12993
  touchAction: "pan-x pan-y pinch-zoom"
12480
12994
  },
12481
- children: /* @__PURE__ */ jsx23(
12995
+ children: /* @__PURE__ */ jsx24(
12482
12996
  "div",
12483
12997
  {
12484
12998
  style: {
@@ -12511,5 +13025,16 @@ svgson/dist/svgson.umd.js:
12511
13025
  * @author Feross Aboukhadijeh <https://feross.org>
12512
13026
  * @license MIT
12513
13027
  *)
13028
+
13029
+ react-dom/cjs/react-dom.development.js:
13030
+ (**
13031
+ * @license React
13032
+ * react-dom.development.js
13033
+ *
13034
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
13035
+ *
13036
+ * This source code is licensed under the MIT license found in the
13037
+ * LICENSE file in the root directory of this source tree.
13038
+ *)
12514
13039
  */
12515
13040
  //# sourceMappingURL=index.js.map