@tscircuit/pcb-viewer 1.2.26 → 1.3.1

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
@@ -7,6 +7,9 @@ function _array_like_to_array(arr, len) {
7
7
  function _array_with_holes(arr) {
8
8
  if (Array.isArray(arr)) return arr;
9
9
  }
10
+ function _array_without_holes(arr) {
11
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
12
+ }
10
13
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
11
14
  try {
12
15
  var info = gen[key](arg);
@@ -68,6 +71,9 @@ function _define_property(obj, key, value) {
68
71
  }
69
72
  return obj;
70
73
  }
74
+ function _iterable_to_array(iter) {
75
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
76
+ }
71
77
  function _iterable_to_array_limit(arr, i) {
72
78
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
73
79
  if (_i == null) return;
@@ -95,6 +101,9 @@ function _iterable_to_array_limit(arr, i) {
95
101
  function _non_iterable_rest() {
96
102
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
97
103
  }
104
+ function _non_iterable_spread() {
105
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
106
+ }
98
107
  function _object_spread(target) {
99
108
  for(var i = 1; i < arguments.length; i++){
100
109
  var source = arguments[i] != null ? arguments[i] : {};
@@ -134,9 +143,49 @@ function _object_spread_props(target, source) {
134
143
  }
135
144
  return target;
136
145
  }
146
+ function _object_without_properties(source, excluded) {
147
+ if (source == null) return {};
148
+ var target = _object_without_properties_loose(source, excluded);
149
+ var key, i;
150
+ if (Object.getOwnPropertySymbols) {
151
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
152
+ for(i = 0; i < sourceSymbolKeys.length; i++){
153
+ key = sourceSymbolKeys[i];
154
+ if (excluded.indexOf(key) >= 0) continue;
155
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
156
+ target[key] = source[key];
157
+ }
158
+ }
159
+ return target;
160
+ }
161
+ function _object_without_properties_loose(source, excluded) {
162
+ if (source == null) return {};
163
+ var target = {};
164
+ var sourceKeys = Object.keys(source);
165
+ var key, i;
166
+ for(i = 0; i < sourceKeys.length; i++){
167
+ key = sourceKeys[i];
168
+ if (excluded.indexOf(key) >= 0) continue;
169
+ target[key] = source[key];
170
+ }
171
+ return target;
172
+ }
137
173
  function _sliced_to_array(arr, i) {
138
174
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
139
175
  }
176
+ function _tagged_template_literal(strings, raw) {
177
+ if (!raw) {
178
+ raw = strings.slice(0);
179
+ }
180
+ return Object.freeze(Object.defineProperties(strings, {
181
+ raw: {
182
+ value: Object.freeze(raw)
183
+ }
184
+ }));
185
+ }
186
+ function _to_consumable_array(arr) {
187
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
188
+ }
140
189
  function _unsupported_iterable_to_array(o, minLen) {
141
190
  if (!o) return;
142
191
  if (typeof o === "string") return _array_like_to_array(o, minLen);
@@ -275,6 +324,35 @@ var _loop = function(letter) {
275
324
  }
276
325
  }
277
326
  };
327
+ function _templateObject() {
328
+ var data = _tagged_template_literal([
329
+ "\n margin-top: 2px;\n padding: 4px;\n padding-left: 8px;\n padding-right: 18px;\n cursor: pointer;\n\n &:hover {\n background-color: rgba(255, 255, 255, 0.1);\n }\n "
330
+ ]);
331
+ _templateObject = function _templateObject() {
332
+ return data;
333
+ };
334
+ return data;
335
+ }
336
+ function _templateObject1() {
337
+ var data = _tagged_template_literal([
338
+ "\n position: absolute;\n z-index: 1000;\n left: ",
339
+ "px;\n top: ",
340
+ "px;\n color: red;\n text-align: center;\n font-family: sans-serif;\n font-size: 12px;\n display: flex;\n flex-direction: column;\n align-items: center;\n cursor: pointer;\n transform: translate(-50%, -100%);\n\n & .error-message {\n opacity: 0;\n pointer-events: none;\n\n width: 200px;\n transition: opacity 0.2s;\n margin-bottom: 10px;\n }\n\n &:hover .error-message {\n opacity: 1;\n display: flex;\n }\n "
341
+ ]);
342
+ _templateObject1 = function _templateObject() {
343
+ return data;
344
+ };
345
+ return data;
346
+ }
347
+ function _templateObject2() {
348
+ var data = _tagged_template_literal([
349
+ "\n width: 10px;\n height: 10px;\n transform: translate(0, 5px) rotate(45deg);\n background-color: red;\n "
350
+ ]);
351
+ _templateObject2 = function _templateObject() {
352
+ return data;
353
+ };
354
+ return data;
355
+ }
278
356
  var __create = Object.create;
279
357
  var __defProp = Object.defineProperty;
280
358
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -400,20 +478,20 @@ var require_dist = __commonJS({
400
478
  }
401
479
  });
402
480
  module2.exports = __toCommonJS2(src_exports2);
403
- var import_transformation_matrix4 = require("transformation-matrix");
404
- var import_react10 = require("react");
481
+ var import_transformation_matrix6 = require("transformation-matrix");
482
+ var import_react16 = require("react");
405
483
  var useMouseMatrixTransform2 = function() {
406
484
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
407
- var extRef = (0, import_react10.useRef)(null);
485
+ var extRef = (0, import_react16.useRef)(null);
408
486
  var _props_canvasElm;
409
487
  var outerCanvasElm = (_props_canvasElm = props.canvasElm) !== null && _props_canvasElm !== void 0 ? _props_canvasElm : extRef.current;
410
488
  var _props_initialTransform;
411
- var _ref = _sliced_to_array((0, import_react10.useState)((_props_initialTransform = props.initialTransform) !== null && _props_initialTransform !== void 0 ? _props_initialTransform : (0, import_transformation_matrix4.identity)()), 2), internalTransform = _ref[0], setInternalTransform = _ref[1];
412
- var _ref1 = _sliced_to_array((0, import_react10.useState)(0), 2), waitCounter = _ref1[0], setWaitCounter = _ref1[1];
413
- var _ref2 = _sliced_to_array((0, import_react10.useReducer)(function(s) {
489
+ var _ref = _sliced_to_array((0, import_react16.useState)((_props_initialTransform = props.initialTransform) !== null && _props_initialTransform !== void 0 ? _props_initialTransform : (0, import_transformation_matrix6.identity)()), 2), internalTransform = _ref[0], setInternalTransform = _ref[1];
490
+ var _ref1 = _sliced_to_array((0, import_react16.useState)(0), 2), waitCounter = _ref1[0], setWaitCounter = _ref1[1];
491
+ var _ref2 = _sliced_to_array((0, import_react16.useReducer)(function(s) {
414
492
  return s + 1;
415
493
  }, 0), 2), extChangeCounter = _ref2[0], incExtChangeCounter = _ref2[1];
416
- var setTransform = (0, import_react10.useCallback)(function(newTransform) {
494
+ var setTransform = (0, import_react16.useCallback)(function(newTransform) {
417
495
  if (props.onSetTransform) {
418
496
  props.onSetTransform(newTransform);
419
497
  }
@@ -424,7 +502,7 @@ var require_dist = __commonJS({
424
502
  props.onSetTransform,
425
503
  setInternalTransform
426
504
  ]);
427
- var setTransformExt = (0, import_react10.useCallback)(function(newTransform) {
505
+ var setTransformExt = (0, import_react16.useCallback)(function(newTransform) {
428
506
  setTransform(newTransform);
429
507
  incExtChangeCounter();
430
508
  }, [
@@ -432,7 +510,7 @@ var require_dist = __commonJS({
432
510
  ]);
433
511
  var _props_transform;
434
512
  var transform = (_props_transform = props.transform) !== null && _props_transform !== void 0 ? _props_transform : internalTransform;
435
- (0, import_react10.useEffect)(function() {
513
+ (0, import_react16.useEffect)(function() {
436
514
  var handleMouseDown = function handleMouseDown(e) {
437
515
  m0 = getMousePos(e);
438
516
  md = true;
@@ -440,7 +518,7 @@ var require_dist = __commonJS({
440
518
  };
441
519
  var handleMouseUp = function handleMouseUp(e) {
442
520
  m1 = getMousePos(e);
443
- var new_tf = (0, import_transformation_matrix4.compose)((0, import_transformation_matrix4.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
521
+ var new_tf = (0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
444
522
  setTransform(new_tf);
445
523
  init_tf = new_tf;
446
524
  md = false;
@@ -449,11 +527,11 @@ var require_dist = __commonJS({
449
527
  mlastrel = getMousePos(e);
450
528
  if (!md) return;
451
529
  m1 = getMousePos(e);
452
- setTransform((0, import_transformation_matrix4.compose)((0, import_transformation_matrix4.translate)(m1.x - m0.x, m1.y - m0.y), init_tf));
530
+ setTransform((0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(m1.x - m0.x, m1.y - m0.y), init_tf));
453
531
  };
454
532
  var handleMouseWheel = function handleMouseWheel(e) {
455
533
  var center = getMousePos(e);
456
- var new_tf = (0, import_transformation_matrix4.compose)((0, import_transformation_matrix4.translate)(center.x, center.y), (0, import_transformation_matrix4.scale)(1 - e.deltaY / 1e3, 1 - e.deltaY / 1e3), (0, import_transformation_matrix4.translate)(-center.x, -center.y), init_tf);
534
+ var new_tf = (0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(center.x, center.y), (0, import_transformation_matrix6.scale)(1 - e.deltaY / 1e3, 1 - e.deltaY / 1e3), (0, import_transformation_matrix6.translate)(-center.x, -center.y), init_tf);
457
535
  setTransform(new_tf);
458
536
  init_tf = new_tf;
459
537
  e.preventDefault();
@@ -462,7 +540,7 @@ var require_dist = __commonJS({
462
540
  if (!md) return;
463
541
  md = false;
464
542
  m1 = getMousePos(e);
465
- var new_tf = (0, import_transformation_matrix4.compose)((0, import_transformation_matrix4.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
543
+ var new_tf = (0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
466
544
  setTransform(new_tf);
467
545
  init_tf = new_tf;
468
546
  };
@@ -515,8 +593,8 @@ var require_dist = __commonJS({
515
593
  waitCounter,
516
594
  extChangeCounter
517
595
  ]);
518
- var applyTransformToPoint = (0, import_react10.useCallback)(function(obj) {
519
- return (0, import_transformation_matrix4.applyToPoint)(transform, obj);
596
+ var applyTransformToPoint = (0, import_react16.useCallback)(function(obj) {
597
+ return (0, import_transformation_matrix6.applyToPoint)(transform, obj);
520
598
  }, [
521
599
  transform
522
600
  ]);
@@ -542,14 +620,14 @@ __export(src_exports, {
542
620
  });
543
621
  module.exports = __toCommonJS(src_exports);
544
622
  // src/PCBViewer.tsx
545
- var import_react9 = __toESM(require("react"));
623
+ var import_react15 = __toESM(require("react"));
546
624
  var import_react_fiber = require("@tscircuit/react-fiber");
547
- var import_builder = require("@tscircuit/builder");
625
+ var import_builder3 = require("@tscircuit/builder");
548
626
  // src/components/CanvasElementsRenderer.tsx
549
- var import_react5 = __toESM(require("react"));
627
+ var import_react11 = __toESM(require("react"));
550
628
  // src/components/CanvasPrimitiveRenderer.tsx
551
629
  var import_react_supergrid = require("react-supergrid");
552
- var import_react = __toESM(require("react"));
630
+ var import_react4 = __toESM(require("react"));
553
631
  // src/assets/alphabet.ts
554
632
  var svgAlphabet = {
555
633
  "0": "M0.4544564813877358 0L0.2723441540828736 0.03592830447352719L0.1086847233315459 0.14528754990019965L0.020630545837255005 0.3040632652221331L0 0.5395277421960205L0.049259221760993496 0.7369487828466779L0.18080513776237842 0.9005494166306564L0.37036887043974215 0.9872116270037247L0.5864663759301132 1L0.8148695622827444 0.9332890276148733L0.9326583645506394 0.8113052246023419L1 0.4031281830668562L0.833288960385582 0.09886798567812842L0.6801767918233781 0.02483708485091681L0.4544564813877358 0",
@@ -961,6 +1039,7 @@ var LAYER_NAME_TO_COLOR = _object_spread({
961
1039
  black: "black",
962
1040
  green: "green",
963
1041
  board: "white",
1042
+ other: "#eee",
964
1043
  // TODO more builtin html colors
965
1044
  // Common eagle names
966
1045
  top: colors_default.board.copper.f,
@@ -978,13 +1057,29 @@ var LAYER_NAME_TO_COLOR = _object_spread({
978
1057
  tkeepout: colors_default.board.b_crtyd,
979
1058
  tplace: colors_default.board.b_silks
980
1059
  }, colors_default.board);
1060
+ var DEFAULT_DRAW_ORDER = [
1061
+ "top",
1062
+ "inner1",
1063
+ "inner2",
1064
+ "inner3",
1065
+ "inner4",
1066
+ "inner5",
1067
+ "inner6",
1068
+ "bottom"
1069
+ ];
981
1070
  var Drawer = /*#__PURE__*/ function() {
982
1071
  "use strict";
983
- function Drawer(canvas) {
1072
+ function Drawer(canvasLayerMap) {
984
1073
  _class_call_check(this, Drawer);
985
- this.canvas = canvas;
986
- this.canvas = canvas;
987
- this.ctx = canvas.getContext("2d");
1074
+ this.foregroundLayer = "top";
1075
+ this.canvasLayerMap = canvasLayerMap;
1076
+ this.ctxLayerMap = Object.fromEntries(Object.entries(canvasLayerMap).map(function(param) {
1077
+ var _param = _sliced_to_array(param, 2), name = _param[0], canvas = _param[1];
1078
+ return [
1079
+ name,
1080
+ canvas.getContext("2d")
1081
+ ];
1082
+ }));
988
1083
  this.transform = (0, import_transformation_matrix.identity)();
989
1084
  this.transform.d *= -1;
990
1085
  this.transform = (0, import_transformation_matrix.compose)(this.transform, (0, import_transformation_matrix.translate)(0, -500));
@@ -998,20 +1093,40 @@ var Drawer = /*#__PURE__*/ function() {
998
1093
  {
999
1094
  key: "clear",
1000
1095
  value: function clear() {
1001
- var _this = this, ctx = _this.ctx, canvas = _this.canvas;
1002
- ctx.clearRect(0, 0, canvas.width, canvas.height);
1096
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1097
+ try {
1098
+ for(var _iterator = Object.values(this.ctxLayerMap)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1099
+ var ctx = _step.value;
1100
+ ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
1101
+ }
1102
+ } catch (err) {
1103
+ _didIteratorError = true;
1104
+ _iteratorError = err;
1105
+ } finally{
1106
+ try {
1107
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1108
+ _iterator.return();
1109
+ }
1110
+ } finally{
1111
+ if (_didIteratorError) {
1112
+ throw _iteratorError;
1113
+ }
1114
+ }
1115
+ }
1003
1116
  }
1004
1117
  },
1005
1118
  {
1006
1119
  key: "equip",
1007
- value: function equip(aperature) {
1120
+ value: function equip(aperture) {
1008
1121
  this.aperture = _object_spread({
1009
1122
  fontSize: 0,
1010
1123
  shape: "circle",
1011
1124
  mode: "add",
1012
1125
  size: 0,
1013
- color: "red"
1014
- }, aperature);
1126
+ color: "red",
1127
+ layer: "top",
1128
+ opacity: this.foregroundLayer === aperture.color ? 1 : 0.5
1129
+ }, aperture);
1015
1130
  }
1016
1131
  },
1017
1132
  {
@@ -1026,7 +1141,8 @@ var Drawer = /*#__PURE__*/ function() {
1026
1141
  y + h / 2
1027
1142
  ]), 2), x2$ = _ref1[0], y2$ = _ref1[1];
1028
1143
  this.applyAperture();
1029
- this.ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$);
1144
+ var ctx = this.getLayerCtx();
1145
+ ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$);
1030
1146
  }
1031
1147
  },
1032
1148
  {
@@ -1038,10 +1154,11 @@ var Drawer = /*#__PURE__*/ function() {
1038
1154
  y
1039
1155
  ]), 2), x$ = _ref[0], y$ = _ref[1];
1040
1156
  this.applyAperture();
1041
- this.ctx.beginPath();
1042
- this.ctx.arc(x$, y$, r$, 0, 2 * Math.PI);
1043
- this.ctx.fill();
1044
- this.ctx.closePath();
1157
+ var ctx = this.getLayerCtx();
1158
+ ctx.beginPath();
1159
+ ctx.arc(x$, y$, r$, 0, 2 * Math.PI);
1160
+ ctx.fill();
1161
+ ctx.closePath();
1045
1162
  }
1046
1163
  },
1047
1164
  {
@@ -1052,15 +1169,65 @@ var Drawer = /*#__PURE__*/ function() {
1052
1169
  y
1053
1170
  ]), 2), x$ = _ref[0], y$ = _ref[1];
1054
1171
  this.applyAperture();
1055
- this.ctx.font = "10px sans-serif";
1056
- this.ctx.fillText(text, x$, y$);
1172
+ var ctx = this.getLayerCtx();
1173
+ ctx.font = "10px sans-serif";
1174
+ ctx.fillText(text, x$, y$);
1175
+ }
1176
+ },
1177
+ {
1178
+ key: "getLayerCtx",
1179
+ value: function getLayerCtx() {
1180
+ var ctx = this.ctxLayerMap[this.aperture.layer];
1181
+ if (!ctx) {
1182
+ throw new Error('No context for layer "'.concat(this.aperture.layer, '"'));
1183
+ }
1184
+ return ctx;
1185
+ }
1186
+ },
1187
+ {
1188
+ /**
1189
+ * Iterate over each canvas and set the z index based on the layer order, but
1190
+ * always render the foreground layer on top.
1191
+ *
1192
+ * Also: Set the opacity of every non-foreground layer to 0.5
1193
+ */ key: "orderAndFadeLayers",
1194
+ value: function orderAndFadeLayers() {
1195
+ var _this = this, canvasLayerMap = _this.canvasLayerMap, foregroundLayer = _this.foregroundLayer;
1196
+ var opaqueLayers = /* @__PURE__ */ new Set([
1197
+ foregroundLayer,
1198
+ "drill",
1199
+ "other",
1200
+ "board"
1201
+ ]);
1202
+ var order = [
1203
+ "drill",
1204
+ "board",
1205
+ foregroundLayer
1206
+ ].concat(_to_consumable_array(DEFAULT_DRAW_ORDER.filter(function(l) {
1207
+ return l !== foregroundLayer;
1208
+ })));
1209
+ order.forEach(function(layer, i) {
1210
+ var canvas = canvasLayerMap[layer];
1211
+ if (!canvas) return;
1212
+ canvas.style.zIndex = "".concat(100 - i);
1213
+ canvas.style.opacity = opaqueLayers.has(layer) ? "1" : "0.5";
1214
+ });
1057
1215
  }
1058
1216
  },
1059
1217
  {
1060
1218
  key: "applyAperture",
1061
1219
  value: function applyAperture() {
1062
- var _this = this, ctx = _this.ctx, transform = _this.transform, aperture = _this.aperture;
1220
+ var _this = this, transform = _this.transform, aperture = _this.aperture;
1063
1221
  var size = aperture.size, mode = aperture.mode, color = aperture.color, fontSize = aperture.fontSize;
1222
+ if (color in this.ctxLayerMap) {
1223
+ this.aperture.layer = color;
1224
+ } else {
1225
+ this.aperture.layer = "other";
1226
+ }
1227
+ var ctx = this.getLayerCtx();
1228
+ if (!ctx) {
1229
+ throw new Error('No context for layer "'.concat(this.foregroundLayer, '"'));
1230
+ }
1064
1231
  if (!color) color = "undefined";
1065
1232
  ctx.lineWidth = scaleOnly(transform, size);
1066
1233
  ctx.lineCap = "round";
@@ -1098,9 +1265,10 @@ var Drawer = /*#__PURE__*/ function() {
1098
1265
  ]), 2), x$ = _ref[0], y$ = _ref[1];
1099
1266
  var _this_aperture = this.aperture, size = _this_aperture.size, shape = _this_aperture.shape, mode = _this_aperture.mode;
1100
1267
  var size$ = scaleOnly(this.transform, size);
1101
- var _this = this, lastPoint = _this.lastPoint, ctx = _this.ctx;
1268
+ var lastPoint = this.lastPoint;
1102
1269
  var lastPoint$ = (0, import_transformation_matrix.applyToPoint)(this.transform, lastPoint);
1103
1270
  this.applyAperture();
1271
+ var ctx = this.getLayerCtx();
1104
1272
  if (shape === "square") ctx.fillRect(lastPoint$.x - size$ / 2, lastPoint$.y - size$ / 2, size$, size$);
1105
1273
  ctx.beginPath();
1106
1274
  ctx.moveTo(lastPoint$.x, lastPoint$.y);
@@ -1117,28 +1285,69 @@ var Drawer = /*#__PURE__*/ function() {
1117
1285
  ]);
1118
1286
  return Drawer;
1119
1287
  }();
1288
+ // src/global-store.ts
1289
+ var import_zustand = require("zustand");
1290
+ // src/components/ContextProviders.tsx
1291
+ var import_react = require("react");
1292
+ var import_react2 = require("react");
1293
+ var StoreContext = (0, import_react2.createContext)(null);
1294
+ var ContextProviders = function(param) {
1295
+ var children = param.children;
1296
+ var store = (0, import_react.useMemo)(function() {
1297
+ return createStore();
1298
+ }, []);
1299
+ return /* @__PURE__ */ React.createElement(StoreContext.Provider, {
1300
+ value: store
1301
+ }, children);
1302
+ };
1303
+ // src/global-store.ts
1304
+ var import_react3 = require("react");
1305
+ var createStore = function() {
1306
+ return (0, import_zustand.createStore)(function(set) {
1307
+ return {
1308
+ selected_layer: "top",
1309
+ selectLayer: function(layer) {
1310
+ return set({
1311
+ selected_layer: layer
1312
+ });
1313
+ }
1314
+ };
1315
+ });
1316
+ };
1317
+ var useStore = function(s) {
1318
+ var store = (0, import_react3.useContext)(StoreContext);
1319
+ return (0, import_zustand.useStore)(store, s);
1320
+ };
1120
1321
  // src/components/CanvasPrimitiveRenderer.tsx
1322
+ var import_builder = require("@tscircuit/builder");
1121
1323
  var CanvasPrimitiveRenderer = function(param) {
1122
1324
  var primitives = param.primitives, transform = param.transform, grid = param.grid, _param_width = param.width, width = _param_width === void 0 ? 500 : _param_width, _param_height = param.height, height = _param_height === void 0 ? 500 : _param_height;
1123
- var ref = (0, import_react.useRef)();
1124
- (0, import_react.useEffect)(function() {
1125
- if (!ref.current) return;
1126
- var drawer = new Drawer(ref.current);
1325
+ var canvasRefs = (0, import_react4.useRef)();
1326
+ var selectedLayer = useStore(function(s) {
1327
+ return s.selected_layer;
1328
+ });
1329
+ (0, import_react4.useEffect)(function() {
1330
+ if (!canvasRefs.current) return;
1331
+ if (Object.keys(canvasRefs.current).length === 0) return;
1332
+ var drawer = new Drawer(canvasRefs.current);
1127
1333
  if (transform) drawer.transform = transform;
1128
1334
  drawer.clear();
1335
+ drawer.foregroundLayer = selectedLayer;
1129
1336
  drawPrimitives(drawer, primitives);
1337
+ drawer.orderAndFadeLayers();
1130
1338
  }, [
1131
1339
  primitives,
1132
- transform
1340
+ transform,
1341
+ selectedLayer
1133
1342
  ]);
1134
- return /* @__PURE__ */ import_react.default.createElement("div", {
1343
+ return /* @__PURE__ */ import_react4.default.createElement("div", {
1135
1344
  style: {
1136
1345
  backgroundColor: "black",
1137
1346
  width: width,
1138
1347
  height: height,
1139
1348
  position: "relative"
1140
1349
  }
1141
- }, /* @__PURE__ */ import_react.default.createElement(import_react_supergrid.SuperGrid, {
1350
+ }, /* @__PURE__ */ import_react4.default.createElement(import_react_supergrid.SuperGrid, {
1142
1351
  textColor: "rgba(0,255,0,0.8)",
1143
1352
  majorColor: "rgba(0,255,0,0.4)",
1144
1353
  minorColor: "rgba(0,255,0,0.2)",
@@ -1149,20 +1358,32 @@ var CanvasPrimitiveRenderer = function(param) {
1149
1358
  stringifyCoord: function(x, y, z) {
1150
1359
  return "".concat((0, import_react_supergrid.toMMSI)(x, z), ", ").concat((0, import_react_supergrid.toMMSI)(y, z));
1151
1360
  }
1152
- }), /* @__PURE__ */ import_react.default.createElement("canvas", {
1153
- ref: ref,
1154
- style: {
1155
- position: "absolute",
1156
- left: 0,
1157
- top: 0,
1158
- pointerEvents: "none"
1159
- },
1160
- width: width,
1161
- height: height
1361
+ }), import_builder.all_layers.map(function(l) {
1362
+ return l.replace(/-/g, "");
1363
+ }).concat([
1364
+ "drill",
1365
+ "other"
1366
+ ]).map(function(layer, i) {
1367
+ return /* @__PURE__ */ import_react4.default.createElement("canvas", {
1368
+ key: layer,
1369
+ ref: function(el) {
1370
+ var _canvasRefs_current;
1371
+ (_canvasRefs_current = canvasRefs.current) !== null && _canvasRefs_current !== void 0 ? _canvasRefs_current : canvasRefs.current = {};
1372
+ canvasRefs.current[layer] = el;
1373
+ },
1374
+ style: {
1375
+ position: "absolute",
1376
+ left: 0,
1377
+ top: 0,
1378
+ pointerEvents: "none"
1379
+ },
1380
+ width: width,
1381
+ height: height
1382
+ });
1162
1383
  }));
1163
1384
  };
1164
1385
  // src/components/CanvasElementsRenderer.tsx
1165
- var import_react6 = require("react");
1386
+ var import_react12 = require("react");
1166
1387
  // src/lib/convert-element-to-primitive.ts
1167
1388
  var convertElementToPrimitives = function(element, allElements) {
1168
1389
  var _parent_pcb_component = "pcb_component_id" in element ? allElements.find(function(elm) {
@@ -1388,11 +1609,11 @@ var convertElementToPrimitives = function(element, allElements) {
1388
1609
  return [];
1389
1610
  };
1390
1611
  // src/components/MouseElementTracker.tsx
1391
- var import_react3 = __toESM(require("react"));
1392
- var import_react4 = require("react");
1612
+ var import_react6 = __toESM(require("react"));
1613
+ var import_react7 = require("react");
1393
1614
  var import_transformation_matrix2 = require("transformation-matrix");
1394
1615
  // src/components/ElementOverlayBox.tsx
1395
- var import_react2 = __toESM(require("react"));
1616
+ var import_react5 = __toESM(require("react"));
1396
1617
  var containerStyle = {
1397
1618
  position: "absolute",
1398
1619
  left: 0,
@@ -1433,8 +1654,8 @@ var layerColorHightlightMap = {
1433
1654
  var HighlightedPrimitiveBoxWithText = function(param) {
1434
1655
  var primitive = param.primitive;
1435
1656
  var _primitive__element;
1436
- var _ref = _sliced_to_array((0, import_react2.useState)(false), 2), finalState = _ref[0], setFinalState = _ref[1];
1437
- (0, import_react2.useEffect)(function() {
1657
+ var _ref = _sliced_to_array((0, import_react5.useState)(false), 2), finalState = _ref[0], setFinalState = _ref[1];
1658
+ (0, import_react5.useEffect)(function() {
1438
1659
  setTimeout(function() {
1439
1660
  setFinalState(true);
1440
1661
  }, 100);
@@ -1450,7 +1671,7 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1450
1671
  var sip = 26;
1451
1672
  var _layerColorHightlightMap_primitive__element_layer;
1452
1673
  var color = (_layerColorHightlightMap_primitive__element_layer = layerColorHightlightMap[primitive === null || primitive === void 0 ? void 0 : (_primitive__element = primitive._element) === null || _primitive__element === void 0 ? void 0 : _primitive__element.layer]) !== null && _layerColorHightlightMap_primitive__element_layer !== void 0 ? _layerColorHightlightMap_primitive__element_layer : "red";
1453
- return /* @__PURE__ */ import_react2.default.createElement("div", {
1674
+ return /* @__PURE__ */ import_react5.default.createElement("div", {
1454
1675
  style: {
1455
1676
  position: "absolute",
1456
1677
  left: x - w / 2 - 8,
@@ -1459,7 +1680,7 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1459
1680
  height: h + 16,
1460
1681
  color: color
1461
1682
  }
1462
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
1683
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
1463
1684
  style: {
1464
1685
  // width: finalState ? `${100 + 20 * si}%` : "100%",
1465
1686
  // height: finalState ? `${100 + 20 * si}%` : "100%",
@@ -1473,7 +1694,7 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1473
1694
  opacity: finalState ? 1 : si === 0 ? 1 : 0,
1474
1695
  transition: "width 0.2s, height 0.2s, margin-left 0.2s, margin-top 0.2s, opacity 0.2s"
1475
1696
  }
1476
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
1697
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
1477
1698
  style: {
1478
1699
  position: "absolute",
1479
1700
  left: 0,
@@ -1487,10 +1708,10 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1487
1708
  };
1488
1709
  var ElementOverlayBox = function(param) {
1489
1710
  var highlightedPrimitives = param.highlightedPrimitives;
1490
- return /* @__PURE__ */ import_react2.default.createElement("div", {
1711
+ return /* @__PURE__ */ import_react5.default.createElement("div", {
1491
1712
  style: containerStyle
1492
1713
  }, highlightedPrimitives.map(function(primitive, i) {
1493
- return /* @__PURE__ */ import_react2.default.createElement(HighlightedPrimitiveBoxWithText, {
1714
+ return /* @__PURE__ */ import_react5.default.createElement(HighlightedPrimitiveBoxWithText, {
1494
1715
  key: i,
1495
1716
  primitive: primitive
1496
1717
  });
@@ -1499,8 +1720,8 @@ var ElementOverlayBox = function(param) {
1499
1720
  // src/components/MouseElementTracker.tsx
1500
1721
  var MouseElementTracker = function(param) {
1501
1722
  var children = param.children, transform = param.transform, primitives = param.primitives;
1502
- var _ref = _sliced_to_array((0, import_react3.useState)([]), 2), mousedPrimitives = _ref[0], setMousedPrimitives = _ref[1];
1503
- var highlightedPrimitives = (0, import_react4.useMemo)(function() {
1723
+ var _ref = _sliced_to_array((0, import_react6.useState)([]), 2), mousedPrimitives = _ref[0], setMousedPrimitives = _ref[1];
1724
+ var highlightedPrimitives = (0, import_react7.useMemo)(function() {
1504
1725
  var highlightedPrimitives2 = [];
1505
1726
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1506
1727
  try {
@@ -1513,8 +1734,8 @@ var MouseElementTracker = function(param) {
1513
1734
  var w = "w" in primitive ? primitive.w : "r" in primitive ? primitive.r * 2 : 0;
1514
1735
  var h = "h" in primitive ? primitive.h : "r" in primitive ? primitive.r * 2 : 0;
1515
1736
  var screenSize = {
1516
- w: w * transform.d,
1517
- h: h * transform.d
1737
+ w: w * transform.a,
1738
+ h: h * transform.a
1518
1739
  };
1519
1740
  var same_space_index = highlightedPrimitives2.filter(function(hp) {
1520
1741
  return screenPos.x === hp.screen_x && screenPos.y === hp.screen_y && screenSize.w === hp.screen_w && screenSize.h === hp.screen_h;
@@ -1547,7 +1768,7 @@ var MouseElementTracker = function(param) {
1547
1768
  mousedPrimitives,
1548
1769
  transform
1549
1770
  ]);
1550
- return /* @__PURE__ */ import_react3.default.createElement("div", {
1771
+ return /* @__PURE__ */ import_react6.default.createElement("div", {
1551
1772
  style: {
1552
1773
  position: "relative"
1553
1774
  },
@@ -1590,13 +1811,403 @@ var MouseElementTracker = function(param) {
1590
1811
  setMousedPrimitives(mousedPrimitives2);
1591
1812
  }
1592
1813
  }
1593
- }, children, /* @__PURE__ */ import_react3.default.createElement(ElementOverlayBox, {
1814
+ }, children, /* @__PURE__ */ import_react6.default.createElement(ElementOverlayBox, {
1594
1815
  highlightedPrimitives: highlightedPrimitives
1595
1816
  }));
1596
1817
  };
1818
+ // src/components/DimensionOverlay.tsx
1819
+ var import_react8 = require("react");
1820
+ var import_transformation_matrix3 = require("transformation-matrix");
1821
+ var DimensionOverlay = function(param) {
1822
+ var children = param.children, transform = param.transform;
1823
+ if (!transform) transform = (0, import_transformation_matrix3.identity)();
1824
+ var _ref = _sliced_to_array((0, import_react8.useState)(false), 2), dimensionToolVisible = _ref[0], setDimensionToolVisible = _ref[1];
1825
+ var _ref1 = _sliced_to_array((0, import_react8.useState)(false), 2), dimensionToolStretching = _ref1[0], setDimensionToolStretching = _ref1[1];
1826
+ var _ref2 = _sliced_to_array((0, import_react8.useState)({
1827
+ x: 0,
1828
+ y: 0
1829
+ }), 2), dStart = _ref2[0], setDStart = _ref2[1];
1830
+ var _ref3 = _sliced_to_array((0, import_react8.useState)({
1831
+ x: 0,
1832
+ y: 0
1833
+ }), 2), dEnd = _ref3[0], setDEnd = _ref3[1];
1834
+ var mousePosRef = (0, import_react8.useRef)({
1835
+ x: 0,
1836
+ y: 0
1837
+ });
1838
+ var containerRef = (0, import_react8.useRef)(null);
1839
+ var container = containerRef.current;
1840
+ var containerBounds = container === null || container === void 0 ? void 0 : container.getBoundingClientRect();
1841
+ (0, import_react8.useEffect)(function() {
1842
+ var down = function(e) {
1843
+ if (e.key === "d") {
1844
+ setDStart({
1845
+ x: mousePosRef.current.x,
1846
+ y: mousePosRef.current.y
1847
+ });
1848
+ setDEnd({
1849
+ x: mousePosRef.current.x,
1850
+ y: mousePosRef.current.y
1851
+ });
1852
+ setDimensionToolVisible(function(visible) {
1853
+ return !visible;
1854
+ });
1855
+ setDimensionToolStretching(true);
1856
+ e.preventDefault();
1857
+ }
1858
+ if (e.key === "Escape") {
1859
+ setDimensionToolVisible(false);
1860
+ setDimensionToolStretching(false);
1861
+ }
1862
+ };
1863
+ window.addEventListener("keydown", down);
1864
+ return function() {
1865
+ return window.removeEventListener("keydown", down);
1866
+ };
1867
+ }, [
1868
+ containerRef
1869
+ ]);
1870
+ var screenDStart = (0, import_transformation_matrix3.applyToPoint)(transform, dStart);
1871
+ var screenDEnd = (0, import_transformation_matrix3.applyToPoint)(transform, dEnd);
1872
+ var arrowScreenBounds = {
1873
+ left: Math.min(screenDStart.x, screenDEnd.x),
1874
+ right: Math.max(screenDStart.x, screenDEnd.x),
1875
+ top: Math.min(screenDStart.y, screenDEnd.y),
1876
+ bottom: Math.max(screenDStart.y, screenDEnd.y),
1877
+ flipX: screenDStart.x > screenDEnd.x,
1878
+ flipY: screenDStart.y > screenDEnd.y,
1879
+ width: 0,
1880
+ height: 0
1881
+ };
1882
+ arrowScreenBounds.width = arrowScreenBounds.right - arrowScreenBounds.left;
1883
+ arrowScreenBounds.height = arrowScreenBounds.bottom - arrowScreenBounds.top;
1884
+ return /* @__PURE__ */ React.createElement("div", {
1885
+ ref: containerRef,
1886
+ style: {
1887
+ position: "relative"
1888
+ },
1889
+ onMouseMove: function(e) {
1890
+ var rect = e.currentTarget.getBoundingClientRect();
1891
+ var x = e.clientX - rect.left;
1892
+ var y = e.clientY - rect.top;
1893
+ var rwPoint = (0, import_transformation_matrix3.applyToPoint)((0, import_transformation_matrix3.inverse)(transform), {
1894
+ x: x,
1895
+ y: y
1896
+ });
1897
+ mousePosRef.current.x = rwPoint.x;
1898
+ mousePosRef.current.y = rwPoint.y;
1899
+ if (dimensionToolStretching) {
1900
+ setDEnd({
1901
+ x: rwPoint.x,
1902
+ y: rwPoint.y
1903
+ });
1904
+ }
1905
+ },
1906
+ onMouseDown: function() {
1907
+ if (dimensionToolStretching) {
1908
+ setDimensionToolStretching(false);
1909
+ } else if (dimensionToolVisible) {
1910
+ setDimensionToolVisible(false);
1911
+ }
1912
+ }
1913
+ }, children, dimensionToolVisible && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
1914
+ style: {
1915
+ position: "absolute",
1916
+ left: arrowScreenBounds.left,
1917
+ width: arrowScreenBounds.width,
1918
+ textAlign: "center",
1919
+ top: screenDStart.y + 2,
1920
+ color: "red",
1921
+ mixBlendMode: "difference",
1922
+ pointerEvents: "none",
1923
+ marginTop: arrowScreenBounds.flipY ? 0 : -20,
1924
+ fontSize: 12,
1925
+ fontFamily: "sans-serif",
1926
+ zIndex: 1e3
1927
+ }
1928
+ }, Math.abs(dStart.x - dEnd.x).toFixed(2)), /* @__PURE__ */ React.createElement("div", {
1929
+ style: {
1930
+ position: "absolute",
1931
+ left: screenDEnd.x,
1932
+ height: arrowScreenBounds.height,
1933
+ display: "flex",
1934
+ flexDirection: "column",
1935
+ justifyContent: "center",
1936
+ top: arrowScreenBounds.top,
1937
+ color: "red",
1938
+ pointerEvents: "none",
1939
+ mixBlendMode: "difference",
1940
+ fontSize: 12,
1941
+ fontFamily: "sans-serif",
1942
+ zIndex: 1e3
1943
+ }
1944
+ }, /* @__PURE__ */ React.createElement("div", {
1945
+ style: {
1946
+ marginLeft: arrowScreenBounds.flipX ? "-100%" : 4,
1947
+ paddingRight: 4
1948
+ }
1949
+ }, Math.abs(dStart.y - dEnd.y).toFixed(2))), /* @__PURE__ */ React.createElement("svg", {
1950
+ style: {
1951
+ position: "absolute",
1952
+ left: 0,
1953
+ top: 0,
1954
+ pointerEvents: "none",
1955
+ mixBlendMode: "difference",
1956
+ zIndex: 1e3
1957
+ },
1958
+ width: containerBounds.width,
1959
+ height: containerBounds.height
1960
+ }, /* @__PURE__ */ React.createElement("defs", null, /* @__PURE__ */ React.createElement("marker", {
1961
+ id: "head",
1962
+ orient: "auto",
1963
+ markerWidth: "3",
1964
+ markerHeight: "4",
1965
+ refX: "2",
1966
+ refY: "2"
1967
+ }, /* @__PURE__ */ React.createElement("path", {
1968
+ d: "M0,0 V4 L2,2 Z",
1969
+ fill: "red"
1970
+ }))), /* @__PURE__ */ React.createElement("line", {
1971
+ x1: screenDStart.x,
1972
+ y1: screenDStart.y,
1973
+ x2: screenDEnd.x,
1974
+ y2: screenDEnd.y,
1975
+ markerEnd: "url(#head)",
1976
+ strokeWidth: 1.5,
1977
+ fill: "none",
1978
+ stroke: "red"
1979
+ }), /* @__PURE__ */ React.createElement("line", {
1980
+ x1: screenDStart.x,
1981
+ y1: screenDStart.y,
1982
+ x2: screenDEnd.x,
1983
+ y2: screenDStart.y,
1984
+ strokeWidth: 1.5,
1985
+ fill: "none",
1986
+ strokeDasharray: "2,2",
1987
+ stroke: "red"
1988
+ }), /* @__PURE__ */ React.createElement("line", {
1989
+ x1: screenDEnd.x,
1990
+ y1: screenDStart.y,
1991
+ x2: screenDEnd.x,
1992
+ y2: screenDEnd.y,
1993
+ strokeWidth: 1.5,
1994
+ fill: "none",
1995
+ strokeDasharray: "2,2",
1996
+ stroke: "red"
1997
+ })), /* @__PURE__ */ React.createElement("div", {
1998
+ style: {
1999
+ right: 0,
2000
+ bottom: 0,
2001
+ position: "absolute",
2002
+ color: "red",
2003
+ fontFamily: "sans-serif",
2004
+ fontSize: 12,
2005
+ margin: 4
2006
+ }
2007
+ }, "(", dStart.x.toFixed(2), ",", dStart.y.toFixed(2), ")", /* @__PURE__ */ React.createElement("br", null), "(", dEnd.x.toFixed(2), ",", dEnd.y.toFixed(2), ")", /* @__PURE__ */ React.createElement("br", null), "dist:", " ", Math.sqrt(Math.pow(dEnd.x - dStart.x, 2) + Math.pow(dEnd.y - dStart.y, 2)).toFixed(2))));
2008
+ };
2009
+ // src/components/ToolbarOverlay.tsx
2010
+ var import_react9 = require("react");
2011
+ var import_css = require("@emotion/css");
2012
+ var import_builder2 = require("@tscircuit/builder");
2013
+ var LayerButton = function(param) {
2014
+ var name = param.name, selected = param.selected, onClick = param.onClick;
2015
+ return /* @__PURE__ */ React.createElement("div", {
2016
+ className: import_css.css(_templateObject()),
2017
+ onClick: onClick
2018
+ }, /* @__PURE__ */ React.createElement("span", {
2019
+ style: {
2020
+ marginRight: 2,
2021
+ opacity: selected ? 1 : 0
2022
+ }
2023
+ }, "•"), /* @__PURE__ */ React.createElement("span", {
2024
+ style: {
2025
+ marginLeft: 2,
2026
+ fontWeight: 500,
2027
+ color: LAYER_NAME_TO_COLOR[name.replace(/-/, "")]
2028
+ }
2029
+ }, name));
2030
+ };
2031
+ var ToolbarButton = function(_param) {
2032
+ var children = _param.children, props = _object_without_properties(_param, [
2033
+ "children"
2034
+ ]);
2035
+ return /* @__PURE__ */ React.createElement("div", _object_spread_props(_object_spread({}, props), {
2036
+ style: _object_spread({
2037
+ backgroundColor: "#1F1F1F",
2038
+ border: "1px solid #666",
2039
+ margin: 4,
2040
+ padding: 4,
2041
+ paddingLeft: 6,
2042
+ paddingRight: 6,
2043
+ borderRadius: 2,
2044
+ alignSelf: "start",
2045
+ color: "#eee",
2046
+ cursor: "pointer"
2047
+ }, props.style)
2048
+ }), children);
2049
+ };
2050
+ var ToolbarOverlay = function(param) {
2051
+ var children = param.children, elements = param.elements;
2052
+ var _ref = _sliced_to_array((0, import_react9.useState)(false), 2), isMouseOverContainer = _ref[0], setIsMouseOverContainer = _ref[1];
2053
+ var _ref1 = _sliced_to_array((0, import_react9.useState)(false), 2), isLayerMenuOpen = _ref1[0], setLayerMenuOpen = _ref1[1];
2054
+ var _ref2 = _sliced_to_array((0, import_react9.useState)(false), 2), isErrorsOpen = _ref2[0], setErrorsOpen = _ref2[1];
2055
+ var _useStore = _sliced_to_array(useStore(function(s) {
2056
+ return [
2057
+ s.selected_layer,
2058
+ s.selectLayer
2059
+ ];
2060
+ }), 2), selectedLayer = _useStore[0], selectLayer = _useStore[1];
2061
+ var _elements_filter_length;
2062
+ var errorCount = (_elements_filter_length = elements === null || elements === void 0 ? void 0 : elements.filter(function(e) {
2063
+ return e.type.includes("error");
2064
+ }).length) !== null && _elements_filter_length !== void 0 ? _elements_filter_length : 0;
2065
+ return /* @__PURE__ */ React.createElement("div", {
2066
+ style: {
2067
+ position: "relative"
2068
+ },
2069
+ onMouseEnter: function() {
2070
+ setIsMouseOverContainer(true);
2071
+ },
2072
+ onMouseLeave: function() {
2073
+ setIsMouseOverContainer(false);
2074
+ setLayerMenuOpen(false);
2075
+ }
2076
+ }, children, /* @__PURE__ */ React.createElement("div", {
2077
+ style: {
2078
+ position: "absolute",
2079
+ opacity: isMouseOverContainer ? 1 : 0,
2080
+ top: 16,
2081
+ left: 16,
2082
+ transition: isMouseOverContainer ? "opacity 100ms linear" : "opacity 1s linear",
2083
+ zIndex: 100,
2084
+ color: "red",
2085
+ display: "flex",
2086
+ fontSize: 12,
2087
+ height: 100,
2088
+ fontFamily: "sans-serif"
2089
+ }
2090
+ }, /* @__PURE__ */ React.createElement(ToolbarButton, {
2091
+ onClick: function() {
2092
+ setLayerMenuOpen(!isLayerMenuOpen);
2093
+ },
2094
+ onMouseLeave: function() {
2095
+ if (isLayerMenuOpen) {
2096
+ setLayerMenuOpen(false);
2097
+ }
2098
+ }
2099
+ }, /* @__PURE__ */ React.createElement("div", null, "layer:", " ", /* @__PURE__ */ React.createElement("span", {
2100
+ style: {
2101
+ marginLeft: 2,
2102
+ fontWeight: 500,
2103
+ color: LAYER_NAME_TO_COLOR[selectedLayer]
2104
+ }
2105
+ }, selectedLayer)), isLayerMenuOpen && /* @__PURE__ */ React.createElement("div", {
2106
+ style: {
2107
+ marginTop: 4,
2108
+ minWidth: 120
2109
+ }
2110
+ }, import_builder2.all_layers.map(function(l) {
2111
+ return l.replace(/-/g, "");
2112
+ }).map(function(layer) {
2113
+ return /* @__PURE__ */ React.createElement(LayerButton, {
2114
+ key: layer,
2115
+ name: layer,
2116
+ selected: layer === selectedLayer,
2117
+ onClick: function() {
2118
+ selectLayer(layer.replace(/-/, ""));
2119
+ }
2120
+ });
2121
+ }))), /* @__PURE__ */ React.createElement(ToolbarButton, {
2122
+ style: errorCount > 0 ? {
2123
+ color: "red"
2124
+ } : {},
2125
+ onClick: function() {
2126
+ return setErrorsOpen(!isErrorsOpen);
2127
+ },
2128
+ onMouseLeave: function() {
2129
+ return setErrorsOpen(false);
2130
+ }
2131
+ }, /* @__PURE__ */ React.createElement("div", null, errorCount, " errors"), isErrorsOpen && /* @__PURE__ */ React.createElement("div", {
2132
+ style: {
2133
+ display: "grid",
2134
+ gridTemplateColumns: "100px 300px"
2135
+ }
2136
+ }, elements === null || elements === void 0 ? void 0 : elements.filter(function(e) {
2137
+ return e.type.includes("error");
2138
+ }).map(function(e, i) {
2139
+ return /* @__PURE__ */ React.createElement(import_react9.Fragment, {
2140
+ key: i
2141
+ }, /* @__PURE__ */ React.createElement("div", null, e.error_type), /* @__PURE__ */ React.createElement("div", null, e.message));
2142
+ })))));
2143
+ };
2144
+ // src/components/ErrorOverlay.tsx
2145
+ var import_css2 = require("@emotion/css");
2146
+ var import_react10 = require("react");
2147
+ var import_transformation_matrix4 = require("transformation-matrix");
2148
+ var ErrorOverlay = function(param) {
2149
+ var children = param.children, transform = param.transform, elements = param.elements;
2150
+ var _containerRef_current;
2151
+ if (!transform) transform = (0, import_transformation_matrix4.identity)();
2152
+ var containerRef = (0, import_react10.useRef)(null);
2153
+ var containerBounds = containerRef === null || containerRef === void 0 ? void 0 : (_containerRef_current = containerRef.current) === null || _containerRef_current === void 0 ? void 0 : _containerRef_current.getBoundingClientRect();
2154
+ return /* @__PURE__ */ React.createElement("div", {
2155
+ style: {
2156
+ position: "relative"
2157
+ },
2158
+ ref: containerRef
2159
+ }, children, elements === null || elements === void 0 ? void 0 : elements.filter(function(el) {
2160
+ return el.type === "pcb_error";
2161
+ }).map(function(el) {
2162
+ var pcb_port_ids = el.pcb_port_ids;
2163
+ var port1 = elements.find(function(el2) {
2164
+ return el2.type === "pcb_port" && el2.pcb_port_id === pcb_port_ids[0];
2165
+ });
2166
+ var port2 = elements.find(function(el2) {
2167
+ return el2.type === "pcb_port" && el2.pcb_port_id === pcb_port_ids[1];
2168
+ });
2169
+ if (!port1 || !port2) return null;
2170
+ var screenPort1 = (0, import_transformation_matrix4.applyToPoint)(transform, {
2171
+ x: port1.x,
2172
+ y: port1.y
2173
+ });
2174
+ var screenPort2 = (0, import_transformation_matrix4.applyToPoint)(transform, {
2175
+ x: port2.x,
2176
+ y: port2.y
2177
+ });
2178
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("svg", {
2179
+ style: {
2180
+ position: "absolute",
2181
+ left: 0,
2182
+ top: 0,
2183
+ pointerEvents: "none",
2184
+ mixBlendMode: "difference",
2185
+ zIndex: 1e3
2186
+ },
2187
+ width: containerBounds === null || containerBounds === void 0 ? void 0 : containerBounds.width,
2188
+ height: containerBounds === null || containerBounds === void 0 ? void 0 : containerBounds.height
2189
+ }, /* @__PURE__ */ React.createElement("line", {
2190
+ x1: screenPort1.x,
2191
+ y1: screenPort1.y,
2192
+ x2: screenPort2.x,
2193
+ y2: screenPort2.y,
2194
+ markerEnd: "url(#head)",
2195
+ strokeWidth: 1.5,
2196
+ strokeDasharray: "2,2",
2197
+ fill: "none",
2198
+ stroke: "red"
2199
+ })), /* @__PURE__ */ React.createElement("div", {
2200
+ className: import_css2.css(_templateObject1(), (screenPort1.x + screenPort2.x) / 2, (screenPort1.y + screenPort2.y) / 2)
2201
+ }, /* @__PURE__ */ React.createElement("div", {
2202
+ className: "error-message"
2203
+ }, el.message), /* @__PURE__ */ React.createElement("div", {
2204
+ className: import_css2.css(_templateObject2())
2205
+ })));
2206
+ }));
2207
+ };
1597
2208
  // src/components/CanvasElementsRenderer.tsx
1598
2209
  var CanvasElementsRenderer = function(props) {
1599
- var primitives = (0, import_react6.useMemo)(function() {
2210
+ var primitives = (0, import_react12.useMemo)(function() {
1600
2211
  var primitives2 = props.elements.flatMap(function(elm) {
1601
2212
  return convertElementToPrimitives(elm, props.elements);
1602
2213
  });
@@ -1604,16 +2215,23 @@ var CanvasElementsRenderer = function(props) {
1604
2215
  }, [
1605
2216
  props.elements
1606
2217
  ]);
1607
- return /* @__PURE__ */ import_react5.default.createElement(MouseElementTracker, {
2218
+ return /* @__PURE__ */ import_react11.default.createElement(MouseElementTracker, {
1608
2219
  transform: props.transform,
1609
2220
  primitives: primitives
1610
- }, /* @__PURE__ */ import_react5.default.createElement(CanvasPrimitiveRenderer, {
2221
+ }, /* @__PURE__ */ import_react11.default.createElement(DimensionOverlay, {
2222
+ transform: props.transform
2223
+ }, /* @__PURE__ */ import_react11.default.createElement(ToolbarOverlay, {
2224
+ elements: props.elements
2225
+ }, /* @__PURE__ */ import_react11.default.createElement(ErrorOverlay, {
2226
+ transform: props.transform,
2227
+ elements: props.elements
2228
+ }, /* @__PURE__ */ import_react11.default.createElement(CanvasPrimitiveRenderer, {
1611
2229
  transform: props.transform,
1612
2230
  primitives: primitives,
1613
2231
  width: props.width,
1614
2232
  height: props.height,
1615
2233
  grid: props.grid
1616
- }));
2234
+ })))));
1617
2235
  };
1618
2236
  // src/PCBViewer.tsx
1619
2237
  var import_use_mouse_matrix_transform = __toESM(require_dist());
@@ -1621,11 +2239,11 @@ var import_use_mouse_matrix_transform = __toESM(require_dist());
1621
2239
  var noop = function noop() {};
1622
2240
  var isBrowser = typeof window !== "undefined";
1623
2241
  // node_modules/react-use/esm/useIsomorphicLayoutEffect.js
1624
- var import_react7 = require("react");
1625
- var useIsomorphicLayoutEffect = isBrowser ? import_react7.useLayoutEffect : import_react7.useEffect;
2242
+ var import_react13 = require("react");
2243
+ var useIsomorphicLayoutEffect = isBrowser ? import_react13.useLayoutEffect : import_react13.useEffect;
1626
2244
  var useIsomorphicLayoutEffect_default = useIsomorphicLayoutEffect;
1627
2245
  // node_modules/react-use/esm/useMeasure.js
1628
- var import_react8 = require("react");
2246
+ var import_react14 = require("react");
1629
2247
  var defaultState = {
1630
2248
  x: 0,
1631
2249
  y: 0,
@@ -1637,9 +2255,9 @@ var defaultState = {
1637
2255
  right: 0
1638
2256
  };
1639
2257
  function useMeasure() {
1640
- var _a = (0, import_react8.useState)(null), element = _a[0], ref = _a[1];
1641
- var _b = (0, import_react8.useState)(defaultState), rect = _b[0], setRect = _b[1];
1642
- var observer = (0, import_react8.useMemo)(function() {
2258
+ var _a = (0, import_react14.useState)(null), element = _a[0], ref = _a[1];
2259
+ var _b = (0, import_react14.useState)(defaultState), rect = _b[0], setRect = _b[1];
2260
+ var observer = (0, import_react14.useMemo)(function() {
1643
2261
  return new window.ResizeObserver(function(entries) {
1644
2262
  if (entries[0]) {
1645
2263
  var _a2 = entries[0].contentRect, x = _a2.x, y = _a2.y, width = _a2.width, height = _a2.height, top_1 = _a2.top, left = _a2.left, bottom = _a2.bottom, right = _a2.right;
@@ -1677,19 +2295,19 @@ var useMeasure_default = isBrowser && typeof window.ResizeObserver !== "undefine
1677
2295
  ];
1678
2296
  };
1679
2297
  // src/PCBViewer.tsx
1680
- var import_transformation_matrix3 = require("transformation-matrix");
1681
- var import_builder2 = require("@tscircuit/builder");
1682
- var defaultTransform = (0, import_transformation_matrix3.compose)((0, import_transformation_matrix3.translate)(400, 300), (0, import_transformation_matrix3.scale)(40, 40));
2298
+ var import_transformation_matrix5 = require("transformation-matrix");
2299
+ var import_builder4 = require("@tscircuit/builder");
2300
+ var defaultTransform = (0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(400, 300), (0, import_transformation_matrix5.scale)(40, -40));
1683
2301
  var PCBViewer = function(param) {
1684
2302
  var children = param.children, soup = param.soup, _param_height = param.height, height = _param_height === void 0 ? 600 : _param_height;
1685
- var _ref = _sliced_to_array((0, import_react9.useState)([]), 2), stateElements = _ref[0], setStateElements = _ref[1];
2303
+ var _ref = _sliced_to_array((0, import_react15.useState)([]), 2), stateElements = _ref[0], setStateElements = _ref[1];
1686
2304
  var _useMeasure_default = _sliced_to_array(useMeasure_default(), 2), ref = _useMeasure_default[0], refDimensions = _useMeasure_default[1];
1687
- var _ref1 = _sliced_to_array((0, import_react9.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
2305
+ var _ref1 = _sliced_to_array((0, import_react15.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
1688
2306
  var _ref2 = (0, import_use_mouse_matrix_transform.default)({
1689
2307
  transform: transform,
1690
2308
  onSetTransform: setTransformInternal
1691
2309
  }), transformRef = _ref2.ref, setTransform = _ref2.setTransform;
1692
- var _ref3 = _sliced_to_array((0, import_react9.useState)(null), 2), error = _ref3[0], setError = _ref3[1];
2310
+ var _ref3 = _sliced_to_array((0, import_react15.useState)(null), 2), error = _ref3[0], setError = _ref3[1];
1693
2311
  var resetTransform = function() {
1694
2312
  var elmBounds = (refDimensions === null || refDimensions === void 0 ? void 0 : refDimensions.width) > 0 ? refDimensions : {
1695
2313
  width: 500,
@@ -1697,7 +2315,7 @@ var PCBViewer = function(param) {
1697
2315
  };
1698
2316
  var _ref = elements.some(function(e) {
1699
2317
  return e.type.startsWith("pcb_");
1700
- }) ? (0, import_builder2.findBoundsAndCenter)(elements.filter(function(e) {
2318
+ }) ? (0, import_builder4.findBoundsAndCenter)(elements.filter(function(e) {
1701
2319
  return e.type.startsWith("pcb_");
1702
2320
  })) : {
1703
2321
  center: {
@@ -1710,10 +2328,10 @@ var PCBViewer = function(param) {
1710
2328
  var _elmBounds_width, _elmBounds_height;
1711
2329
  var scaleFactor = Math.min(((_elmBounds_width = elmBounds.width) !== null && _elmBounds_width !== void 0 ? _elmBounds_width : 0) / width, ((_elmBounds_height = elmBounds.height) !== null && _elmBounds_height !== void 0 ? _elmBounds_height : 0) / height2, 100);
1712
2330
  var _elmBounds_width1, _elmBounds_height1;
1713
- setTransform((0, import_transformation_matrix3.compose)((0, import_transformation_matrix3.translate)(((_elmBounds_width1 = elmBounds.width) !== null && _elmBounds_width1 !== void 0 ? _elmBounds_width1 : 0) / 2, ((_elmBounds_height1 = elmBounds.height) !== null && _elmBounds_height1 !== void 0 ? _elmBounds_height1 : 0) / 2), // translate(100, 0),
1714
- (0, import_transformation_matrix3.scale)(scaleFactor, scaleFactor, 0, 0), (0, import_transformation_matrix3.translate)(-center.x, -center.y)));
2331
+ setTransform((0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(((_elmBounds_width1 = elmBounds.width) !== null && _elmBounds_width1 !== void 0 ? _elmBounds_width1 : 0) / 2, ((_elmBounds_height1 = elmBounds.height) !== null && _elmBounds_height1 !== void 0 ? _elmBounds_height1 : 0) / 2), // translate(100, 0),
2332
+ (0, import_transformation_matrix5.scale)(scaleFactor, -scaleFactor, 0, 0), (0, import_transformation_matrix5.translate)(-center.x, -center.y)));
1715
2333
  };
1716
- (0, import_react9.useEffect)(function() {
2334
+ (0, import_react15.useEffect)(function() {
1717
2335
  var doRender = function doRender() {
1718
2336
  return _doRender.apply(this, arguments);
1719
2337
  };
@@ -1724,7 +2342,7 @@ var PCBViewer = function(param) {
1724
2342
  return _ts_generator(this, function(_state) {
1725
2343
  switch(_state.label){
1726
2344
  case 0:
1727
- projectBuilder = (0, import_builder.createProjectBuilder)();
2345
+ projectBuilder = (0, import_builder3.createProjectBuilder)();
1728
2346
  return [
1729
2347
  4,
1730
2348
  (0, import_react_fiber.createRoot)().render(children, projectBuilder).then(function(elements2) {
@@ -1749,26 +2367,25 @@ var PCBViewer = function(param) {
1749
2367
  }, [
1750
2368
  children
1751
2369
  ]);
1752
- (0, import_react9.useEffect)(function() {
1753
- if (refDimensions && refDimensions.width !== 0 && children) {
2370
+ (0, import_react15.useEffect)(function() {
2371
+ if (refDimensions && refDimensions.width !== 0 && (children || soup)) {
1754
2372
  resetTransform();
1755
2373
  }
1756
2374
  }, [
1757
2375
  children,
1758
2376
  refDimensions
1759
2377
  ]);
1760
- if (error) return /* @__PURE__ */ import_react9.default.createElement("div", {
2378
+ if (error) return /* @__PURE__ */ import_react15.default.createElement("div", {
1761
2379
  style: {
1762
2380
  color: "red"
1763
2381
  }
1764
2382
  }, " ", error, " ");
1765
2383
  var elements = soup !== null && soup !== void 0 ? soup : stateElements;
1766
- if (elements.length === 0) return null;
1767
- return /* @__PURE__ */ import_react9.default.createElement("div", {
2384
+ return /* @__PURE__ */ import_react15.default.createElement("div", {
1768
2385
  ref: transformRef
1769
- }, /* @__PURE__ */ import_react9.default.createElement("div", {
2386
+ }, /* @__PURE__ */ import_react15.default.createElement("div", {
1770
2387
  ref: ref
1771
- }, /* @__PURE__ */ import_react9.default.createElement(CanvasElementsRenderer, {
2388
+ }, /* @__PURE__ */ import_react15.default.createElement(ContextProviders, null, /* @__PURE__ */ import_react15.default.createElement(CanvasElementsRenderer, {
1772
2389
  key: refDimensions.width,
1773
2390
  transform: transform,
1774
2391
  height: height,
@@ -1785,7 +2402,7 @@ var PCBViewer = function(param) {
1785
2402
  elements: elements.filter(function(elm) {
1786
2403
  return elm.type.startsWith("pcb_") || elm.type.startsWith("source_");
1787
2404
  })
1788
- })));
2405
+ }))));
1789
2406
  };
1790
2407
  // Annotate the CommonJS export names for ESM import in node:
1791
2408
  0 && (module.exports = {