@tscircuit/pcb-viewer 1.2.26 → 1.3.0

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,15 @@ 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
+ }
278
336
  var __create = Object.create;
279
337
  var __defProp = Object.defineProperty;
280
338
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -400,20 +458,20 @@ var require_dist = __commonJS({
400
458
  }
401
459
  });
402
460
  module2.exports = __toCommonJS2(src_exports2);
403
- var import_transformation_matrix4 = require("transformation-matrix");
404
- var import_react10 = require("react");
461
+ var import_transformation_matrix5 = require("transformation-matrix");
462
+ var import_react15 = require("react");
405
463
  var useMouseMatrixTransform2 = function() {
406
464
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
407
- var extRef = (0, import_react10.useRef)(null);
465
+ var extRef = (0, import_react15.useRef)(null);
408
466
  var _props_canvasElm;
409
467
  var outerCanvasElm = (_props_canvasElm = props.canvasElm) !== null && _props_canvasElm !== void 0 ? _props_canvasElm : extRef.current;
410
468
  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) {
469
+ var _ref = _sliced_to_array((0, import_react15.useState)((_props_initialTransform = props.initialTransform) !== null && _props_initialTransform !== void 0 ? _props_initialTransform : (0, import_transformation_matrix5.identity)()), 2), internalTransform = _ref[0], setInternalTransform = _ref[1];
470
+ var _ref1 = _sliced_to_array((0, import_react15.useState)(0), 2), waitCounter = _ref1[0], setWaitCounter = _ref1[1];
471
+ var _ref2 = _sliced_to_array((0, import_react15.useReducer)(function(s) {
414
472
  return s + 1;
415
473
  }, 0), 2), extChangeCounter = _ref2[0], incExtChangeCounter = _ref2[1];
416
- var setTransform = (0, import_react10.useCallback)(function(newTransform) {
474
+ var setTransform = (0, import_react15.useCallback)(function(newTransform) {
417
475
  if (props.onSetTransform) {
418
476
  props.onSetTransform(newTransform);
419
477
  }
@@ -424,7 +482,7 @@ var require_dist = __commonJS({
424
482
  props.onSetTransform,
425
483
  setInternalTransform
426
484
  ]);
427
- var setTransformExt = (0, import_react10.useCallback)(function(newTransform) {
485
+ var setTransformExt = (0, import_react15.useCallback)(function(newTransform) {
428
486
  setTransform(newTransform);
429
487
  incExtChangeCounter();
430
488
  }, [
@@ -432,7 +490,7 @@ var require_dist = __commonJS({
432
490
  ]);
433
491
  var _props_transform;
434
492
  var transform = (_props_transform = props.transform) !== null && _props_transform !== void 0 ? _props_transform : internalTransform;
435
- (0, import_react10.useEffect)(function() {
493
+ (0, import_react15.useEffect)(function() {
436
494
  var handleMouseDown = function handleMouseDown(e) {
437
495
  m0 = getMousePos(e);
438
496
  md = true;
@@ -440,7 +498,7 @@ var require_dist = __commonJS({
440
498
  };
441
499
  var handleMouseUp = function handleMouseUp(e) {
442
500
  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);
501
+ var new_tf = (0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
444
502
  setTransform(new_tf);
445
503
  init_tf = new_tf;
446
504
  md = false;
@@ -449,11 +507,11 @@ var require_dist = __commonJS({
449
507
  mlastrel = getMousePos(e);
450
508
  if (!md) return;
451
509
  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));
510
+ setTransform((0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(m1.x - m0.x, m1.y - m0.y), init_tf));
453
511
  };
454
512
  var handleMouseWheel = function handleMouseWheel(e) {
455
513
  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);
514
+ var new_tf = (0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(center.x, center.y), (0, import_transformation_matrix5.scale)(1 - e.deltaY / 1e3, 1 - e.deltaY / 1e3), (0, import_transformation_matrix5.translate)(-center.x, -center.y), init_tf);
457
515
  setTransform(new_tf);
458
516
  init_tf = new_tf;
459
517
  e.preventDefault();
@@ -462,7 +520,7 @@ var require_dist = __commonJS({
462
520
  if (!md) return;
463
521
  md = false;
464
522
  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);
523
+ var new_tf = (0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
466
524
  setTransform(new_tf);
467
525
  init_tf = new_tf;
468
526
  };
@@ -515,8 +573,8 @@ var require_dist = __commonJS({
515
573
  waitCounter,
516
574
  extChangeCounter
517
575
  ]);
518
- var applyTransformToPoint = (0, import_react10.useCallback)(function(obj) {
519
- return (0, import_transformation_matrix4.applyToPoint)(transform, obj);
576
+ var applyTransformToPoint = (0, import_react15.useCallback)(function(obj) {
577
+ return (0, import_transformation_matrix5.applyToPoint)(transform, obj);
520
578
  }, [
521
579
  transform
522
580
  ]);
@@ -542,14 +600,14 @@ __export(src_exports, {
542
600
  });
543
601
  module.exports = __toCommonJS(src_exports);
544
602
  // src/PCBViewer.tsx
545
- var import_react9 = __toESM(require("react"));
603
+ var import_react14 = __toESM(require("react"));
546
604
  var import_react_fiber = require("@tscircuit/react-fiber");
547
- var import_builder = require("@tscircuit/builder");
605
+ var import_builder3 = require("@tscircuit/builder");
548
606
  // src/components/CanvasElementsRenderer.tsx
549
- var import_react5 = __toESM(require("react"));
607
+ var import_react10 = __toESM(require("react"));
550
608
  // src/components/CanvasPrimitiveRenderer.tsx
551
609
  var import_react_supergrid = require("react-supergrid");
552
- var import_react = __toESM(require("react"));
610
+ var import_react4 = __toESM(require("react"));
553
611
  // src/assets/alphabet.ts
554
612
  var svgAlphabet = {
555
613
  "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 +1019,7 @@ var LAYER_NAME_TO_COLOR = _object_spread({
961
1019
  black: "black",
962
1020
  green: "green",
963
1021
  board: "white",
1022
+ other: "#eee",
964
1023
  // TODO more builtin html colors
965
1024
  // Common eagle names
966
1025
  top: colors_default.board.copper.f,
@@ -978,13 +1037,29 @@ var LAYER_NAME_TO_COLOR = _object_spread({
978
1037
  tkeepout: colors_default.board.b_crtyd,
979
1038
  tplace: colors_default.board.b_silks
980
1039
  }, colors_default.board);
1040
+ var DEFAULT_DRAW_ORDER = [
1041
+ "top",
1042
+ "inner1",
1043
+ "inner2",
1044
+ "inner3",
1045
+ "inner4",
1046
+ "inner5",
1047
+ "inner6",
1048
+ "bottom"
1049
+ ];
981
1050
  var Drawer = /*#__PURE__*/ function() {
982
1051
  "use strict";
983
- function Drawer(canvas) {
1052
+ function Drawer(canvasLayerMap) {
984
1053
  _class_call_check(this, Drawer);
985
- this.canvas = canvas;
986
- this.canvas = canvas;
987
- this.ctx = canvas.getContext("2d");
1054
+ this.foregroundLayer = "top";
1055
+ this.canvasLayerMap = canvasLayerMap;
1056
+ this.ctxLayerMap = Object.fromEntries(Object.entries(canvasLayerMap).map(function(param) {
1057
+ var _param = _sliced_to_array(param, 2), name = _param[0], canvas = _param[1];
1058
+ return [
1059
+ name,
1060
+ canvas.getContext("2d")
1061
+ ];
1062
+ }));
988
1063
  this.transform = (0, import_transformation_matrix.identity)();
989
1064
  this.transform.d *= -1;
990
1065
  this.transform = (0, import_transformation_matrix.compose)(this.transform, (0, import_transformation_matrix.translate)(0, -500));
@@ -998,20 +1073,40 @@ var Drawer = /*#__PURE__*/ function() {
998
1073
  {
999
1074
  key: "clear",
1000
1075
  value: function clear() {
1001
- var _this = this, ctx = _this.ctx, canvas = _this.canvas;
1002
- ctx.clearRect(0, 0, canvas.width, canvas.height);
1076
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1077
+ try {
1078
+ for(var _iterator = Object.values(this.ctxLayerMap)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1079
+ var ctx = _step.value;
1080
+ ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
1081
+ }
1082
+ } catch (err) {
1083
+ _didIteratorError = true;
1084
+ _iteratorError = err;
1085
+ } finally{
1086
+ try {
1087
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1088
+ _iterator.return();
1089
+ }
1090
+ } finally{
1091
+ if (_didIteratorError) {
1092
+ throw _iteratorError;
1093
+ }
1094
+ }
1095
+ }
1003
1096
  }
1004
1097
  },
1005
1098
  {
1006
1099
  key: "equip",
1007
- value: function equip(aperature) {
1100
+ value: function equip(aperture) {
1008
1101
  this.aperture = _object_spread({
1009
1102
  fontSize: 0,
1010
1103
  shape: "circle",
1011
1104
  mode: "add",
1012
1105
  size: 0,
1013
- color: "red"
1014
- }, aperature);
1106
+ color: "red",
1107
+ layer: "top",
1108
+ opacity: this.foregroundLayer === aperture.color ? 1 : 0.5
1109
+ }, aperture);
1015
1110
  }
1016
1111
  },
1017
1112
  {
@@ -1026,7 +1121,8 @@ var Drawer = /*#__PURE__*/ function() {
1026
1121
  y + h / 2
1027
1122
  ]), 2), x2$ = _ref1[0], y2$ = _ref1[1];
1028
1123
  this.applyAperture();
1029
- this.ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$);
1124
+ var ctx = this.getLayerCtx();
1125
+ ctx.fillRect(x1$, y1$, x2$ - x1$, y2$ - y1$);
1030
1126
  }
1031
1127
  },
1032
1128
  {
@@ -1038,10 +1134,11 @@ var Drawer = /*#__PURE__*/ function() {
1038
1134
  y
1039
1135
  ]), 2), x$ = _ref[0], y$ = _ref[1];
1040
1136
  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();
1137
+ var ctx = this.getLayerCtx();
1138
+ ctx.beginPath();
1139
+ ctx.arc(x$, y$, r$, 0, 2 * Math.PI);
1140
+ ctx.fill();
1141
+ ctx.closePath();
1045
1142
  }
1046
1143
  },
1047
1144
  {
@@ -1052,15 +1149,65 @@ var Drawer = /*#__PURE__*/ function() {
1052
1149
  y
1053
1150
  ]), 2), x$ = _ref[0], y$ = _ref[1];
1054
1151
  this.applyAperture();
1055
- this.ctx.font = "10px sans-serif";
1056
- this.ctx.fillText(text, x$, y$);
1152
+ var ctx = this.getLayerCtx();
1153
+ ctx.font = "10px sans-serif";
1154
+ ctx.fillText(text, x$, y$);
1155
+ }
1156
+ },
1157
+ {
1158
+ key: "getLayerCtx",
1159
+ value: function getLayerCtx() {
1160
+ var ctx = this.ctxLayerMap[this.aperture.layer];
1161
+ if (!ctx) {
1162
+ throw new Error('No context for layer "'.concat(this.aperture.layer, '"'));
1163
+ }
1164
+ return ctx;
1165
+ }
1166
+ },
1167
+ {
1168
+ /**
1169
+ * Iterate over each canvas and set the z index based on the layer order, but
1170
+ * always render the foreground layer on top.
1171
+ *
1172
+ * Also: Set the opacity of every non-foreground layer to 0.5
1173
+ */ key: "orderAndFadeLayers",
1174
+ value: function orderAndFadeLayers() {
1175
+ var _this = this, canvasLayerMap = _this.canvasLayerMap, foregroundLayer = _this.foregroundLayer;
1176
+ var opaqueLayers = /* @__PURE__ */ new Set([
1177
+ foregroundLayer,
1178
+ "drill",
1179
+ "other",
1180
+ "board"
1181
+ ]);
1182
+ var order = [
1183
+ "drill",
1184
+ "board",
1185
+ foregroundLayer
1186
+ ].concat(_to_consumable_array(DEFAULT_DRAW_ORDER.filter(function(l) {
1187
+ return l !== foregroundLayer;
1188
+ })));
1189
+ order.forEach(function(layer, i) {
1190
+ var canvas = canvasLayerMap[layer];
1191
+ if (!canvas) return;
1192
+ canvas.style.zIndex = "".concat(100 - i);
1193
+ canvas.style.opacity = opaqueLayers.has(layer) ? "1" : "0.5";
1194
+ });
1057
1195
  }
1058
1196
  },
1059
1197
  {
1060
1198
  key: "applyAperture",
1061
1199
  value: function applyAperture() {
1062
- var _this = this, ctx = _this.ctx, transform = _this.transform, aperture = _this.aperture;
1200
+ var _this = this, transform = _this.transform, aperture = _this.aperture;
1063
1201
  var size = aperture.size, mode = aperture.mode, color = aperture.color, fontSize = aperture.fontSize;
1202
+ if (color in this.ctxLayerMap) {
1203
+ this.aperture.layer = color;
1204
+ } else {
1205
+ this.aperture.layer = "other";
1206
+ }
1207
+ var ctx = this.getLayerCtx();
1208
+ if (!ctx) {
1209
+ throw new Error('No context for layer "'.concat(this.foregroundLayer, '"'));
1210
+ }
1064
1211
  if (!color) color = "undefined";
1065
1212
  ctx.lineWidth = scaleOnly(transform, size);
1066
1213
  ctx.lineCap = "round";
@@ -1098,9 +1245,10 @@ var Drawer = /*#__PURE__*/ function() {
1098
1245
  ]), 2), x$ = _ref[0], y$ = _ref[1];
1099
1246
  var _this_aperture = this.aperture, size = _this_aperture.size, shape = _this_aperture.shape, mode = _this_aperture.mode;
1100
1247
  var size$ = scaleOnly(this.transform, size);
1101
- var _this = this, lastPoint = _this.lastPoint, ctx = _this.ctx;
1248
+ var lastPoint = this.lastPoint;
1102
1249
  var lastPoint$ = (0, import_transformation_matrix.applyToPoint)(this.transform, lastPoint);
1103
1250
  this.applyAperture();
1251
+ var ctx = this.getLayerCtx();
1104
1252
  if (shape === "square") ctx.fillRect(lastPoint$.x - size$ / 2, lastPoint$.y - size$ / 2, size$, size$);
1105
1253
  ctx.beginPath();
1106
1254
  ctx.moveTo(lastPoint$.x, lastPoint$.y);
@@ -1117,28 +1265,69 @@ var Drawer = /*#__PURE__*/ function() {
1117
1265
  ]);
1118
1266
  return Drawer;
1119
1267
  }();
1268
+ // src/global-store.ts
1269
+ var import_zustand = require("zustand");
1270
+ // src/components/ContextProviders.tsx
1271
+ var import_react = require("react");
1272
+ var import_react2 = require("react");
1273
+ var StoreContext = (0, import_react2.createContext)(null);
1274
+ var ContextProviders = function(param) {
1275
+ var children = param.children;
1276
+ var store = (0, import_react.useMemo)(function() {
1277
+ return createStore();
1278
+ }, []);
1279
+ return /* @__PURE__ */ React.createElement(StoreContext.Provider, {
1280
+ value: store
1281
+ }, children);
1282
+ };
1283
+ // src/global-store.ts
1284
+ var import_react3 = require("react");
1285
+ var createStore = function() {
1286
+ return (0, import_zustand.createStore)(function(set) {
1287
+ return {
1288
+ selected_layer: "top",
1289
+ selectLayer: function(layer) {
1290
+ return set({
1291
+ selected_layer: layer
1292
+ });
1293
+ }
1294
+ };
1295
+ });
1296
+ };
1297
+ var useStore = function(s) {
1298
+ var store = (0, import_react3.useContext)(StoreContext);
1299
+ return (0, import_zustand.useStore)(store, s);
1300
+ };
1120
1301
  // src/components/CanvasPrimitiveRenderer.tsx
1302
+ var import_builder = require("@tscircuit/builder");
1121
1303
  var CanvasPrimitiveRenderer = function(param) {
1122
1304
  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);
1305
+ var canvasRefs = (0, import_react4.useRef)();
1306
+ var selectedLayer = useStore(function(s) {
1307
+ return s.selected_layer;
1308
+ });
1309
+ (0, import_react4.useEffect)(function() {
1310
+ if (!canvasRefs.current) return;
1311
+ if (Object.keys(canvasRefs.current).length === 0) return;
1312
+ var drawer = new Drawer(canvasRefs.current);
1127
1313
  if (transform) drawer.transform = transform;
1128
1314
  drawer.clear();
1315
+ drawer.foregroundLayer = selectedLayer;
1129
1316
  drawPrimitives(drawer, primitives);
1317
+ drawer.orderAndFadeLayers();
1130
1318
  }, [
1131
1319
  primitives,
1132
- transform
1320
+ transform,
1321
+ selectedLayer
1133
1322
  ]);
1134
- return /* @__PURE__ */ import_react.default.createElement("div", {
1323
+ return /* @__PURE__ */ import_react4.default.createElement("div", {
1135
1324
  style: {
1136
1325
  backgroundColor: "black",
1137
1326
  width: width,
1138
1327
  height: height,
1139
1328
  position: "relative"
1140
1329
  }
1141
- }, /* @__PURE__ */ import_react.default.createElement(import_react_supergrid.SuperGrid, {
1330
+ }, /* @__PURE__ */ import_react4.default.createElement(import_react_supergrid.SuperGrid, {
1142
1331
  textColor: "rgba(0,255,0,0.8)",
1143
1332
  majorColor: "rgba(0,255,0,0.4)",
1144
1333
  minorColor: "rgba(0,255,0,0.2)",
@@ -1149,20 +1338,32 @@ var CanvasPrimitiveRenderer = function(param) {
1149
1338
  stringifyCoord: function(x, y, z) {
1150
1339
  return "".concat((0, import_react_supergrid.toMMSI)(x, z), ", ").concat((0, import_react_supergrid.toMMSI)(y, z));
1151
1340
  }
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
1341
+ }), import_builder.all_layers.map(function(l) {
1342
+ return l.replace(/-/g, "");
1343
+ }).concat([
1344
+ "drill",
1345
+ "other"
1346
+ ]).map(function(layer, i) {
1347
+ return /* @__PURE__ */ import_react4.default.createElement("canvas", {
1348
+ key: layer,
1349
+ ref: function(el) {
1350
+ var _canvasRefs_current;
1351
+ (_canvasRefs_current = canvasRefs.current) !== null && _canvasRefs_current !== void 0 ? _canvasRefs_current : canvasRefs.current = {};
1352
+ canvasRefs.current[layer] = el;
1353
+ },
1354
+ style: {
1355
+ position: "absolute",
1356
+ left: 0,
1357
+ top: 0,
1358
+ pointerEvents: "none"
1359
+ },
1360
+ width: width,
1361
+ height: height
1362
+ });
1162
1363
  }));
1163
1364
  };
1164
1365
  // src/components/CanvasElementsRenderer.tsx
1165
- var import_react6 = require("react");
1366
+ var import_react11 = require("react");
1166
1367
  // src/lib/convert-element-to-primitive.ts
1167
1368
  var convertElementToPrimitives = function(element, allElements) {
1168
1369
  var _parent_pcb_component = "pcb_component_id" in element ? allElements.find(function(elm) {
@@ -1388,11 +1589,11 @@ var convertElementToPrimitives = function(element, allElements) {
1388
1589
  return [];
1389
1590
  };
1390
1591
  // src/components/MouseElementTracker.tsx
1391
- var import_react3 = __toESM(require("react"));
1392
- var import_react4 = require("react");
1592
+ var import_react6 = __toESM(require("react"));
1593
+ var import_react7 = require("react");
1393
1594
  var import_transformation_matrix2 = require("transformation-matrix");
1394
1595
  // src/components/ElementOverlayBox.tsx
1395
- var import_react2 = __toESM(require("react"));
1596
+ var import_react5 = __toESM(require("react"));
1396
1597
  var containerStyle = {
1397
1598
  position: "absolute",
1398
1599
  left: 0,
@@ -1433,8 +1634,8 @@ var layerColorHightlightMap = {
1433
1634
  var HighlightedPrimitiveBoxWithText = function(param) {
1434
1635
  var primitive = param.primitive;
1435
1636
  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() {
1637
+ var _ref = _sliced_to_array((0, import_react5.useState)(false), 2), finalState = _ref[0], setFinalState = _ref[1];
1638
+ (0, import_react5.useEffect)(function() {
1438
1639
  setTimeout(function() {
1439
1640
  setFinalState(true);
1440
1641
  }, 100);
@@ -1450,7 +1651,7 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1450
1651
  var sip = 26;
1451
1652
  var _layerColorHightlightMap_primitive__element_layer;
1452
1653
  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", {
1654
+ return /* @__PURE__ */ import_react5.default.createElement("div", {
1454
1655
  style: {
1455
1656
  position: "absolute",
1456
1657
  left: x - w / 2 - 8,
@@ -1459,7 +1660,7 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1459
1660
  height: h + 16,
1460
1661
  color: color
1461
1662
  }
1462
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
1663
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
1463
1664
  style: {
1464
1665
  // width: finalState ? `${100 + 20 * si}%` : "100%",
1465
1666
  // height: finalState ? `${100 + 20 * si}%` : "100%",
@@ -1473,7 +1674,7 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1473
1674
  opacity: finalState ? 1 : si === 0 ? 1 : 0,
1474
1675
  transition: "width 0.2s, height 0.2s, margin-left 0.2s, margin-top 0.2s, opacity 0.2s"
1475
1676
  }
1476
- }, /* @__PURE__ */ import_react2.default.createElement("div", {
1677
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
1477
1678
  style: {
1478
1679
  position: "absolute",
1479
1680
  left: 0,
@@ -1487,10 +1688,10 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1487
1688
  };
1488
1689
  var ElementOverlayBox = function(param) {
1489
1690
  var highlightedPrimitives = param.highlightedPrimitives;
1490
- return /* @__PURE__ */ import_react2.default.createElement("div", {
1691
+ return /* @__PURE__ */ import_react5.default.createElement("div", {
1491
1692
  style: containerStyle
1492
1693
  }, highlightedPrimitives.map(function(primitive, i) {
1493
- return /* @__PURE__ */ import_react2.default.createElement(HighlightedPrimitiveBoxWithText, {
1694
+ return /* @__PURE__ */ import_react5.default.createElement(HighlightedPrimitiveBoxWithText, {
1494
1695
  key: i,
1495
1696
  primitive: primitive
1496
1697
  });
@@ -1499,8 +1700,8 @@ var ElementOverlayBox = function(param) {
1499
1700
  // src/components/MouseElementTracker.tsx
1500
1701
  var MouseElementTracker = function(param) {
1501
1702
  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() {
1703
+ var _ref = _sliced_to_array((0, import_react6.useState)([]), 2), mousedPrimitives = _ref[0], setMousedPrimitives = _ref[1];
1704
+ var highlightedPrimitives = (0, import_react7.useMemo)(function() {
1504
1705
  var highlightedPrimitives2 = [];
1505
1706
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1506
1707
  try {
@@ -1513,8 +1714,8 @@ var MouseElementTracker = function(param) {
1513
1714
  var w = "w" in primitive ? primitive.w : "r" in primitive ? primitive.r * 2 : 0;
1514
1715
  var h = "h" in primitive ? primitive.h : "r" in primitive ? primitive.r * 2 : 0;
1515
1716
  var screenSize = {
1516
- w: w * transform.d,
1517
- h: h * transform.d
1717
+ w: w * transform.a,
1718
+ h: h * transform.a
1518
1719
  };
1519
1720
  var same_space_index = highlightedPrimitives2.filter(function(hp) {
1520
1721
  return screenPos.x === hp.screen_x && screenPos.y === hp.screen_y && screenSize.w === hp.screen_w && screenSize.h === hp.screen_h;
@@ -1547,7 +1748,7 @@ var MouseElementTracker = function(param) {
1547
1748
  mousedPrimitives,
1548
1749
  transform
1549
1750
  ]);
1550
- return /* @__PURE__ */ import_react3.default.createElement("div", {
1751
+ return /* @__PURE__ */ import_react6.default.createElement("div", {
1551
1752
  style: {
1552
1753
  position: "relative"
1553
1754
  },
@@ -1590,13 +1791,317 @@ var MouseElementTracker = function(param) {
1590
1791
  setMousedPrimitives(mousedPrimitives2);
1591
1792
  }
1592
1793
  }
1593
- }, children, /* @__PURE__ */ import_react3.default.createElement(ElementOverlayBox, {
1794
+ }, children, /* @__PURE__ */ import_react6.default.createElement(ElementOverlayBox, {
1594
1795
  highlightedPrimitives: highlightedPrimitives
1595
1796
  }));
1596
1797
  };
1798
+ // src/components/DimensionOverlay.tsx
1799
+ var import_react8 = require("react");
1800
+ var import_transformation_matrix3 = require("transformation-matrix");
1801
+ var DimensionOverlay = function(param) {
1802
+ var children = param.children, transform = param.transform;
1803
+ if (!transform) transform = (0, import_transformation_matrix3.identity)();
1804
+ var _ref = _sliced_to_array((0, import_react8.useState)(false), 2), dimensionToolVisible = _ref[0], setDimensionToolVisible = _ref[1];
1805
+ var _ref1 = _sliced_to_array((0, import_react8.useState)(false), 2), dimensionToolStretching = _ref1[0], setDimensionToolStretching = _ref1[1];
1806
+ var _ref2 = _sliced_to_array((0, import_react8.useState)({
1807
+ x: 0,
1808
+ y: 0
1809
+ }), 2), dStart = _ref2[0], setDStart = _ref2[1];
1810
+ var _ref3 = _sliced_to_array((0, import_react8.useState)({
1811
+ x: 0,
1812
+ y: 0
1813
+ }), 2), dEnd = _ref3[0], setDEnd = _ref3[1];
1814
+ var mousePosRef = (0, import_react8.useRef)({
1815
+ x: 0,
1816
+ y: 0
1817
+ });
1818
+ var containerRef = (0, import_react8.useRef)(null);
1819
+ var container = containerRef.current;
1820
+ var containerBounds = container === null || container === void 0 ? void 0 : container.getBoundingClientRect();
1821
+ (0, import_react8.useEffect)(function() {
1822
+ var down = function(e) {
1823
+ if (e.key === "d") {
1824
+ setDStart({
1825
+ x: mousePosRef.current.x,
1826
+ y: mousePosRef.current.y
1827
+ });
1828
+ setDEnd({
1829
+ x: mousePosRef.current.x,
1830
+ y: mousePosRef.current.y
1831
+ });
1832
+ setDimensionToolVisible(function(visible) {
1833
+ return !visible;
1834
+ });
1835
+ setDimensionToolStretching(true);
1836
+ e.preventDefault();
1837
+ }
1838
+ if (e.key === "Escape") {
1839
+ setDimensionToolVisible(false);
1840
+ setDimensionToolStretching(false);
1841
+ }
1842
+ };
1843
+ window.addEventListener("keydown", down);
1844
+ return function() {
1845
+ return window.removeEventListener("keydown", down);
1846
+ };
1847
+ }, [
1848
+ containerRef
1849
+ ]);
1850
+ var screenDStart = (0, import_transformation_matrix3.applyToPoint)(transform, dStart);
1851
+ var screenDEnd = (0, import_transformation_matrix3.applyToPoint)(transform, dEnd);
1852
+ var arrowScreenBounds = {
1853
+ left: Math.min(screenDStart.x, screenDEnd.x),
1854
+ right: Math.max(screenDStart.x, screenDEnd.x),
1855
+ top: Math.min(screenDStart.y, screenDEnd.y),
1856
+ bottom: Math.max(screenDStart.y, screenDEnd.y),
1857
+ flipX: screenDStart.x > screenDEnd.x,
1858
+ flipY: screenDStart.y > screenDEnd.y,
1859
+ width: 0,
1860
+ height: 0
1861
+ };
1862
+ arrowScreenBounds.width = arrowScreenBounds.right - arrowScreenBounds.left;
1863
+ arrowScreenBounds.height = arrowScreenBounds.bottom - arrowScreenBounds.top;
1864
+ return /* @__PURE__ */ React.createElement("div", {
1865
+ ref: containerRef,
1866
+ style: {
1867
+ position: "relative"
1868
+ },
1869
+ onMouseMove: function(e) {
1870
+ var rect = e.currentTarget.getBoundingClientRect();
1871
+ var x = e.clientX - rect.left;
1872
+ var y = e.clientY - rect.top;
1873
+ var rwPoint = (0, import_transformation_matrix3.applyToPoint)((0, import_transformation_matrix3.inverse)(transform), {
1874
+ x: x,
1875
+ y: y
1876
+ });
1877
+ mousePosRef.current.x = rwPoint.x;
1878
+ mousePosRef.current.y = rwPoint.y;
1879
+ if (dimensionToolStretching) {
1880
+ setDEnd({
1881
+ x: rwPoint.x,
1882
+ y: rwPoint.y
1883
+ });
1884
+ }
1885
+ },
1886
+ onMouseDown: function() {
1887
+ if (dimensionToolStretching) {
1888
+ setDimensionToolStretching(false);
1889
+ } else if (dimensionToolVisible) {
1890
+ setDimensionToolVisible(false);
1891
+ }
1892
+ }
1893
+ }, children, dimensionToolVisible && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
1894
+ style: {
1895
+ position: "absolute",
1896
+ left: arrowScreenBounds.left,
1897
+ width: arrowScreenBounds.width,
1898
+ textAlign: "center",
1899
+ top: screenDStart.y + 2,
1900
+ color: "red",
1901
+ mixBlendMode: "difference",
1902
+ pointerEvents: "none",
1903
+ marginTop: arrowScreenBounds.flipY ? 0 : -20,
1904
+ fontSize: 12,
1905
+ fontFamily: "sans-serif",
1906
+ zIndex: 1e3
1907
+ }
1908
+ }, Math.abs(dStart.x - dEnd.x).toFixed(2)), /* @__PURE__ */ React.createElement("div", {
1909
+ style: {
1910
+ position: "absolute",
1911
+ left: screenDEnd.x,
1912
+ height: arrowScreenBounds.height,
1913
+ display: "flex",
1914
+ flexDirection: "column",
1915
+ justifyContent: "center",
1916
+ top: arrowScreenBounds.top,
1917
+ color: "red",
1918
+ pointerEvents: "none",
1919
+ mixBlendMode: "difference",
1920
+ fontSize: 12,
1921
+ fontFamily: "sans-serif",
1922
+ zIndex: 1e3
1923
+ }
1924
+ }, /* @__PURE__ */ React.createElement("div", {
1925
+ style: {
1926
+ marginLeft: arrowScreenBounds.flipX ? "-100%" : 4,
1927
+ paddingRight: 4
1928
+ }
1929
+ }, Math.abs(dStart.y - dEnd.y).toFixed(2))), /* @__PURE__ */ React.createElement("svg", {
1930
+ style: {
1931
+ position: "absolute",
1932
+ left: 0,
1933
+ top: 0,
1934
+ pointerEvents: "none",
1935
+ mixBlendMode: "difference",
1936
+ zIndex: 1e3
1937
+ },
1938
+ width: containerBounds.width,
1939
+ height: containerBounds.height
1940
+ }, /* @__PURE__ */ React.createElement("defs", null, /* @__PURE__ */ React.createElement("marker", {
1941
+ id: "head",
1942
+ orient: "auto",
1943
+ markerWidth: "3",
1944
+ markerHeight: "4",
1945
+ refX: "2",
1946
+ refY: "2"
1947
+ }, /* @__PURE__ */ React.createElement("path", {
1948
+ d: "M0,0 V4 L2,2 Z",
1949
+ fill: "red"
1950
+ }))), /* @__PURE__ */ React.createElement("line", {
1951
+ x1: screenDStart.x,
1952
+ y1: screenDStart.y,
1953
+ x2: screenDEnd.x,
1954
+ y2: screenDEnd.y,
1955
+ markerEnd: "url(#head)",
1956
+ strokeWidth: 1.5,
1957
+ fill: "none",
1958
+ stroke: "red"
1959
+ }), /* @__PURE__ */ React.createElement("line", {
1960
+ x1: screenDStart.x,
1961
+ y1: screenDStart.y,
1962
+ x2: screenDEnd.x,
1963
+ y2: screenDStart.y,
1964
+ strokeWidth: 1.5,
1965
+ fill: "none",
1966
+ strokeDasharray: "2,2",
1967
+ stroke: "red"
1968
+ }), /* @__PURE__ */ React.createElement("line", {
1969
+ x1: screenDEnd.x,
1970
+ y1: screenDStart.y,
1971
+ x2: screenDEnd.x,
1972
+ y2: screenDEnd.y,
1973
+ strokeWidth: 1.5,
1974
+ fill: "none",
1975
+ strokeDasharray: "2,2",
1976
+ stroke: "red"
1977
+ })), /* @__PURE__ */ React.createElement("div", {
1978
+ style: {
1979
+ right: 0,
1980
+ bottom: 0,
1981
+ position: "absolute",
1982
+ color: "red",
1983
+ fontFamily: "sans-serif",
1984
+ fontSize: 12,
1985
+ margin: 4
1986
+ }
1987
+ }, "(", 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))));
1988
+ };
1989
+ // src/components/ToolbarOverlay.tsx
1990
+ var import_react9 = require("react");
1991
+ var import_css = require("@emotion/css");
1992
+ var import_builder2 = require("@tscircuit/builder");
1993
+ var LayerButton = function(param) {
1994
+ var name = param.name, selected = param.selected, onClick = param.onClick;
1995
+ return /* @__PURE__ */ React.createElement("div", {
1996
+ className: import_css.css(_templateObject()),
1997
+ onClick: onClick
1998
+ }, /* @__PURE__ */ React.createElement("span", {
1999
+ style: {
2000
+ marginRight: 2,
2001
+ opacity: selected ? 1 : 0
2002
+ }
2003
+ }, "•"), /* @__PURE__ */ React.createElement("span", {
2004
+ style: {
2005
+ marginLeft: 2,
2006
+ fontWeight: 500,
2007
+ color: LAYER_NAME_TO_COLOR[name.replace(/-/, "")]
2008
+ }
2009
+ }, name));
2010
+ };
2011
+ var ToolbarButton = function(_param) {
2012
+ var children = _param.children, props = _object_without_properties(_param, [
2013
+ "children"
2014
+ ]);
2015
+ return /* @__PURE__ */ React.createElement("div", _object_spread_props(_object_spread({}, props), {
2016
+ style: {
2017
+ backgroundColor: "#1F1F1F",
2018
+ border: "1px solid #666",
2019
+ margin: 4,
2020
+ padding: 4,
2021
+ paddingLeft: 6,
2022
+ paddingRight: 6,
2023
+ borderRadius: 2,
2024
+ alignSelf: "start",
2025
+ color: "#eee",
2026
+ cursor: "pointer"
2027
+ }
2028
+ }), children);
2029
+ };
2030
+ var ToolbarOverlay = function(param) {
2031
+ var children = param.children, elements = param.elements;
2032
+ var _ref = _sliced_to_array((0, import_react9.useState)(false), 2), isMouseOverContainer = _ref[0], setIsMouseOverContainer = _ref[1];
2033
+ var _ref1 = _sliced_to_array((0, import_react9.useState)(false), 2), isLayerMenuOpen = _ref1[0], setLayerMenuOpen = _ref1[1];
2034
+ var _useStore = _sliced_to_array(useStore(function(s) {
2035
+ return [
2036
+ s.selected_layer,
2037
+ s.selectLayer
2038
+ ];
2039
+ }), 2), selectedLayer = _useStore[0], selectLayer = _useStore[1];
2040
+ var _elements_filter_length;
2041
+ var errorCount = (_elements_filter_length = elements === null || elements === void 0 ? void 0 : elements.filter(function(e) {
2042
+ return e.type.includes("error");
2043
+ }).length) !== null && _elements_filter_length !== void 0 ? _elements_filter_length : 0;
2044
+ return /* @__PURE__ */ React.createElement("div", {
2045
+ style: {
2046
+ position: "relative"
2047
+ },
2048
+ onMouseEnter: function() {
2049
+ setIsMouseOverContainer(true);
2050
+ },
2051
+ onMouseLeave: function() {
2052
+ setIsMouseOverContainer(false);
2053
+ setLayerMenuOpen(false);
2054
+ }
2055
+ }, children, /* @__PURE__ */ React.createElement("div", {
2056
+ style: {
2057
+ position: "absolute",
2058
+ opacity: isMouseOverContainer ? 1 : 0,
2059
+ top: 16,
2060
+ left: 16,
2061
+ transition: isMouseOverContainer ? "opacity 100ms linear" : "opacity 1s linear",
2062
+ zIndex: 100,
2063
+ color: "red",
2064
+ display: "flex",
2065
+ fontSize: 12,
2066
+ height: 100,
2067
+ fontFamily: "sans-serif"
2068
+ }
2069
+ }, /* @__PURE__ */ React.createElement(ToolbarButton, {
2070
+ onClick: function() {
2071
+ setLayerMenuOpen(!isLayerMenuOpen);
2072
+ },
2073
+ onMouseLeave: function() {
2074
+ if (isLayerMenuOpen) {
2075
+ setLayerMenuOpen(false);
2076
+ }
2077
+ }
2078
+ }, /* @__PURE__ */ React.createElement("div", null, "layer:", " ", /* @__PURE__ */ React.createElement("span", {
2079
+ style: {
2080
+ marginLeft: 2,
2081
+ fontWeight: 500,
2082
+ color: LAYER_NAME_TO_COLOR[selectedLayer]
2083
+ }
2084
+ }, selectedLayer)), isLayerMenuOpen && /* @__PURE__ */ React.createElement("div", {
2085
+ style: {
2086
+ marginTop: 4,
2087
+ minWidth: 120
2088
+ }
2089
+ }, import_builder2.all_layers.map(function(l) {
2090
+ return l.replace(/-/g, "");
2091
+ }).map(function(layer) {
2092
+ return /* @__PURE__ */ React.createElement(LayerButton, {
2093
+ key: layer,
2094
+ name: layer,
2095
+ selected: layer === selectedLayer,
2096
+ onClick: function() {
2097
+ selectLayer(layer.replace(/-/, ""));
2098
+ }
2099
+ });
2100
+ }))), /* @__PURE__ */ React.createElement(ToolbarButton, null, errorCount, " errors")));
2101
+ };
1597
2102
  // src/components/CanvasElementsRenderer.tsx
1598
2103
  var CanvasElementsRenderer = function(props) {
1599
- var primitives = (0, import_react6.useMemo)(function() {
2104
+ var primitives = (0, import_react11.useMemo)(function() {
1600
2105
  var primitives2 = props.elements.flatMap(function(elm) {
1601
2106
  return convertElementToPrimitives(elm, props.elements);
1602
2107
  });
@@ -1604,16 +2109,20 @@ var CanvasElementsRenderer = function(props) {
1604
2109
  }, [
1605
2110
  props.elements
1606
2111
  ]);
1607
- return /* @__PURE__ */ import_react5.default.createElement(MouseElementTracker, {
2112
+ return /* @__PURE__ */ import_react10.default.createElement(MouseElementTracker, {
1608
2113
  transform: props.transform,
1609
2114
  primitives: primitives
1610
- }, /* @__PURE__ */ import_react5.default.createElement(CanvasPrimitiveRenderer, {
2115
+ }, /* @__PURE__ */ import_react10.default.createElement(DimensionOverlay, {
2116
+ transform: props.transform
2117
+ }, /* @__PURE__ */ import_react10.default.createElement(ToolbarOverlay, {
2118
+ elements: props.elements
2119
+ }, /* @__PURE__ */ import_react10.default.createElement(CanvasPrimitiveRenderer, {
1611
2120
  transform: props.transform,
1612
2121
  primitives: primitives,
1613
2122
  width: props.width,
1614
2123
  height: props.height,
1615
2124
  grid: props.grid
1616
- }));
2125
+ }))));
1617
2126
  };
1618
2127
  // src/PCBViewer.tsx
1619
2128
  var import_use_mouse_matrix_transform = __toESM(require_dist());
@@ -1621,11 +2130,11 @@ var import_use_mouse_matrix_transform = __toESM(require_dist());
1621
2130
  var noop = function noop() {};
1622
2131
  var isBrowser = typeof window !== "undefined";
1623
2132
  // node_modules/react-use/esm/useIsomorphicLayoutEffect.js
1624
- var import_react7 = require("react");
1625
- var useIsomorphicLayoutEffect = isBrowser ? import_react7.useLayoutEffect : import_react7.useEffect;
2133
+ var import_react12 = require("react");
2134
+ var useIsomorphicLayoutEffect = isBrowser ? import_react12.useLayoutEffect : import_react12.useEffect;
1626
2135
  var useIsomorphicLayoutEffect_default = useIsomorphicLayoutEffect;
1627
2136
  // node_modules/react-use/esm/useMeasure.js
1628
- var import_react8 = require("react");
2137
+ var import_react13 = require("react");
1629
2138
  var defaultState = {
1630
2139
  x: 0,
1631
2140
  y: 0,
@@ -1637,9 +2146,9 @@ var defaultState = {
1637
2146
  right: 0
1638
2147
  };
1639
2148
  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() {
2149
+ var _a = (0, import_react13.useState)(null), element = _a[0], ref = _a[1];
2150
+ var _b = (0, import_react13.useState)(defaultState), rect = _b[0], setRect = _b[1];
2151
+ var observer = (0, import_react13.useMemo)(function() {
1643
2152
  return new window.ResizeObserver(function(entries) {
1644
2153
  if (entries[0]) {
1645
2154
  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 +2186,19 @@ var useMeasure_default = isBrowser && typeof window.ResizeObserver !== "undefine
1677
2186
  ];
1678
2187
  };
1679
2188
  // 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));
2189
+ var import_transformation_matrix4 = require("transformation-matrix");
2190
+ var import_builder4 = require("@tscircuit/builder");
2191
+ var defaultTransform = (0, import_transformation_matrix4.compose)((0, import_transformation_matrix4.translate)(400, 300), (0, import_transformation_matrix4.scale)(40, -40));
1683
2192
  var PCBViewer = function(param) {
1684
2193
  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];
2194
+ var _ref = _sliced_to_array((0, import_react14.useState)([]), 2), stateElements = _ref[0], setStateElements = _ref[1];
1686
2195
  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];
2196
+ var _ref1 = _sliced_to_array((0, import_react14.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
1688
2197
  var _ref2 = (0, import_use_mouse_matrix_transform.default)({
1689
2198
  transform: transform,
1690
2199
  onSetTransform: setTransformInternal
1691
2200
  }), transformRef = _ref2.ref, setTransform = _ref2.setTransform;
1692
- var _ref3 = _sliced_to_array((0, import_react9.useState)(null), 2), error = _ref3[0], setError = _ref3[1];
2201
+ var _ref3 = _sliced_to_array((0, import_react14.useState)(null), 2), error = _ref3[0], setError = _ref3[1];
1693
2202
  var resetTransform = function() {
1694
2203
  var elmBounds = (refDimensions === null || refDimensions === void 0 ? void 0 : refDimensions.width) > 0 ? refDimensions : {
1695
2204
  width: 500,
@@ -1697,7 +2206,7 @@ var PCBViewer = function(param) {
1697
2206
  };
1698
2207
  var _ref = elements.some(function(e) {
1699
2208
  return e.type.startsWith("pcb_");
1700
- }) ? (0, import_builder2.findBoundsAndCenter)(elements.filter(function(e) {
2209
+ }) ? (0, import_builder4.findBoundsAndCenter)(elements.filter(function(e) {
1701
2210
  return e.type.startsWith("pcb_");
1702
2211
  })) : {
1703
2212
  center: {
@@ -1710,10 +2219,10 @@ var PCBViewer = function(param) {
1710
2219
  var _elmBounds_width, _elmBounds_height;
1711
2220
  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
2221
  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)));
2222
+ setTransform((0, import_transformation_matrix4.compose)((0, import_transformation_matrix4.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),
2223
+ (0, import_transformation_matrix4.scale)(scaleFactor, -scaleFactor, 0, 0), (0, import_transformation_matrix4.translate)(-center.x, -center.y)));
1715
2224
  };
1716
- (0, import_react9.useEffect)(function() {
2225
+ (0, import_react14.useEffect)(function() {
1717
2226
  var doRender = function doRender() {
1718
2227
  return _doRender.apply(this, arguments);
1719
2228
  };
@@ -1724,7 +2233,7 @@ var PCBViewer = function(param) {
1724
2233
  return _ts_generator(this, function(_state) {
1725
2234
  switch(_state.label){
1726
2235
  case 0:
1727
- projectBuilder = (0, import_builder.createProjectBuilder)();
2236
+ projectBuilder = (0, import_builder3.createProjectBuilder)();
1728
2237
  return [
1729
2238
  4,
1730
2239
  (0, import_react_fiber.createRoot)().render(children, projectBuilder).then(function(elements2) {
@@ -1749,7 +2258,7 @@ var PCBViewer = function(param) {
1749
2258
  }, [
1750
2259
  children
1751
2260
  ]);
1752
- (0, import_react9.useEffect)(function() {
2261
+ (0, import_react14.useEffect)(function() {
1753
2262
  if (refDimensions && refDimensions.width !== 0 && children) {
1754
2263
  resetTransform();
1755
2264
  }
@@ -1757,18 +2266,18 @@ var PCBViewer = function(param) {
1757
2266
  children,
1758
2267
  refDimensions
1759
2268
  ]);
1760
- if (error) return /* @__PURE__ */ import_react9.default.createElement("div", {
2269
+ if (error) return /* @__PURE__ */ import_react14.default.createElement("div", {
1761
2270
  style: {
1762
2271
  color: "red"
1763
2272
  }
1764
2273
  }, " ", error, " ");
1765
2274
  var elements = soup !== null && soup !== void 0 ? soup : stateElements;
1766
2275
  if (elements.length === 0) return null;
1767
- return /* @__PURE__ */ import_react9.default.createElement("div", {
2276
+ return /* @__PURE__ */ import_react14.default.createElement("div", {
1768
2277
  ref: transformRef
1769
- }, /* @__PURE__ */ import_react9.default.createElement("div", {
2278
+ }, /* @__PURE__ */ import_react14.default.createElement("div", {
1770
2279
  ref: ref
1771
- }, /* @__PURE__ */ import_react9.default.createElement(CanvasElementsRenderer, {
2280
+ }, /* @__PURE__ */ import_react14.default.createElement(ContextProviders, null, /* @__PURE__ */ import_react14.default.createElement(CanvasElementsRenderer, {
1772
2281
  key: refDimensions.width,
1773
2282
  transform: transform,
1774
2283
  height: height,
@@ -1785,7 +2294,7 @@ var PCBViewer = function(param) {
1785
2294
  elements: elements.filter(function(elm) {
1786
2295
  return elm.type.startsWith("pcb_") || elm.type.startsWith("source_");
1787
2296
  })
1788
- })));
2297
+ }))));
1789
2298
  };
1790
2299
  // Annotate the CommonJS export names for ESM import in node:
1791
2300
  0 && (module.exports = {