@tscircuit/pcb-viewer 1.3.4 → 1.3.5

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
@@ -478,20 +478,21 @@ var require_dist = __commonJS({
478
478
  }
479
479
  });
480
480
  module2.exports = __toCommonJS2(src_exports2);
481
- var import_transformation_matrix6 = require("transformation-matrix");
482
- var import_react15 = require("react");
481
+ var import_transformation_matrix8 = require("transformation-matrix");
482
+ var import_react16 = require("react");
483
483
  var useMouseMatrixTransform2 = function() {
484
484
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
485
- var extRef = (0, import_react15.useRef)(null);
485
+ var extRef = (0, import_react16.useRef)(null);
486
+ var _ref = _sliced_to_array((0, import_react16.useState)(0), 2), lastDragCancelTime = _ref[0], setLastDragCancelTime = _ref[1];
486
487
  var _props_canvasElm;
487
488
  var outerCanvasElm = (_props_canvasElm = props.canvasElm) !== null && _props_canvasElm !== void 0 ? _props_canvasElm : extRef.current;
488
489
  var _props_initialTransform;
489
- var _ref = _sliced_to_array((0, import_react15.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_react15.useState)(0), 2), waitCounter = _ref1[0], setWaitCounter = _ref1[1];
491
- var _ref2 = _sliced_to_array((0, import_react15.useReducer)(function(s) {
490
+ var _ref1 = _sliced_to_array((0, import_react16.useState)((_props_initialTransform = props.initialTransform) !== null && _props_initialTransform !== void 0 ? _props_initialTransform : (0, import_transformation_matrix8.identity)()), 2), internalTransform = _ref1[0], setInternalTransform = _ref1[1];
491
+ var _ref2 = _sliced_to_array((0, import_react16.useState)(0), 2), waitCounter = _ref2[0], setWaitCounter = _ref2[1];
492
+ var _ref3 = _sliced_to_array((0, import_react16.useReducer)(function(s) {
492
493
  return s + 1;
493
- }, 0), 2), extChangeCounter = _ref2[0], incExtChangeCounter = _ref2[1];
494
- var setTransform = (0, import_react15.useCallback)(function(newTransform) {
494
+ }, 0), 2), extChangeCounter = _ref3[0], incExtChangeCounter = _ref3[1];
495
+ var setTransform = (0, import_react16.useCallback)(function(newTransform) {
495
496
  if (props.onSetTransform) {
496
497
  props.onSetTransform(newTransform);
497
498
  }
@@ -502,7 +503,7 @@ var require_dist = __commonJS({
502
503
  props.onSetTransform,
503
504
  setInternalTransform
504
505
  ]);
505
- var setTransformExt = (0, import_react15.useCallback)(function(newTransform) {
506
+ var setTransformExt = (0, import_react16.useCallback)(function(newTransform) {
506
507
  setTransform(newTransform);
507
508
  incExtChangeCounter();
508
509
  }, [
@@ -510,15 +511,20 @@ var require_dist = __commonJS({
510
511
  ]);
511
512
  var _props_transform;
512
513
  var transform = (_props_transform = props.transform) !== null && _props_transform !== void 0 ? _props_transform : internalTransform;
513
- (0, import_react15.useEffect)(function() {
514
+ var cancelDrag = (0, import_react16.useCallback)(function() {
515
+ setLastDragCancelTime(Date.now());
516
+ }, []);
517
+ (0, import_react16.useEffect)(function() {
514
518
  var handleMouseDown = function handleMouseDown(e) {
515
519
  m0 = getMousePos(e);
520
+ if (Date.now() - lastDragCancelTime < 100) return;
516
521
  md = true;
517
522
  e.preventDefault();
518
523
  };
519
524
  var handleMouseUp = function handleMouseUp(e) {
525
+ if (!md) return;
520
526
  m1 = getMousePos(e);
521
- var new_tf = (0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
527
+ var new_tf = (0, import_transformation_matrix8.compose)((0, import_transformation_matrix8.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
522
528
  setTransform(new_tf);
523
529
  init_tf = new_tf;
524
530
  md = false;
@@ -527,20 +533,26 @@ var require_dist = __commonJS({
527
533
  mlastrel = getMousePos(e);
528
534
  if (!md) return;
529
535
  m1 = getMousePos(e);
530
- setTransform((0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(m1.x - m0.x, m1.y - m0.y), init_tf));
536
+ setTransform((0, import_transformation_matrix8.compose)((0, import_transformation_matrix8.translate)(m1.x - m0.x, m1.y - m0.y), init_tf));
531
537
  };
532
538
  var handleMouseWheel = function handleMouseWheel(e) {
533
539
  var center = getMousePos(e);
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);
540
+ var new_tf = (0, import_transformation_matrix8.compose)((0, import_transformation_matrix8.translate)(center.x, center.y), (0, import_transformation_matrix8.scale)(1 - e.deltaY / 1e3, 1 - e.deltaY / 1e3), (0, import_transformation_matrix8.translate)(-center.x, -center.y), init_tf);
535
541
  setTransform(new_tf);
536
542
  init_tf = new_tf;
537
543
  e.preventDefault();
538
544
  };
539
545
  var handleMouseOut = function handleMouseOut(e) {
540
546
  if (!md) return;
547
+ if (canvasElm) {
548
+ var boundingBox = canvasElm.getBoundingClientRect();
549
+ if (e.clientX >= boundingBox.left + 10 && e.clientX <= boundingBox.right - 10 && e.clientY >= boundingBox.top + 10 && e.clientY <= boundingBox.bottom - 10) {
550
+ return;
551
+ }
552
+ }
541
553
  md = false;
542
554
  m1 = getMousePos(e);
543
- var new_tf = (0, import_transformation_matrix6.compose)((0, import_transformation_matrix6.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
555
+ var new_tf = (0, import_transformation_matrix8.compose)((0, import_transformation_matrix8.translate)(m1.x - m0.x, m1.y - m0.y), init_tf);
544
556
  setTransform(new_tf);
545
557
  init_tf = new_tf;
546
558
  };
@@ -578,23 +590,24 @@ var require_dist = __commonJS({
578
590
  };
579
591
  canvasElm.addEventListener("mousedown", handleMouseDown);
580
592
  canvasElm.addEventListener("mouseup", handleMouseUp);
581
- canvasElm.addEventListener("mousemove", handleMouseMove);
593
+ window.addEventListener("mousemove", handleMouseMove);
582
594
  canvasElm.addEventListener("mouseout", handleMouseOut);
583
595
  canvasElm.addEventListener("wheel", handleMouseWheel);
584
596
  return function() {
585
597
  canvasElm.removeEventListener("mousedown", handleMouseDown);
586
598
  canvasElm.removeEventListener("mouseup", handleMouseUp);
587
- canvasElm.removeEventListener("mousemove", handleMouseMove);
599
+ window.removeEventListener("mousemove", handleMouseMove);
588
600
  canvasElm.removeEventListener("mouseout", handleMouseOut);
589
601
  canvasElm.removeEventListener("wheel", handleMouseWheel);
590
602
  };
591
603
  }, [
592
604
  outerCanvasElm,
593
605
  waitCounter,
594
- extChangeCounter
606
+ extChangeCounter,
607
+ lastDragCancelTime
595
608
  ]);
596
- var applyTransformToPoint = (0, import_react15.useCallback)(function(obj) {
597
- return (0, import_transformation_matrix6.applyToPoint)(transform, obj);
609
+ var applyTransformToPoint = (0, import_react16.useCallback)(function(obj) {
610
+ return (0, import_transformation_matrix8.applyToPoint)(transform, obj);
598
611
  }, [
599
612
  transform
600
613
  ]);
@@ -602,7 +615,8 @@ var require_dist = __commonJS({
602
615
  ref: extRef,
603
616
  transform: transform,
604
617
  applyTransformToPoint: applyTransformToPoint,
605
- setTransform: setTransformExt
618
+ setTransform: setTransformExt,
619
+ cancelDrag: cancelDrag
606
620
  };
607
621
  };
608
622
  var src_default = useMouseMatrixTransform2;
@@ -620,9 +634,9 @@ __export(src_exports, {
620
634
  });
621
635
  module.exports = __toCommonJS(src_exports);
622
636
  // src/PCBViewer.tsx
623
- var import_react14 = require("react");
637
+ var import_react15 = require("react");
624
638
  var import_react_fiber = require("@tscircuit/react-fiber");
625
- var import_builder3 = require("@tscircuit/builder");
639
+ var import_builder4 = require("@tscircuit/builder");
626
640
  // src/components/CanvasPrimitiveRenderer.tsx
627
641
  var import_react_supergrid = require("react-supergrid");
628
642
  var import_react4 = require("react");
@@ -1306,15 +1320,39 @@ var createStore = function() {
1306
1320
  return (0, import_zustand.createStore)(function(set) {
1307
1321
  return {
1308
1322
  selected_layer: "top",
1323
+ in_edit_mode: false,
1324
+ in_move_footprint_mode: false,
1325
+ in_draw_trace_mode: false,
1326
+ is_moving_component: false,
1327
+ is_drawing_trace: false,
1309
1328
  selectLayer: function(layer) {
1310
1329
  return set({
1311
1330
  selected_layer: layer
1312
1331
  });
1332
+ },
1333
+ setEditMode: function(mode) {
1334
+ return set({
1335
+ in_edit_mode: mode !== "off",
1336
+ in_move_footprint_mode: mode === "move_footprint",
1337
+ in_draw_trace_mode: mode === "draw_trace",
1338
+ is_moving_component: false,
1339
+ is_drawing_trace: false
1340
+ });
1341
+ },
1342
+ setIsMovingComponent: function(is_moving) {
1343
+ return set({
1344
+ is_moving_component: is_moving
1345
+ });
1346
+ },
1347
+ setIsDrawingTrace: function(is_drawing) {
1348
+ return set({
1349
+ is_drawing_trace: is_drawing
1350
+ });
1313
1351
  }
1314
1352
  };
1315
1353
  });
1316
1354
  };
1317
- var useStore = function(s) {
1355
+ var useGlobalStore = function(s) {
1318
1356
  var store = (0, import_react3.useContext)(StoreContext);
1319
1357
  return (0, import_zustand.useStore)(store, s);
1320
1358
  };
@@ -1324,7 +1362,7 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1324
1362
  var CanvasPrimitiveRenderer = function(param) {
1325
1363
  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;
1326
1364
  var canvasRefs = (0, import_react4.useRef)();
1327
- var selectedLayer = useStore(function(s) {
1365
+ var selectedLayer = useGlobalStore(function(s) {
1328
1366
  return s.selected_layer;
1329
1367
  });
1330
1368
  (0, import_react4.useEffect)(function() {
@@ -1387,7 +1425,7 @@ var CanvasPrimitiveRenderer = function(param) {
1387
1425
  });
1388
1426
  };
1389
1427
  // src/components/CanvasElementsRenderer.tsx
1390
- var import_react11 = require("react");
1428
+ var import_react12 = require("react");
1391
1429
  // src/lib/convert-element-to-primitive.ts
1392
1430
  var convertElementToPrimitives = function(element, allElements) {
1393
1431
  var _parent_pcb_component = "pcb_component_id" in element ? allElements.find(function(elm) {
@@ -1716,9 +1754,12 @@ var HighlightedPrimitiveBoxWithText = function(param) {
1716
1754
  };
1717
1755
  var ElementOverlayBox = function(param) {
1718
1756
  var highlightedPrimitives = param.highlightedPrimitives;
1757
+ var is_moving_component = useGlobalStore(function(s) {
1758
+ return s.is_moving_component;
1759
+ });
1719
1760
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", {
1720
1761
  style: containerStyle,
1721
- children: highlightedPrimitives.map(function(primitive, i) {
1762
+ children: !is_moving_component && highlightedPrimitives.map(function(primitive, i) {
1722
1763
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(HighlightedPrimitiveBoxWithText, {
1723
1764
  primitive: primitive
1724
1765
  }, i);
@@ -2114,12 +2155,21 @@ var ToolbarOverlay = function(param) {
2114
2155
  var _ref = _sliced_to_array((0, import_react9.useState)(false), 2), isMouseOverContainer = _ref[0], setIsMouseOverContainer = _ref[1];
2115
2156
  var _ref1 = _sliced_to_array((0, import_react9.useState)(false), 2), isLayerMenuOpen = _ref1[0], setLayerMenuOpen = _ref1[1];
2116
2157
  var _ref2 = _sliced_to_array((0, import_react9.useState)(false), 2), isErrorsOpen = _ref2[0], setErrorsOpen = _ref2[1];
2117
- var _useStore = _sliced_to_array(useStore(function(s) {
2158
+ var _useGlobalStore = _sliced_to_array(useGlobalStore(function(s) {
2118
2159
  return [
2119
2160
  s.selected_layer,
2120
2161
  s.selectLayer
2121
2162
  ];
2122
- }), 2), selectedLayer = _useStore[0], selectLayer = _useStore[1];
2163
+ }), 2), selectedLayer = _useGlobalStore[0], selectLayer = _useGlobalStore[1];
2164
+ var _useGlobalStore1 = _sliced_to_array(useGlobalStore(function(s) {
2165
+ return [
2166
+ s.in_move_footprint_mode,
2167
+ s.in_draw_trace_mode
2168
+ ];
2169
+ }), 2), in_move_footprint_mode = _useGlobalStore1[0], in_draw_trace_mode = _useGlobalStore1[1];
2170
+ var setEditMode = useGlobalStore(function(s) {
2171
+ return s.setEditMode;
2172
+ });
2123
2173
  var _elements_filter_length;
2124
2174
  var errorCount = (_elements_filter_length = elements === null || elements === void 0 ? void 0 : elements.filter(function(e) {
2125
2175
  return e.type.includes("error");
@@ -2131,7 +2181,7 @@ var ToolbarOverlay = function(param) {
2131
2181
  onMouseEnter: function() {
2132
2182
  setIsMouseOverContainer(true);
2133
2183
  },
2134
- onMouseLeave: function() {
2184
+ onMouseLeave: function(e) {
2135
2185
  setIsMouseOverContainer(false);
2136
2186
  setLayerMenuOpen(false);
2137
2187
  },
@@ -2233,6 +2283,30 @@ var ToolbarOverlay = function(param) {
2233
2283
  })
2234
2284
  })
2235
2285
  ]
2286
+ }),
2287
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToolbarButton, {
2288
+ style: {},
2289
+ onClick: function() {
2290
+ setEditMode(in_draw_trace_mode ? "off" : "draw_trace");
2291
+ },
2292
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", {
2293
+ children: [
2294
+ in_draw_trace_mode ? "✖ " : "",
2295
+ "Edit Traces"
2296
+ ]
2297
+ })
2298
+ }),
2299
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToolbarButton, {
2300
+ style: {},
2301
+ onClick: function() {
2302
+ setEditMode(in_move_footprint_mode ? "off" : "move_footprint");
2303
+ },
2304
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", {
2305
+ children: [
2306
+ in_move_footprint_mode ? "✖ " : "",
2307
+ "Move Components"
2308
+ ]
2309
+ })
2236
2310
  })
2237
2311
  ]
2238
2312
  })
@@ -2331,10 +2405,161 @@ var ErrorOverlay = function(param) {
2331
2405
  ]
2332
2406
  });
2333
2407
  };
2334
- // src/components/CanvasElementsRenderer.tsx
2408
+ // src/components/EditOverlay.tsx
2409
+ var import_react11 = require("react");
2410
+ var import_transformation_matrix5 = require("transformation-matrix");
2335
2411
  var import_jsx_runtime8 = require("react/jsx-runtime");
2412
+ var isInsideOf = function(pcb_component, point) {
2413
+ var padding = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 0;
2414
+ var halfWidth = pcb_component.width / 2;
2415
+ var halfHeight = pcb_component.height / 2;
2416
+ var left = pcb_component.center.x - halfWidth - padding;
2417
+ var right = pcb_component.center.x + halfWidth + padding;
2418
+ var top = pcb_component.center.y - halfHeight - padding;
2419
+ var bottom = pcb_component.center.y + halfHeight + padding;
2420
+ return point.x > left && point.x < right && point.y > top && point.y < bottom;
2421
+ };
2422
+ var EditOverlay = function(param) {
2423
+ var children = param.children, disabledProp = param.disabled, transform = param.transform, soup = param.soup, cancelPanDrag = param.cancelPanDrag, onCreateEditEvent = param.onCreateEditEvent, onModifyEditEvent = param.onModifyEditEvent;
2424
+ if (!transform) transform = (0, import_transformation_matrix5.identity)();
2425
+ var containerRef = (0, import_react11.useRef)(null);
2426
+ var _ref = _sliced_to_array((0, import_react11.useState)(null), 2), activePcbComponentId = _ref[0], setActivePcbComponent = _ref[1];
2427
+ var _ref1 = _sliced_to_array((0, import_react11.useState)(null), 2), dragState = _ref1[0], setDragState = _ref1[1];
2428
+ var isPcbComponentActive = activePcbComponentId !== null;
2429
+ var in_edit_mode = useGlobalStore(function(s) {
2430
+ return s.in_edit_mode;
2431
+ });
2432
+ var in_move_footprint_mode = useGlobalStore(function(s) {
2433
+ return s.in_move_footprint_mode;
2434
+ });
2435
+ var setIsMovingComponent = useGlobalStore(function(s) {
2436
+ return s.setIsMovingComponent;
2437
+ });
2438
+ var disabled = disabledProp || !in_edit_mode;
2439
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", {
2440
+ ref: containerRef,
2441
+ style: {
2442
+ position: "relative",
2443
+ overflow: "hidden"
2444
+ },
2445
+ onMouseDown: function(e) {
2446
+ if (disabled) return;
2447
+ var rect = e.currentTarget.getBoundingClientRect();
2448
+ var x = e.clientX - rect.left;
2449
+ var y = e.clientY - rect.top;
2450
+ var rwMousePoint = (0, import_transformation_matrix5.applyToPoint)((0, import_transformation_matrix5.inverse)(transform), {
2451
+ x: x,
2452
+ y: y
2453
+ });
2454
+ var foundActiveComponent = false;
2455
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2456
+ try {
2457
+ for(var _iterator = soup[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2458
+ var e2 = _step.value;
2459
+ if (e2.type === "pcb_component" && isInsideOf(e2, rwMousePoint, 10 / transform.a)) {
2460
+ cancelPanDrag();
2461
+ setActivePcbComponent(e2.pcb_component_id);
2462
+ foundActiveComponent = true;
2463
+ var edit_event_id = Math.random().toString();
2464
+ setDragState({
2465
+ dragStart: rwMousePoint,
2466
+ originalCenter: e2.center,
2467
+ dragEnd: rwMousePoint,
2468
+ edit_event_id: edit_event_id
2469
+ });
2470
+ onCreateEditEvent({
2471
+ edit_event_id: edit_event_id,
2472
+ pcb_edit_event_type: "edit_component_location",
2473
+ pcb_component_id: e2.pcb_component_id,
2474
+ original_center: e2.center,
2475
+ new_center: e2.center,
2476
+ in_progress: true
2477
+ });
2478
+ setIsMovingComponent(true);
2479
+ break;
2480
+ }
2481
+ }
2482
+ } catch (err) {
2483
+ _didIteratorError = true;
2484
+ _iteratorError = err;
2485
+ } finally{
2486
+ try {
2487
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2488
+ _iterator.return();
2489
+ }
2490
+ } finally{
2491
+ if (_didIteratorError) {
2492
+ throw _iteratorError;
2493
+ }
2494
+ }
2495
+ }
2496
+ if (!foundActiveComponent) {
2497
+ setActivePcbComponent(null);
2498
+ }
2499
+ if (foundActiveComponent) {
2500
+ e.preventDefault();
2501
+ return false;
2502
+ }
2503
+ },
2504
+ onMouseMove: function(e) {
2505
+ if (!activePcbComponentId || !dragState) return;
2506
+ var rect = e.currentTarget.getBoundingClientRect();
2507
+ var x = e.clientX - rect.left;
2508
+ var y = e.clientY - rect.top;
2509
+ var rwMousePoint = (0, import_transformation_matrix5.applyToPoint)((0, import_transformation_matrix5.inverse)(transform), {
2510
+ x: x,
2511
+ y: y
2512
+ });
2513
+ setDragState(_object_spread_props(_object_spread({}, dragState), {
2514
+ dragEnd: rwMousePoint
2515
+ }));
2516
+ onModifyEditEvent({
2517
+ edit_event_id: dragState.edit_event_id,
2518
+ new_center: {
2519
+ x: dragState.originalCenter.x + rwMousePoint.x - dragState.dragStart.x,
2520
+ y: dragState.originalCenter.y + rwMousePoint.y - dragState.dragStart.y
2521
+ }
2522
+ });
2523
+ },
2524
+ onMouseUp: function(e) {
2525
+ if (!activePcbComponentId) return;
2526
+ setActivePcbComponent(null);
2527
+ setIsMovingComponent(false);
2528
+ if (dragState) {
2529
+ onModifyEditEvent({
2530
+ edit_event_id: dragState.edit_event_id,
2531
+ in_progress: false
2532
+ });
2533
+ setDragState(null);
2534
+ }
2535
+ },
2536
+ children: [
2537
+ children,
2538
+ !disabled && soup.filter(function(e) {
2539
+ return e.type === "pcb_component";
2540
+ }).map(function(e) {
2541
+ var projectedCenter = (0, import_transformation_matrix5.applyToPoint)(transform, e.center);
2542
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", {
2543
+ style: {
2544
+ position: "absolute",
2545
+ pointerEvents: "none",
2546
+ // b/c of transform, this is actually center not left/top
2547
+ left: projectedCenter.x,
2548
+ top: projectedCenter.y,
2549
+ width: e.width * transform.a + 20,
2550
+ height: e.height * transform.a + 20,
2551
+ transform: "translate(-50%, -50%)",
2552
+ background: isPcbComponentActive && activePcbComponentId === e.pcb_component_id ? "rgba(255, 0, 0, 0.2)" : ""
2553
+ }
2554
+ }, e.pcb_component_id);
2555
+ })
2556
+ ]
2557
+ });
2558
+ };
2559
+ // src/components/CanvasElementsRenderer.tsx
2560
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2336
2561
  var CanvasElementsRenderer = function(props) {
2337
- var primitives = (0, import_react11.useMemo)(function() {
2562
+ var primitives = (0, import_react12.useMemo)(function() {
2338
2563
  var primitives2 = props.elements.flatMap(function(elm) {
2339
2564
  return convertElementToPrimitives(elm, props.elements);
2340
2565
  });
@@ -2342,22 +2567,30 @@ var CanvasElementsRenderer = function(props) {
2342
2567
  }, [
2343
2568
  props.elements
2344
2569
  ]);
2345
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MouseElementTracker, {
2570
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MouseElementTracker, {
2346
2571
  transform: props.transform,
2347
2572
  primitives: primitives,
2348
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DimensionOverlay, {
2573
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EditOverlay, {
2574
+ disabled: !props.allowEditing,
2349
2575
  transform: props.transform,
2350
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToolbarOverlay, {
2351
- elements: props.elements,
2352
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ErrorOverlay, {
2353
- transform: props.transform,
2576
+ soup: props.elements,
2577
+ cancelPanDrag: props.cancelPanDrag,
2578
+ onCreateEditEvent: props.onCreateEditEvent,
2579
+ onModifyEditEvent: props.onModifyEditEvent,
2580
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DimensionOverlay, {
2581
+ transform: props.transform,
2582
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ToolbarOverlay, {
2354
2583
  elements: props.elements,
2355
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasPrimitiveRenderer, {
2584
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ErrorOverlay, {
2356
2585
  transform: props.transform,
2357
- primitives: primitives,
2358
- width: props.width,
2359
- height: props.height,
2360
- grid: props.grid
2586
+ elements: props.elements,
2587
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CanvasPrimitiveRenderer, {
2588
+ transform: props.transform,
2589
+ primitives: primitives,
2590
+ width: props.width,
2591
+ height: props.height,
2592
+ grid: props.grid
2593
+ })
2361
2594
  })
2362
2595
  })
2363
2596
  })
@@ -2370,11 +2603,11 @@ var import_use_mouse_matrix_transform = __toESM(require_dist());
2370
2603
  var noop = function noop() {};
2371
2604
  var isBrowser = typeof window !== "undefined";
2372
2605
  // node_modules/react-use/esm/useIsomorphicLayoutEffect.js
2373
- var import_react12 = require("react");
2374
- var useIsomorphicLayoutEffect = isBrowser ? import_react12.useLayoutEffect : import_react12.useEffect;
2606
+ var import_react13 = require("react");
2607
+ var useIsomorphicLayoutEffect = isBrowser ? import_react13.useLayoutEffect : import_react13.useEffect;
2375
2608
  var useIsomorphicLayoutEffect_default = useIsomorphicLayoutEffect;
2376
2609
  // node_modules/react-use/esm/useMeasure.js
2377
- var import_react13 = require("react");
2610
+ var import_react14 = require("react");
2378
2611
  var defaultState = {
2379
2612
  x: 0,
2380
2613
  y: 0,
@@ -2386,9 +2619,9 @@ var defaultState = {
2386
2619
  right: 0
2387
2620
  };
2388
2621
  function useMeasure() {
2389
- var _a = (0, import_react13.useState)(null), element = _a[0], ref = _a[1];
2390
- var _b = (0, import_react13.useState)(defaultState), rect = _b[0], setRect = _b[1];
2391
- var observer = (0, import_react13.useMemo)(function() {
2622
+ var _a = (0, import_react14.useState)(null), element = _a[0], ref = _a[1];
2623
+ var _b = (0, import_react14.useState)(defaultState), rect = _b[0], setRect = _b[1];
2624
+ var observer = (0, import_react14.useMemo)(function() {
2392
2625
  return new window.ResizeObserver(function(entries) {
2393
2626
  if (entries[0]) {
2394
2627
  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;
@@ -2426,20 +2659,56 @@ var useMeasure_default = isBrowser && typeof window.ResizeObserver !== "undefine
2426
2659
  ];
2427
2660
  };
2428
2661
  // src/PCBViewer.tsx
2429
- var import_transformation_matrix5 = require("transformation-matrix");
2430
- var import_builder4 = require("@tscircuit/builder");
2431
- var import_jsx_runtime9 = require("react/jsx-runtime");
2432
- var defaultTransform = (0, import_transformation_matrix5.compose)((0, import_transformation_matrix5.translate)(400, 300), (0, import_transformation_matrix5.scale)(40, -40));
2662
+ var import_transformation_matrix7 = require("transformation-matrix");
2663
+ var import_builder5 = require("@tscircuit/builder");
2664
+ // src/lib/apply-edit-events.ts
2665
+ var import_builder3 = require("@tscircuit/builder");
2666
+ var import_transformation_matrix6 = require("transformation-matrix");
2667
+ var applyEditEvents = function(soup, edit_events) {
2668
+ soup = JSON.parse(JSON.stringify(soup));
2669
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2670
+ try {
2671
+ var _loop = function() {
2672
+ var edit_event = _step.value;
2673
+ if (edit_event.pcb_edit_event_type === "edit_component_location") {
2674
+ var mat = (0, import_transformation_matrix6.translate)(edit_event.new_center.x - edit_event.original_center.x, edit_event.new_center.y - edit_event.original_center.y);
2675
+ soup = soup.map(function(e) {
2676
+ return e.pcb_component_id !== edit_event.pcb_component_id ? e : (0, import_builder3.transformPCBElement)(e, mat);
2677
+ });
2678
+ }
2679
+ };
2680
+ for(var _iterator = edit_events[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_loop();
2681
+ } catch (err) {
2682
+ _didIteratorError = true;
2683
+ _iteratorError = err;
2684
+ } finally{
2685
+ try {
2686
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2687
+ _iterator.return();
2688
+ }
2689
+ } finally{
2690
+ if (_didIteratorError) {
2691
+ throw _iteratorError;
2692
+ }
2693
+ }
2694
+ }
2695
+ return soup;
2696
+ };
2697
+ // src/PCBViewer.tsx
2698
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2699
+ var defaultTransform = (0, import_transformation_matrix7.compose)((0, import_transformation_matrix7.translate)(400, 300), (0, import_transformation_matrix7.scale)(40, -40));
2433
2700
  var PCBViewer = function(param) {
2434
- var children = param.children, soup = param.soup, _param_height = param.height, height = _param_height === void 0 ? 600 : _param_height;
2435
- var _ref = _sliced_to_array((0, import_react14.useState)([]), 2), stateElements = _ref[0], setStateElements = _ref[1];
2701
+ var children = param.children, soup = param.soup, _param_height = param.height, height = _param_height === void 0 ? 600 : _param_height, _param_allowEditing = param.allowEditing, allowEditing = _param_allowEditing === void 0 ? true : _param_allowEditing, editEventsProp = param.editEvents, onEditEventsChanged = param.onEditEventsChanged;
2702
+ var _ref = _sliced_to_array((0, import_react15.useState)([]), 2), stateElements = _ref[0], setStateElements = _ref[1];
2436
2703
  var _useMeasure_default = _sliced_to_array(useMeasure_default(), 2), ref = _useMeasure_default[0], refDimensions = _useMeasure_default[1];
2437
- var _ref1 = _sliced_to_array((0, import_react14.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
2704
+ var _ref1 = _sliced_to_array((0, import_react15.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
2438
2705
  var _ref2 = (0, import_use_mouse_matrix_transform.default)({
2439
2706
  transform: transform,
2440
2707
  onSetTransform: setTransformInternal
2441
- }), transformRef = _ref2.ref, setTransform = _ref2.setTransform;
2442
- var _ref3 = _sliced_to_array((0, import_react14.useState)(null), 2), error = _ref3[0], setError = _ref3[1];
2708
+ }), transformRef = _ref2.ref, setTransform = _ref2.setTransform, cancelPanDrag = _ref2.cancelDrag;
2709
+ var _ref3 = _sliced_to_array((0, import_react15.useState)([]), 2), editEvents = _ref3[0], setEditEvents = _ref3[1];
2710
+ editEvents = editEventsProp !== null && editEventsProp !== void 0 ? editEventsProp : editEvents;
2711
+ var _ref4 = _sliced_to_array((0, import_react15.useState)(null), 2), error = _ref4[0], setError = _ref4[1];
2443
2712
  var resetTransform = function() {
2444
2713
  var elmBounds = (refDimensions === null || refDimensions === void 0 ? void 0 : refDimensions.width) > 0 ? refDimensions : {
2445
2714
  width: 500,
@@ -2447,7 +2716,7 @@ var PCBViewer = function(param) {
2447
2716
  };
2448
2717
  var _ref = elements.some(function(e) {
2449
2718
  return e.type.startsWith("pcb_");
2450
- }) ? (0, import_builder4.findBoundsAndCenter)(elements.filter(function(e) {
2719
+ }) ? (0, import_builder5.findBoundsAndCenter)(elements.filter(function(e) {
2451
2720
  return e.type.startsWith("pcb_");
2452
2721
  })) : {
2453
2722
  center: {
@@ -2460,10 +2729,10 @@ var PCBViewer = function(param) {
2460
2729
  var _elmBounds_width, _elmBounds_height;
2461
2730
  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);
2462
2731
  var _elmBounds_width1, _elmBounds_height1;
2463
- 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),
2464
- (0, import_transformation_matrix5.scale)(scaleFactor, -scaleFactor, 0, 0), (0, import_transformation_matrix5.translate)(-center.x, -center.y)));
2732
+ setTransform((0, import_transformation_matrix7.compose)((0, import_transformation_matrix7.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),
2733
+ (0, import_transformation_matrix7.scale)(scaleFactor, -scaleFactor, 0, 0), (0, import_transformation_matrix7.translate)(-center.x, -center.y)));
2465
2734
  };
2466
- (0, import_react14.useEffect)(function() {
2735
+ (0, import_react15.useEffect)(function() {
2467
2736
  var doRender = function doRender() {
2468
2737
  return _doRender.apply(this, arguments);
2469
2738
  };
@@ -2474,7 +2743,7 @@ var PCBViewer = function(param) {
2474
2743
  return _ts_generator(this, function(_state) {
2475
2744
  switch(_state.label){
2476
2745
  case 0:
2477
- projectBuilder = (0, import_builder3.createProjectBuilder)();
2746
+ projectBuilder = (0, import_builder4.createProjectBuilder)();
2478
2747
  return [
2479
2748
  4,
2480
2749
  (0, import_react_fiber.createRoot)().render(children, projectBuilder).then(function(elements2) {
@@ -2499,7 +2768,7 @@ var PCBViewer = function(param) {
2499
2768
  }, [
2500
2769
  children
2501
2770
  ]);
2502
- (0, import_react14.useEffect)(function() {
2771
+ (0, import_react15.useEffect)(function() {
2503
2772
  if (refDimensions && refDimensions.width !== 0 && (children || soup)) {
2504
2773
  resetTransform();
2505
2774
  }
@@ -2507,7 +2776,7 @@ var PCBViewer = function(param) {
2507
2776
  children,
2508
2777
  refDimensions
2509
2778
  ]);
2510
- if (error) return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", {
2779
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", {
2511
2780
  style: {
2512
2781
  color: "red"
2513
2782
  },
@@ -2517,16 +2786,43 @@ var PCBViewer = function(param) {
2517
2786
  " "
2518
2787
  ]
2519
2788
  });
2520
- var elements = soup !== null && soup !== void 0 ? soup : stateElements;
2521
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", {
2789
+ var pcbElmsPreEdit = (soup !== null && soup !== void 0 ? soup : stateElements).filter(function(e) {
2790
+ return e.type.startsWith("pcb_") || e.type.startsWith("source_");
2791
+ });
2792
+ var elements = (0, import_react15.useMemo)(function() {
2793
+ return applyEditEvents(pcbElmsPreEdit, editEvents);
2794
+ }, [
2795
+ pcbElmsPreEdit,
2796
+ editEvents
2797
+ ]);
2798
+ var onCreateEditEvent = function(event) {
2799
+ setEditEvents(_to_consumable_array(editEvents).concat([
2800
+ event
2801
+ ]));
2802
+ onEditEventsChanged === null || onEditEventsChanged === void 0 ? void 0 : onEditEventsChanged(_to_consumable_array(editEvents).concat([
2803
+ event
2804
+ ]));
2805
+ };
2806
+ var onModifyEditEvent = function(modifiedEvent) {
2807
+ var newEditEvents = editEvents.map(function(e) {
2808
+ return e.edit_event_id === modifiedEvent.edit_event_id ? _object_spread({}, e, modifiedEvent) : e;
2809
+ });
2810
+ setEditEvents(newEditEvents);
2811
+ onEditEventsChanged === null || onEditEventsChanged === void 0 ? void 0 : onEditEventsChanged(newEditEvents);
2812
+ };
2813
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", {
2522
2814
  ref: transformRef,
2523
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", {
2815
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", {
2524
2816
  ref: ref,
2525
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ContextProviders, {
2526
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CanvasElementsRenderer, {
2817
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ContextProviders, {
2818
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CanvasElementsRenderer, {
2527
2819
  transform: transform,
2528
2820
  height: height,
2529
2821
  width: refDimensions.width,
2822
+ allowEditing: allowEditing,
2823
+ cancelPanDrag: cancelPanDrag,
2824
+ onCreateEditEvent: onCreateEditEvent,
2825
+ onModifyEditEvent: onModifyEditEvent,
2530
2826
  grid: {
2531
2827
  spacing: 1,
2532
2828
  view_window: {
@@ -2536,9 +2832,7 @@ var PCBViewer = function(param) {
2536
2832
  bottom: 0
2537
2833
  }
2538
2834
  },
2539
- elements: elements.filter(function(elm) {
2540
- return elm.type.startsWith("pcb_") || elm.type.startsWith("source_");
2541
- })
2835
+ elements: elements
2542
2836
  }, refDimensions.width)
2543
2837
  })
2544
2838
  })