@tscircuit/pcb-viewer 1.10.24 → 1.10.26

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
@@ -616,20 +616,20 @@ var require_dist = __commonJS({
616
616
  });
617
617
  module2.exports = __toCommonJS2(src_exports2);
618
618
  var import_transformation_matrix12 = require("transformation-matrix");
619
- var import_react21 = require("react");
619
+ var import_react22 = require("react");
620
620
  var useMouseMatrixTransform2 = function() {
621
621
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
622
- var extRef = (0, import_react21.useRef)(null);
623
- var _ref = _sliced_to_array((0, import_react21.useState)(0), 2), lastDragCancelTime = _ref[0], setLastDragCancelTime = _ref[1];
622
+ var extRef = (0, import_react22.useRef)(null);
623
+ var _ref = _sliced_to_array((0, import_react22.useState)(0), 2), lastDragCancelTime = _ref[0], setLastDragCancelTime = _ref[1];
624
624
  var _props_canvasElm;
625
625
  var outerCanvasElm = (_props_canvasElm = props.canvasElm) !== null && _props_canvasElm !== void 0 ? _props_canvasElm : extRef.current;
626
626
  var _props_initialTransform;
627
- var _ref1 = _sliced_to_array((0, import_react21.useState)((_props_initialTransform = props.initialTransform) !== null && _props_initialTransform !== void 0 ? _props_initialTransform : (0, import_transformation_matrix12.identity)()), 2), internalTransform = _ref1[0], setInternalTransform = _ref1[1];
628
- var _ref2 = _sliced_to_array((0, import_react21.useState)(0), 2), waitCounter = _ref2[0], setWaitCounter = _ref2[1];
629
- var _ref3 = _sliced_to_array((0, import_react21.useReducer)(function(s) {
627
+ var _ref1 = _sliced_to_array((0, import_react22.useState)((_props_initialTransform = props.initialTransform) !== null && _props_initialTransform !== void 0 ? _props_initialTransform : (0, import_transformation_matrix12.identity)()), 2), internalTransform = _ref1[0], setInternalTransform = _ref1[1];
628
+ var _ref2 = _sliced_to_array((0, import_react22.useState)(0), 2), waitCounter = _ref2[0], setWaitCounter = _ref2[1];
629
+ var _ref3 = _sliced_to_array((0, import_react22.useReducer)(function(s) {
630
630
  return s + 1;
631
631
  }, 0), 2), extChangeCounter = _ref3[0], incExtChangeCounter = _ref3[1];
632
- var setTransform = (0, import_react21.useCallback)(function(newTransform) {
632
+ var setTransform = (0, import_react22.useCallback)(function(newTransform) {
633
633
  if (props.onSetTransform) {
634
634
  props.onSetTransform(newTransform);
635
635
  }
@@ -640,7 +640,7 @@ var require_dist = __commonJS({
640
640
  props.onSetTransform,
641
641
  setInternalTransform
642
642
  ]);
643
- var setTransformExt = (0, import_react21.useCallback)(function(newTransform) {
643
+ var setTransformExt = (0, import_react22.useCallback)(function(newTransform) {
644
644
  setTransform(newTransform);
645
645
  incExtChangeCounter();
646
646
  }, [
@@ -648,10 +648,10 @@ var require_dist = __commonJS({
648
648
  ]);
649
649
  var _props_transform;
650
650
  var transform = (_props_transform = props.transform) !== null && _props_transform !== void 0 ? _props_transform : internalTransform;
651
- var cancelDrag = (0, import_react21.useCallback)(function() {
651
+ var cancelDrag = (0, import_react22.useCallback)(function() {
652
652
  setLastDragCancelTime(Date.now());
653
653
  }, []);
654
- (0, import_react21.useEffect)(function() {
654
+ (0, import_react22.useEffect)(function() {
655
655
  var handleMouseDown = function handleMouseDown(e) {
656
656
  m0 = getMousePos(e);
657
657
  if (Date.now() - lastDragCancelTime < 100) return;
@@ -743,7 +743,7 @@ var require_dist = __commonJS({
743
743
  extChangeCounter,
744
744
  lastDragCancelTime
745
745
  ]);
746
- var applyTransformToPoint = (0, import_react21.useCallback)(function(obj) {
746
+ var applyTransformToPoint = (0, import_react22.useCallback)(function(obj) {
747
747
  return (0, import_transformation_matrix12.applyToPoint)(transform, obj);
748
748
  }, [
749
749
  transform
@@ -1042,6 +1042,9 @@ __export(dist_exports, {
1042
1042
  source_simple_inductor: function() {
1043
1043
  return source_simple_inductor;
1044
1044
  },
1045
+ source_simple_mosfet: function() {
1046
+ return source_simple_mosfet;
1047
+ },
1045
1048
  source_simple_pin_header: function() {
1046
1049
  return source_simple_pin_header;
1047
1050
  },
@@ -1060,6 +1063,9 @@ __export(dist_exports, {
1060
1063
  source_simple_resonator: function() {
1061
1064
  return source_simple_resonator;
1062
1065
  },
1066
+ source_simple_transistor: function() {
1067
+ return source_simple_transistor;
1068
+ },
1063
1069
  source_trace: function() {
1064
1070
  return source_trace;
1065
1071
  },
@@ -7621,12 +7627,15 @@ var source_component_base = z.object({
7621
7627
  expectTypesMatch(true);
7622
7628
  var source_simple_capacitor = source_component_base.extend({
7623
7629
  ftype: z.literal("simple_capacitor"),
7624
- capacitance: capacitance
7630
+ capacitance: capacitance,
7631
+ display_capacitance: z.string().optional(),
7632
+ max_decoupling_trace_length: distance.optional()
7625
7633
  });
7626
7634
  expectTypesMatch(true);
7627
7635
  var source_simple_resistor = source_component_base.extend({
7628
7636
  ftype: z.literal("simple_resistor"),
7629
- resistance: resistance
7637
+ resistance: resistance,
7638
+ display_resistance: z.string().optional()
7630
7639
  });
7631
7640
  expectTypesMatch(true);
7632
7641
  var source_simple_diode = source_component_base.extend({
@@ -7692,6 +7701,26 @@ var source_simple_resonator = source_component_base.extend({
7692
7701
  frequency: frequency
7693
7702
  });
7694
7703
  expectTypesMatch(true);
7704
+ var source_simple_transistor = source_component_base.extend({
7705
+ ftype: z.literal("simple_transistor"),
7706
+ transistor_type: z.enum([
7707
+ "npn",
7708
+ "pnp"
7709
+ ])
7710
+ });
7711
+ expectTypesMatch(true);
7712
+ var source_simple_mosfet = source_component_base.extend({
7713
+ ftype: z.literal("simple_mosfet"),
7714
+ channel_type: z.enum([
7715
+ "n",
7716
+ "p"
7717
+ ]),
7718
+ mosfet_mode: z.enum([
7719
+ "enhancement",
7720
+ "depletion"
7721
+ ])
7722
+ });
7723
+ expectTypesMatch(true);
7695
7724
  var any_source_component = z.union([
7696
7725
  source_simple_resistor,
7697
7726
  source_simple_capacitor,
@@ -7707,7 +7736,9 @@ var any_source_component = z.union([
7707
7736
  source_simple_potentiometer,
7708
7737
  source_simple_crystal,
7709
7738
  source_simple_pin_header,
7710
- source_simple_resonator
7739
+ source_simple_resonator,
7740
+ source_simple_transistor,
7741
+ source_simple_mosfet
7711
7742
  ]);
7712
7743
  var source_port = z.object({
7713
7744
  type: z.literal("source_port"),
@@ -7723,7 +7754,9 @@ var source_trace = z.object({
7723
7754
  source_trace_id: z.string(),
7724
7755
  connected_source_port_ids: z.array(z.string()),
7725
7756
  connected_source_net_ids: z.array(z.string()),
7726
- subcircuit_connectivity_map_key: z.string().optional()
7757
+ subcircuit_connectivity_map_key: z.string().optional(),
7758
+ max_length: z.number().optional(),
7759
+ display_name: z.string().optional()
7727
7760
  });
7728
7761
  expectTypesMatch(true);
7729
7762
  var source_group = z.object({
@@ -7778,6 +7811,7 @@ expectTypesMatch(true);
7778
7811
  var schematic_component_port_arrangement_by_sides = z.object({
7779
7812
  left_side: z.object({
7780
7813
  pins: z.array(z.number()),
7814
+ // @ts-ignore
7781
7815
  direction: z.enum([
7782
7816
  "top-to-bottom",
7783
7817
  "bottom-to-top"
@@ -7785,6 +7819,7 @@ var schematic_component_port_arrangement_by_sides = z.object({
7785
7819
  }).optional(),
7786
7820
  right_side: z.object({
7787
7821
  pins: z.array(z.number()),
7822
+ // @ts-ignore
7788
7823
  direction: z.enum([
7789
7824
  "top-to-bottom",
7790
7825
  "bottom-to-top"
@@ -7792,6 +7827,7 @@ var schematic_component_port_arrangement_by_sides = z.object({
7792
7827
  }).optional(),
7793
7828
  top_side: z.object({
7794
7829
  pins: z.array(z.number()),
7830
+ // @ts-ignore
7795
7831
  direction: z.enum([
7796
7832
  "left-to-right",
7797
7833
  "right-to-left"
@@ -7799,6 +7835,7 @@ var schematic_component_port_arrangement_by_sides = z.object({
7799
7835
  }).optional(),
7800
7836
  bottom_side: z.object({
7801
7837
  pins: z.array(z.number()),
7838
+ // @ts-ignore
7802
7839
  direction: z.enum([
7803
7840
  "left-to-right",
7804
7841
  "right-to-left"
@@ -8060,12 +8097,30 @@ var pcb_plated_hole_oval = z.object({
8060
8097
  pcb_port_id: z.string().optional(),
8061
8098
  pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
8062
8099
  });
8100
+ var pcb_circular_hole_with_rect_pad = z.object({
8101
+ type: z.literal("pcb_plated_hole"),
8102
+ shape: z.literal("circular_hole_with_rect_pad"),
8103
+ hole_shape: z.literal("circle"),
8104
+ pad_shape: z.literal("rect"),
8105
+ hole_diameter: z.number(),
8106
+ rect_pad_width: z.number(),
8107
+ rect_pad_height: z.number(),
8108
+ x: distance,
8109
+ y: distance,
8110
+ layers: z.array(layer_ref),
8111
+ port_hints: z.array(z.string()).optional(),
8112
+ pcb_component_id: z.string().optional(),
8113
+ pcb_port_id: z.string().optional(),
8114
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
8115
+ });
8063
8116
  var pcb_plated_hole = z.union([
8064
8117
  pcb_plated_hole_circle,
8065
- pcb_plated_hole_oval
8118
+ pcb_plated_hole_oval,
8119
+ pcb_circular_hole_with_rect_pad
8066
8120
  ]);
8067
8121
  expectTypesMatch(true);
8068
8122
  expectTypesMatch(true);
8123
+ expectTypesMatch(true);
8069
8124
  var pcb_port = z.object({
8070
8125
  type: z.literal("pcb_port"),
8071
8126
  pcb_port_id: getZodPrefixedIdWithDefault("pcb_port"),
@@ -8161,6 +8216,7 @@ var pcb_text = z.object({
8161
8216
  width: length,
8162
8217
  height: length,
8163
8218
  lines: z.number(),
8219
+ // @ts-ignore
8164
8220
  align: z.enum([
8165
8221
  "bottom-left"
8166
8222
  ])
@@ -8197,6 +8253,7 @@ var pcb_trace = z.object({
8197
8253
  ]).default("constant").optional(),
8198
8254
  route_order_index: z.number().optional(),
8199
8255
  should_round_corners: z.boolean().optional(),
8256
+ trace_length: z.number().optional(),
8200
8257
  route: z.array(z.union([
8201
8258
  z.object({
8202
8259
  route_type: z.literal("wire"),
@@ -8460,6 +8517,8 @@ var any_circuit_element = z.union([
8460
8517
  source_simple_inductor,
8461
8518
  source_simple_pin_header,
8462
8519
  source_simple_resonator,
8520
+ source_simple_transistor,
8521
+ source_simple_mosfet,
8463
8522
  source_simple_potentiometer,
8464
8523
  source_simple_push_button,
8465
8524
  pcb_component,
@@ -9673,7 +9732,7 @@ var ToastContainer = function() {
9673
9732
  });
9674
9733
  };
9675
9734
  // src/PCBViewer.tsx
9676
- var import_react20 = require("react");
9735
+ var import_react21 = require("react");
9677
9736
  // node_modules/react-use/esm/misc/util.js
9678
9737
  var noop = function noop() {};
9679
9738
  var isBrowser = typeof window !== "undefined";
@@ -9737,7 +9796,7 @@ var useMeasure_default = isBrowser && typeof window.ResizeObserver !== "undefine
9737
9796
  var import_transformation_matrix11 = require("transformation-matrix");
9738
9797
  var import_use_mouse_matrix_transform = __toESM(require_dist());
9739
9798
  // src/components/CanvasElementsRenderer.tsx
9740
- var import_react18 = require("react");
9799
+ var import_react19 = require("react");
9741
9800
  // src/components/CanvasPrimitiveRenderer.tsx
9742
9801
  var import_react_supergrid = require("react-supergrid");
9743
9802
  var import_react7 = require("react");
@@ -10754,7 +10813,7 @@ var CanvasPrimitiveRenderer = function(param) {
10754
10813
  });
10755
10814
  };
10756
10815
  // src/components/CanvasElementsRenderer.tsx
10757
- var import_react19 = require("react");
10816
+ var import_react20 = require("react");
10758
10817
  // src/lib/util/expand-stroke.ts
10759
10818
  function getExpandedStroke(strokeInput, defaultWidth) {
10760
10819
  if (strokeInput.length < 2) {
@@ -11368,6 +11427,50 @@ var import_react10 = require("react");
11368
11427
  var import_transformation_matrix5 = require("transformation-matrix");
11369
11428
  // src/components/ElementOverlayBox.tsx
11370
11429
  var import_react8 = require("react");
11430
+ // src/lib/get-trace-overlay-text.ts
11431
+ function getTraceOverlayInfo(param) {
11432
+ var primitiveElement = param.primitiveElement, elements = param.elements;
11433
+ var text = primitiveElement.trace_length ? "".concat(primitiveElement.trace_length.toFixed(3)) : "";
11434
+ var trace = su_default(elements).source_trace.get(primitiveElement === null || primitiveElement === void 0 ? void 0 : primitiveElement.source_trace_id);
11435
+ if (trace === null || trace === void 0 ? void 0 : trace.display_name) {
11436
+ if (trace === null || trace === void 0 ? void 0 : trace.max_length) {
11437
+ text += " / ".concat(trace.max_length, "mm ");
11438
+ } else {
11439
+ text += " mm ";
11440
+ }
11441
+ text += "(".concat(trace.display_name, ")");
11442
+ }
11443
+ if (!text) return null;
11444
+ var isOverLength = primitiveElement.trace_length && (trace === null || trace === void 0 ? void 0 : trace.max_length) && primitiveElement.trace_length > trace.max_length;
11445
+ return {
11446
+ text: text,
11447
+ isOverLength: isOverLength
11448
+ };
11449
+ }
11450
+ // src/lib/filter-traces-if-multiple.ts
11451
+ function filterTracesIfMultiple(primitives) {
11452
+ var DISPLAY_ALL_TRACE_LENGTHS = false;
11453
+ var traces = primitives.filter(function(p) {
11454
+ return p._element.type === "pcb_trace";
11455
+ });
11456
+ if (traces.length > 1) {
11457
+ if (!DISPLAY_ALL_TRACE_LENGTHS) return primitives.filter(function(p) {
11458
+ return p._element.type !== "pcb_trace";
11459
+ });
11460
+ var shortestTrace = traces.reduce(function(shortest, current2) {
11461
+ var shortestLength = shortest._element.trace_length;
11462
+ var currentLength = current2._element.trace_length;
11463
+ return currentLength < shortestLength ? current2 : shortest;
11464
+ }, traces[0]);
11465
+ return primitives.filter(function(p) {
11466
+ return p._element.type !== "pcb_trace";
11467
+ }).concat([
11468
+ shortestTrace
11469
+ ]);
11470
+ }
11471
+ return primitives;
11472
+ }
11473
+ // src/components/ElementOverlayBox.tsx
11371
11474
  var import_jsx_runtime4 = require("react/jsx-runtime");
11372
11475
  var containerStyle = {
11373
11476
  position: "absolute",
@@ -11382,6 +11485,13 @@ var containerStyle = {
11382
11485
  var getTextForHighlightedPrimitive = function(prim) {
11383
11486
  var element = prim._element, _parent_pcb_component = prim._parent_pcb_component, _parent_source_component = prim._parent_source_component, _source_port = prim._source_port;
11384
11487
  switch(element.type){
11488
+ case "pcb_trace":
11489
+ {
11490
+ if (element.trace_length) {
11491
+ return "".concat(element.trace_length.toFixed(3));
11492
+ }
11493
+ return "";
11494
+ }
11385
11495
  case "pcb_smtpad":
11386
11496
  case "pcb_plated_hole":
11387
11497
  {
@@ -11409,7 +11519,7 @@ var layerColorHightlightMap = {
11409
11519
  bottom: "aqua"
11410
11520
  };
11411
11521
  var HighlightedPrimitiveBoxWithText = function(param) {
11412
- var primitive = param.primitive;
11522
+ var primitive = param.primitive, mousePos = param.mousePos, elements = param.elements;
11413
11523
  var _primitive__element;
11414
11524
  var _ref = _sliced_to_array((0, import_react8.useState)(false), 2), finalState = _ref[0], setFinalState = _ref[1];
11415
11525
  var primitiveElement = primitive._element;
@@ -11433,6 +11543,42 @@ var HighlightedPrimitiveBoxWithText = function(param) {
11433
11543
  if (primitiveElement.type === "pcb_smtpad" && (primitiveElement === null || primitiveElement === void 0 ? void 0 : primitiveElement.shape) === "rotated_rect") {
11434
11544
  rotation2 = primitiveElement === null || primitiveElement === void 0 ? void 0 : primitiveElement.ccw_rotation;
11435
11545
  }
11546
+ if (primitiveElement.type === "pcb_trace") {
11547
+ var traceTextContext = {
11548
+ primitiveElement: primitiveElement,
11549
+ elements: elements
11550
+ };
11551
+ var overlayInfo = getTraceOverlayInfo(traceTextContext);
11552
+ if (!overlayInfo) return null;
11553
+ var yOffset = mousePos.y - 35;
11554
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", {
11555
+ style: {
11556
+ zIndex: zIndexMap.elementOverlay,
11557
+ position: "absolute",
11558
+ left: mousePos.x,
11559
+ top: yOffset,
11560
+ color: color2,
11561
+ pointerEvents: "none",
11562
+ transform: "translateX(-50%)"
11563
+ },
11564
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", {
11565
+ style: {
11566
+ backgroundColor: "#f2efcc",
11567
+ color: overlayInfo.isOverLength ? "red" : "black",
11568
+ textShadow: "none",
11569
+ WebkitFontSmoothing: "antialiased",
11570
+ MozOsxFontSmoothing: "grayscale",
11571
+ padding: "6px 6px",
11572
+ borderRadius: "6px",
11573
+ fontSize: "14px",
11574
+ minWidth: "45px",
11575
+ textAlign: "center",
11576
+ whiteSpace: "nowrap"
11577
+ },
11578
+ children: overlayInfo.text
11579
+ })
11580
+ });
11581
+ }
11436
11582
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", {
11437
11583
  style: {
11438
11584
  zIndex: zIndexMap.elementOverlay,
@@ -11484,15 +11630,29 @@ var HighlightedPrimitiveBoxWithText = function(param) {
11484
11630
  });
11485
11631
  };
11486
11632
  var ElementOverlayBox = function(param) {
11487
- var highlightedPrimitives = param.highlightedPrimitives;
11633
+ var highlightedPrimitives = param.highlightedPrimitives, mousePos = param.mousePos, elements = param.elements;
11488
11634
  var is_moving_component = useGlobalStore(function(s) {
11489
11635
  return s.is_moving_component;
11490
11636
  });
11637
+ var hasSmtPadAndTrace = highlightedPrimitives.some(function(p) {
11638
+ return p._element.type === "pcb_smtpad";
11639
+ }) && highlightedPrimitives.some(function(p) {
11640
+ return p._element.type === "pcb_trace";
11641
+ });
11642
+ var primitives = highlightedPrimitives;
11643
+ if (hasSmtPadAndTrace) {
11644
+ primitives = primitives.filter(function(p) {
11645
+ return p._element.type === "pcb_smtpad";
11646
+ });
11647
+ }
11648
+ primitives = filterTracesIfMultiple(primitives);
11491
11649
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", {
11492
11650
  style: containerStyle,
11493
- children: !is_moving_component && highlightedPrimitives.map(function(primitive, i) {
11651
+ children: !is_moving_component && primitives.map(function(primitive, i) {
11494
11652
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HighlightedPrimitiveBoxWithText, {
11495
- primitive: primitive
11653
+ primitive: primitive,
11654
+ mousePos: mousePos,
11655
+ elements: elements
11496
11656
  }, i);
11497
11657
  })
11498
11658
  });
@@ -11505,10 +11665,15 @@ function ifSetsMatchExactly(set1, set2) {
11505
11665
  });
11506
11666
  }
11507
11667
  // src/components/MouseElementTracker.tsx
11668
+ var import_math_utils = require("@tscircuit/math-utils");
11508
11669
  var import_jsx_runtime5 = require("react/jsx-runtime");
11509
11670
  var MouseElementTracker = function(param) {
11510
- var children = param.children, transform = param.transform, primitives = param.primitives, onMouseHoverOverPrimitives = param.onMouseHoverOverPrimitives;
11671
+ var elements = param.elements, children = param.children, transform = param.transform, primitives = param.primitives, onMouseHoverOverPrimitives = param.onMouseHoverOverPrimitives;
11511
11672
  var _ref = _sliced_to_array((0, import_react9.useState)([]), 2), mousedPrimitives = _ref[0], setMousedPrimitives = _ref[1];
11673
+ var _ref1 = _sliced_to_array((0, import_react9.useState)({
11674
+ x: 0,
11675
+ y: 0
11676
+ }), 2), mousePos = _ref1[0], setMousePos = _ref1[1];
11512
11677
  var highlightedPrimitives = (0, import_react10.useMemo)(function() {
11513
11678
  var highlightedPrimitives2 = [];
11514
11679
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -11566,6 +11731,10 @@ var MouseElementTracker = function(param) {
11566
11731
  var rect = e.currentTarget.getBoundingClientRect();
11567
11732
  var x = e.clientX - rect.left;
11568
11733
  var y = e.clientY - rect.top;
11734
+ setMousePos({
11735
+ x: x,
11736
+ y: y
11737
+ });
11569
11738
  var rwPoint = (0, import_transformation_matrix5.applyToPoint)((0, import_transformation_matrix5.inverse)(transform), {
11570
11739
  x: x,
11571
11740
  y: y
@@ -11575,10 +11744,37 @@ var MouseElementTracker = function(param) {
11575
11744
  try {
11576
11745
  for(var _iterator = primitives[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
11577
11746
  var primitive = _step.value;
11578
- if (!("x" in primitive && "y" in primitive && ("w" in primitive && "h" in primitive || "r" in primitive))) continue;
11747
+ var _primitive__element;
11579
11748
  if (!primitive._element) continue;
11580
- var w = "w" in primitive ? primitive.w : primitive.r * 2;
11581
- var h = "h" in primitive ? primitive.h : primitive.r * 2;
11749
+ if ("x1" in primitive && ((_primitive__element = primitive._element) === null || _primitive__element === void 0 ? void 0 : _primitive__element.type) === "pcb_trace") {
11750
+ var distance2 = (0, import_math_utils.pointToSegmentDistance)({
11751
+ x: rwPoint.x,
11752
+ y: rwPoint.y
11753
+ }, {
11754
+ x: primitive.x1,
11755
+ y: primitive.y1
11756
+ }, {
11757
+ x: primitive.x2,
11758
+ y: primitive.y2
11759
+ });
11760
+ var lineWidth = primitive.width || 0.5;
11761
+ var detectionThreshold = Math.max(lineWidth * 25, 2) / transform.a;
11762
+ if (distance2 < detectionThreshold) {
11763
+ newMousedPrimitives.push(primitive);
11764
+ }
11765
+ continue;
11766
+ }
11767
+ if (!("x" in primitive && "y" in primitive)) continue;
11768
+ var w = 0, h = 0;
11769
+ if ("w" in primitive && "h" in primitive) {
11770
+ w = primitive.w;
11771
+ h = primitive.h;
11772
+ } else if ("r" in primitive) {
11773
+ w = primitive.r * 2;
11774
+ h = primitive.r * 2;
11775
+ } else {
11776
+ continue;
11777
+ }
11582
11778
  if (Math.abs(primitive.x - rwPoint.x) < w / 2 && Math.abs(primitive.y - rwPoint.y) < h / 2) {
11583
11779
  newMousedPrimitives.push(primitive);
11584
11780
  }
@@ -11611,6 +11807,8 @@ var MouseElementTracker = function(param) {
11611
11807
  children: [
11612
11808
  children,
11613
11809
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ElementOverlayBox, {
11810
+ elements: elements,
11811
+ mousePos: mousePos,
11614
11812
  highlightedPrimitives: highlightedPrimitives
11615
11813
  })
11616
11814
  ]
@@ -11886,7 +12084,7 @@ var import_css = require("@emotion/css");
11886
12084
  // package.json
11887
12085
  var package_default = {
11888
12086
  name: "@tscircuit/pcb-viewer",
11889
- version: "1.10.23",
12087
+ version: "1.10.25",
11890
12088
  main: "dist/index.js",
11891
12089
  repository: "tscircuit/pcb-viewer",
11892
12090
  license: "MIT",
@@ -11911,14 +12109,14 @@ var package_default = {
11911
12109
  "@storybook/nextjs": "^8.0.6",
11912
12110
  "@storybook/react": "^8.0.6",
11913
12111
  "@swc/core": "^1.4.12",
11914
- "@tscircuit/core": "0.0.236",
12112
+ "@tscircuit/core": "0.0.253",
11915
12113
  "@tscircuit/eagle-xml-converter": "^0.0.6",
11916
- "@tscircuit/props": "^0.0.108",
12114
+ "@tscircuit/props": "^0.0.124",
11917
12115
  "@tscircuit/soup-util": "^0.0.38",
11918
12116
  "@types/color": "^3.0.6",
11919
12117
  "@types/node": "18.7.23",
11920
12118
  "@types/react": "^18.3.3",
11921
- "circuit-json": "^0.0.120",
12119
+ "circuit-json": "^0.0.128",
11922
12120
  next: "^14.1.4",
11923
12121
  react: "^18.2.0",
11924
12122
  "react-dom": "^18.2.0",
@@ -11936,6 +12134,7 @@ var package_default = {
11936
12134
  },
11937
12135
  dependencies: {
11938
12136
  "@emotion/css": "^11.11.2",
12137
+ "@tscircuit/math-utils": "^0.0.7",
11939
12138
  "circuit-json-to-connectivity-map": "^0.0.16",
11940
12139
  "circuit-to-svg": "^0.0.36",
11941
12140
  color: "^4.2.3",
@@ -12885,28 +13084,103 @@ var EditTraceHintOverlay = function(param) {
12885
13084
  };
12886
13085
  // src/components/RatsNestOverlay.tsx
12887
13086
  var import_transformation_matrix10 = require("transformation-matrix");
13087
+ var import_circuit_json_to_connectivity_map = require("circuit-json-to-connectivity-map");
13088
+ var import_react18 = require("react");
12888
13089
  var import_jsx_runtime12 = require("react/jsx-runtime");
12889
13090
  var RatsNestOverlay = function(param) {
12890
13091
  var transform = param.transform, soup = param.soup, children = param.children;
12891
13092
  var isShowingRatsNest = useGlobalStore(function(s) {
12892
13093
  return s.is_showing_rats_nest;
12893
13094
  });
13095
+ var _ref = (0, import_react18.useMemo)(function() {
13096
+ return (0, import_circuit_json_to_connectivity_map.getFullConnectivityMapFromCircuitJson)(soup || []);
13097
+ }, [
13098
+ soup
13099
+ ]), netMap = _ref.netMap, idToNetMap = _ref.idToNetMap;
13100
+ var ratsNestLines = (0, import_react18.useMemo)(function() {
13101
+ if (!soup || !isShowingRatsNest) return [];
13102
+ var getElementPosition = function(id) {
13103
+ var element = su_default(soup)[id.replace(/_\d+$/, "")].get(id);
13104
+ if (element && "x" in element && "y" in element) {
13105
+ return {
13106
+ x: element.x,
13107
+ y: element.y
13108
+ };
13109
+ }
13110
+ return null;
13111
+ };
13112
+ var findNearestPointInNet = function(sourcePoint, netId) {
13113
+ var connectedIds = netMap[netId] || [];
13114
+ var nearestPoint = null;
13115
+ var minDistance = Infinity;
13116
+ connectedIds.forEach(function(id) {
13117
+ var pos = getElementPosition(id);
13118
+ if (pos) {
13119
+ var distance2 = Math.sqrt(Math.pow(sourcePoint.x - pos.x, 2) + Math.pow(sourcePoint.y - pos.y, 2));
13120
+ if (distance2 < minDistance && distance2 > 0) {
13121
+ minDistance = distance2;
13122
+ nearestPoint = pos;
13123
+ }
13124
+ }
13125
+ });
13126
+ return nearestPoint;
13127
+ };
13128
+ var pcbPorts = su_default(soup).pcb_port.list();
13129
+ var sourceTraces = su_default(soup).source_trace.list();
13130
+ var lines = [];
13131
+ pcbPorts.forEach(function(port, index) {
13132
+ var portId = port.pcb_port_id;
13133
+ var netId = idToNetMap[portId];
13134
+ var isInNet = false;
13135
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
13136
+ try {
13137
+ for(var _iterator = sourceTraces[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
13138
+ var trace = _step.value;
13139
+ var _su_default_source_port_getUsing;
13140
+ var sourceTrace = trace.connected_source_port_ids.includes((_su_default_source_port_getUsing = su_default(soup).source_port.getUsing({
13141
+ pcb_port_id: portId
13142
+ })) === null || _su_default_source_port_getUsing === void 0 ? void 0 : _su_default_source_port_getUsing.source_port_id);
13143
+ if (sourceTrace && trace.connected_source_net_ids.length > 0) {
13144
+ isInNet = true;
13145
+ }
13146
+ }
13147
+ } catch (err) {
13148
+ _didIteratorError = true;
13149
+ _iteratorError = err;
13150
+ } finally{
13151
+ try {
13152
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
13153
+ _iterator.return();
13154
+ }
13155
+ } finally{
13156
+ if (_didIteratorError) {
13157
+ throw _iteratorError;
13158
+ }
13159
+ }
13160
+ }
13161
+ if (!netId) return;
13162
+ var startPoint = {
13163
+ x: port.x,
13164
+ y: port.y
13165
+ };
13166
+ var nearestPoint = findNearestPointInNet(startPoint, netId);
13167
+ if (!nearestPoint) return;
13168
+ lines.push({
13169
+ key: "".concat(portId, "-").concat(index),
13170
+ startPoint: startPoint,
13171
+ endPoint: nearestPoint,
13172
+ isInNet: isInNet
13173
+ });
13174
+ });
13175
+ return lines;
13176
+ }, [
13177
+ soup,
13178
+ netMap,
13179
+ idToNetMap,
13180
+ isShowingRatsNest
13181
+ ]);
12894
13182
  if (!soup || !isShowingRatsNest) return children;
12895
13183
  if (!transform) transform = (0, import_transformation_matrix10.identity)();
12896
- var sourceTraces = su_default(soup).source_trace.list();
12897
- var groups = [];
12898
- sourceTraces.forEach(function(sourceTrace) {
12899
- if (sourceTrace.connected_source_port_ids) {
12900
- var group = [];
12901
- sourceTrace.connected_source_port_ids.forEach(function(source_port_id) {
12902
- var pcbPort = su_default(soup).pcb_port.getWhere({
12903
- source_port_id: source_port_id
12904
- });
12905
- if (pcbPort) group.push(pcbPort);
12906
- });
12907
- groups.push(group);
12908
- }
12909
- });
12910
13184
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", {
12911
13185
  style: {
12912
13186
  position: "relative"
@@ -12924,40 +13198,26 @@ var RatsNestOverlay = function(param) {
12924
13198
  opacity: 0.5,
12925
13199
  zIndex: zIndexMap.ratsNestOverlay
12926
13200
  },
12927
- children: groups.map(function(group, index) {
12928
- var points = group.map(function(port) {
12929
- return (0, import_transformation_matrix10.applyToPoint)(transform, {
12930
- x: port.x,
12931
- y: port.y
12932
- });
12933
- });
12934
- var lines = [];
12935
- for(var i = 0; i < points.length; i++){
12936
- for(var j = i + 1; j < points.length; j++){
12937
- lines.push([
12938
- points[i],
12939
- points[j]
12940
- ]);
12941
- }
12942
- }
12943
- return lines.map(function(param, index2) {
12944
- var _param = _sliced_to_array(param, 2), start = _param[0], end = _param[1];
12945
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("line", {
12946
- x1: start.x,
12947
- y1: start.y,
12948
- x2: end.x,
12949
- y2: end.y,
12950
- stroke: "white",
12951
- strokeWidth: "1"
12952
- }, index2);
12953
- });
13201
+ children: ratsNestLines.map(function(param) {
13202
+ var key = param.key, startPoint = param.startPoint, endPoint = param.endPoint, isInNet = param.isInNet;
13203
+ var transformedStart = (0, import_transformation_matrix10.applyToPoint)(transform, startPoint);
13204
+ var transformedEnd = (0, import_transformation_matrix10.applyToPoint)(transform, endPoint);
13205
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("line", {
13206
+ x1: transformedStart.x,
13207
+ y1: transformedStart.y,
13208
+ x2: transformedEnd.x,
13209
+ y2: transformedEnd.y,
13210
+ stroke: "white",
13211
+ strokeWidth: "1",
13212
+ strokeDasharray: isInNet ? "6,6" : void 0
13213
+ }, key);
12954
13214
  })
12955
13215
  })
12956
13216
  ]
12957
13217
  });
12958
13218
  };
12959
13219
  // src/components/CanvasElementsRenderer.tsx
12960
- var import_circuit_json_to_connectivity_map = require("circuit-json-to-connectivity-map");
13220
+ var import_circuit_json_to_connectivity_map2 = require("circuit-json-to-connectivity-map");
12961
13221
  // src/lib/util/addInteractionMetadataToPrimitives.ts
12962
13222
  function addInteractionMetadataToPrimitives(param) {
12963
13223
  var primitivesWithoutInteractionMetadata = param.primitivesWithoutInteractionMetadata, drawingObjectIdsWithMouseOver = param.drawingObjectIdsWithMouseOver, primitiveIdsInMousedOverNet = param.primitiveIdsInMousedOverNet;
@@ -13000,11 +13260,11 @@ function addInteractionMetadataToPrimitives(param) {
13000
13260
  var import_jsx_runtime13 = require("react/jsx-runtime");
13001
13261
  var CanvasElementsRenderer = function(props) {
13002
13262
  var transform = props.transform, elements = props.elements;
13003
- var _ref = _sliced_to_array((0, import_react19.useMemo)(function() {
13263
+ var _ref = _sliced_to_array((0, import_react20.useMemo)(function() {
13004
13264
  var primitivesWithoutInteractionMetadata2 = props.elements.flatMap(function(elm) {
13005
13265
  return convertElementToPrimitives(elm, props.elements);
13006
13266
  });
13007
- var connectivityMap2 = (0, import_circuit_json_to_connectivity_map.getFullConnectivityMapFromCircuitJson)(props.elements);
13267
+ var connectivityMap2 = (0, import_circuit_json_to_connectivity_map2.getFullConnectivityMapFromCircuitJson)(props.elements);
13008
13268
  return [
13009
13269
  primitivesWithoutInteractionMetadata2,
13010
13270
  connectivityMap2
@@ -13012,8 +13272,9 @@ var CanvasElementsRenderer = function(props) {
13012
13272
  }, [
13013
13273
  props.elements
13014
13274
  ]), 2), primitivesWithoutInteractionMetadata = _ref[0], connectivityMap = _ref[1];
13015
- var _ref1 = _sliced_to_array((0, import_react18.useState)(primitivesWithoutInteractionMetadata), 2), primitives = _ref1[0], setPrimitives = _ref1[1];
13275
+ var _ref1 = _sliced_to_array((0, import_react19.useState)(primitivesWithoutInteractionMetadata), 2), primitives = _ref1[0], setPrimitives = _ref1[1];
13016
13276
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MouseElementTracker, {
13277
+ elements: elements,
13017
13278
  transform: transform,
13018
13279
  primitives: primitivesWithoutInteractionMetadata,
13019
13280
  onMouseHoverOverPrimitives: function(primitivesHoveredOver) {
@@ -13100,12 +13361,12 @@ var PCBViewer = function(param) {
13100
13361
  soup !== null && soup !== void 0 ? soup : soup = circuitJson;
13101
13362
  var _ref = (0, import_core.useRenderedCircuit)(children), circuitJsonFromChildren = _ref.circuitJson, errorFromChildren = _ref.error, isLoading = _ref.isLoading;
13102
13363
  var _useMeasure_default = _sliced_to_array(useMeasure_default(), 2), ref = _useMeasure_default[0], refDimensions = _useMeasure_default[1];
13103
- var _ref1 = _sliced_to_array((0, import_react20.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
13364
+ var _ref1 = _sliced_to_array((0, import_react21.useState)(defaultTransform), 2), transform = _ref1[0], setTransformInternal = _ref1[1];
13104
13365
  var _ref2 = (0, import_use_mouse_matrix_transform.default)({
13105
13366
  transform: transform,
13106
13367
  onSetTransform: setTransformInternal
13107
13368
  }), transformRef = _ref2.ref, setTransform = _ref2.setTransform, cancelPanDrag = _ref2.cancelDrag;
13108
- var _ref3 = _sliced_to_array((0, import_react20.useState)([]), 2), editEvents = _ref3[0], setEditEvents = _ref3[1];
13369
+ var _ref3 = _sliced_to_array((0, import_react21.useState)([]), 2), editEvents = _ref3[0], setEditEvents = _ref3[1];
13109
13370
  editEvents = editEventsProp !== null && editEventsProp !== void 0 ? editEventsProp : editEvents;
13110
13371
  var _ref4;
13111
13372
  var stateElements = (_ref4 = circuitJsonFromChildren !== null && circuitJsonFromChildren !== void 0 ? circuitJsonFromChildren : soup) !== null && _ref4 !== void 0 ? _ref4 : [];
@@ -13131,7 +13392,7 @@ var PCBViewer = function(param) {
13131
13392
  var _elmBounds_width1, _elmBounds_height1;
13132
13393
  setTransform((0, import_transformation_matrix11.compose)((0, import_transformation_matrix11.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), (0, import_transformation_matrix11.scale)(scaleFactor, -scaleFactor, 0, 0), (0, import_transformation_matrix11.translate)(-center.x, -center.y)));
13133
13394
  };
13134
- (0, import_react20.useEffect)(function() {
13395
+ (0, import_react21.useEffect)(function() {
13135
13396
  if (refDimensions && refDimensions.width !== 0 && (children || soup)) {
13136
13397
  resetTransform();
13137
13398
  }
@@ -13143,7 +13404,7 @@ var PCBViewer = function(param) {
13143
13404
  var pcbElmsPreEdit = ((_ref5 = circuitJson !== null && circuitJson !== void 0 ? circuitJson : soup) !== null && _ref5 !== void 0 ? _ref5 : stateElements).filter(function(e) {
13144
13405
  return e.type.startsWith("pcb_") || e.type.startsWith("source_");
13145
13406
  });
13146
- var elements = (0, import_react20.useMemo)(function() {
13407
+ var elements = (0, import_react21.useMemo)(function() {
13147
13408
  return applyEditEvents(pcbElmsPreEdit, editEvents);
13148
13409
  }, [
13149
13410
  pcbElmsPreEdit,