@tscircuit/pcb-viewer 1.11.282 → 1.11.284

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
@@ -10468,7 +10468,6 @@ var createBoxFromPoints = (points) => {
10468
10468
  }
10469
10469
  return { minX, maxX, minY, maxY };
10470
10470
  };
10471
- var getBoundsFromPoints = createBoxFromPoints;
10472
10471
  var mergeBoundingBoxesInternal = (a, b) => ({
10473
10472
  minX: Math.min(a.minX, b.minX),
10474
10473
  maxX: Math.max(a.maxX, b.maxX),
@@ -10605,7 +10604,7 @@ function calculateDiagonalLabel(params) {
10605
10604
  } = params;
10606
10605
  const deltaX = dimensionEnd.x - dimensionStart.x;
10607
10606
  const deltaY = dimensionEnd.y - dimensionStart.y;
10608
- const distance5 = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
10607
+ const distance4 = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
10609
10608
  const screenDeltaX = screenDimensionEnd.x - screenDimensionStart.x;
10610
10609
  const screenDeltaY = screenDimensionEnd.y - screenDimensionStart.y;
10611
10610
  const screenDistance = Math.sqrt(
@@ -10647,11 +10646,11 @@ function calculateDiagonalLabel(params) {
10647
10646
  const x = midX + offsetX;
10648
10647
  const y = midY + offsetY;
10649
10648
  return {
10650
- distance: distance5,
10649
+ distance: distance4,
10651
10650
  screenDistance,
10652
10651
  x,
10653
10652
  y,
10654
- show: distance5 > 0.01 && screenDistance > 30 && isDiagonal
10653
+ show: distance4 > 0.01 && screenDistance > 30 && isDiagonal
10655
10654
  };
10656
10655
  }
10657
10656
 
@@ -10945,11 +10944,11 @@ var DimensionOverlay = ({
10945
10944
  for (const snap of snappingPointsWithScreen) {
10946
10945
  const dx = snap.screenPoint.x - screenPoint.x;
10947
10946
  const dy = snap.screenPoint.y - screenPoint.y;
10948
- const distance5 = Math.hypot(dx, dy);
10949
- if (distance5 > SNAP_THRESHOLD_PX) continue;
10950
- if (!bestMatch || distance5 < bestMatch.distance) {
10947
+ const distance4 = Math.hypot(dx, dy);
10948
+ if (distance4 > SNAP_THRESHOLD_PX) continue;
10949
+ if (!bestMatch || distance4 < bestMatch.distance) {
10951
10950
  bestMatch = {
10952
- distance: distance5,
10951
+ distance: distance4,
10953
10952
  id: snap.id,
10954
10953
  point: snap.point
10955
10954
  };
@@ -11548,10 +11547,10 @@ var isInsideOfSmtpad = (elm, point, padding = 0) => {
11548
11547
  };
11549
11548
  var isInsideOfPlatedHole = (hole, point, padding = 0) => {
11550
11549
  if (hole.shape === "circle") {
11551
- const distance5 = Math.sqrt(
11550
+ const distance4 = Math.sqrt(
11552
11551
  (point.x - hole.x) ** 2 + (point.y - hole.y) ** 2
11553
11552
  );
11554
- return distance5 <= hole.outer_diameter / 2 + padding;
11553
+ return distance4 <= hole.outer_diameter / 2 + padding;
11555
11554
  } else if (hole.shape === "circular_hole_with_rect_pad") {
11556
11555
  const dx = Math.abs(point.x - hole.x);
11557
11556
  const dy = Math.abs(point.y - hole.y);
@@ -12379,7 +12378,7 @@ var ErrorOverlay = ({
12379
12378
 
12380
12379
  // src/components/MouseElementTracker.tsx
12381
12380
  import { pointToSegmentDistance } from "@tscircuit/math-utils";
12382
- import { distance as distance4 } from "circuit-json";
12381
+ import { distance as distance3 } from "circuit-json";
12383
12382
 
12384
12383
  // src/lib/util/if-sets-match-exactly.ts
12385
12384
  function ifSetsMatchExactly(set1, set2) {
@@ -12709,6 +12708,7 @@ var BoardAnchorOffsetOverlay = ({
12709
12708
  const components = elements.filter(
12710
12709
  (el) => isPcbComponent(el)
12711
12710
  );
12711
+ const groups = elements.filter((el) => isPcbGroup(el));
12712
12712
  const hoveredComponentIds = highlightedPrimitives.map((primitive) => {
12713
12713
  if (isPcbComponent(primitive._parent_pcb_component)) {
12714
12714
  return primitive._parent_pcb_component.pcb_component_id;
@@ -12718,20 +12718,36 @@ var BoardAnchorOffsetOverlay = ({
12718
12718
  }
12719
12719
  return null;
12720
12720
  }).filter((id) => Boolean(id));
12721
+ const hoveredGroupIds = /* @__PURE__ */ new Set();
12722
+ hoveredComponentIds.forEach((componentId) => {
12723
+ const component = components.find((c) => c.pcb_component_id === componentId);
12724
+ if (component?.pcb_group_id) {
12725
+ hoveredGroupIds.add(component.pcb_group_id);
12726
+ }
12727
+ });
12721
12728
  const isShowingAnchorOffsets = useGlobalStore(
12722
12729
  (state) => state.is_showing_group_anchor_offsets
12723
12730
  );
12724
12731
  if (!isShowingAnchorOffsets && hoveredComponentIds.length === 0) {
12725
12732
  return null;
12726
12733
  }
12727
- const targets = components.map((component) => {
12734
+ const componentTargets = components.map((component) => {
12728
12735
  const boardId = component.positioned_relative_to_pcb_board_id;
12729
12736
  if (!boardId) return null;
12730
12737
  const board = boards.find((b) => b.pcb_board_id === boardId);
12731
- return board ? { component, board } : null;
12738
+ return board ? { component, board, type: "component" } : null;
12739
+ }).filter(
12740
+ (target) => Boolean(target)
12741
+ );
12742
+ const groupTargets = groups.map((group) => {
12743
+ const boardId = group.positioned_relative_to_pcb_board_id;
12744
+ if (!boardId || !group.center) return null;
12745
+ const board = boards.find((b) => b.pcb_board_id === boardId);
12746
+ return board ? { group, board, type: "group" } : null;
12732
12747
  }).filter(
12733
12748
  (target) => Boolean(target)
12734
12749
  );
12750
+ const targets = [...componentTargets, ...groupTargets];
12735
12751
  if (targets.length === 0) return null;
12736
12752
  const shouldShowAllTargets = hoveredComponentIds.length === 0;
12737
12753
  const labelStyle = {
@@ -12742,9 +12758,13 @@ var BoardAnchorOffsetOverlay = ({
12742
12758
  fontFamily: "monospace",
12743
12759
  fontWeight: "bold"
12744
12760
  };
12745
- const targetEntries = targets.filter(
12746
- ({ component }) => shouldShowAllTargets || hoveredComponentIds.includes(component.pcb_component_id)
12747
- );
12761
+ const targetEntries = targets.filter((target) => {
12762
+ if (target.type === "component") {
12763
+ return shouldShowAllTargets || hoveredComponentIds.includes(target.component.pcb_component_id);
12764
+ } else {
12765
+ return shouldShowAllTargets || hoveredGroupIds.has(target.group.pcb_group_id);
12766
+ }
12767
+ });
12748
12768
  if (targetEntries.length === 0) return null;
12749
12769
  const boardAnchorScreens = /* @__PURE__ */ new Map();
12750
12770
  return /* @__PURE__ */ jsx12(
@@ -12772,35 +12792,53 @@ var BoardAnchorOffsetOverlay = ({
12772
12792
  width: containerWidth,
12773
12793
  height: containerHeight,
12774
12794
  children: [
12775
- targetEntries.map(({ component, board }) => {
12776
- const anchorPosition = board.center;
12777
- const componentCenter = component.center;
12778
- const anchorKey = board.pcb_board_id;
12795
+ targetEntries.map((target) => {
12796
+ const anchorPosition = target.board.center;
12797
+ const anchorKey = target.board.pcb_board_id;
12798
+ let targetCenter;
12799
+ let targetId;
12800
+ let displayOffsetX;
12801
+ let displayOffsetY;
12802
+ if (target.type === "component") {
12803
+ targetCenter = target.component.center;
12804
+ targetId = target.component.pcb_component_id;
12805
+ displayOffsetX = target.component.display_offset_x;
12806
+ displayOffsetY = target.component.display_offset_y;
12807
+ } else {
12808
+ if (!target.group.center) return null;
12809
+ targetCenter = {
12810
+ x: target.group.center.x,
12811
+ y: target.group.center.y
12812
+ };
12813
+ targetId = target.group.pcb_group_id;
12814
+ displayOffsetX = target.group.display_offset_x;
12815
+ displayOffsetY = target.group.display_offset_y;
12816
+ }
12779
12817
  if (!boardAnchorScreens.has(anchorKey)) {
12780
12818
  const screenPoint = applyToPoint12(transform, anchorPosition);
12781
12819
  boardAnchorScreens.set(anchorKey, screenPoint);
12782
12820
  }
12783
12821
  const anchorMarkerScreen = boardAnchorScreens.get(anchorKey);
12784
- const componentScreen = applyToPoint12(transform, componentCenter);
12785
- const offsetX = componentCenter.x - anchorPosition.x;
12786
- const offsetY = componentCenter.y - anchorPosition.y;
12787
- const xLineLength = Math.abs(componentScreen.x - anchorMarkerScreen.x);
12788
- const yLineLength = Math.abs(componentScreen.y - anchorMarkerScreen.y);
12789
- const isComponentAboveAnchor = componentScreen.y < anchorMarkerScreen.y;
12790
- const isComponentRightOfAnchor = componentScreen.x > anchorMarkerScreen.x;
12791
- const xLabelOffset = isComponentAboveAnchor ? VISUAL_CONFIG.LABEL_OFFSET_ABOVE : VISUAL_CONFIG.LABEL_OFFSET_BELOW;
12792
- const yLabelOffset = isComponentRightOfAnchor ? VISUAL_CONFIG.LABEL_OFFSET_RIGHT : VISUAL_CONFIG.LABEL_OFFSET_LEFT;
12822
+ const targetScreen = applyToPoint12(transform, targetCenter);
12823
+ const offsetX = targetCenter.x - anchorPosition.x;
12824
+ const offsetY = targetCenter.y - anchorPosition.y;
12825
+ const xLineLength = Math.abs(targetScreen.x - anchorMarkerScreen.x);
12826
+ const yLineLength = Math.abs(targetScreen.y - anchorMarkerScreen.y);
12827
+ const isTargetAboveAnchor = targetScreen.y < anchorMarkerScreen.y;
12828
+ const isTargetRightOfAnchor = targetScreen.x > anchorMarkerScreen.x;
12829
+ const xLabelOffset = isTargetAboveAnchor ? VISUAL_CONFIG.LABEL_OFFSET_ABOVE : VISUAL_CONFIG.LABEL_OFFSET_BELOW;
12830
+ const yLabelOffset = isTargetRightOfAnchor ? VISUAL_CONFIG.LABEL_OFFSET_RIGHT : VISUAL_CONFIG.LABEL_OFFSET_LEFT;
12793
12831
  const shouldShowXLabel = xLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL;
12794
12832
  const shouldShowYLabel = yLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL;
12795
- const xLabelText = component.display_offset_x ?? `Board \u0394x: ${offsetX.toFixed(2)}mm`;
12796
- const yLabelText = component.display_offset_y ?? `Board \u0394y: ${offsetY.toFixed(2)}mm`;
12833
+ const xLabelText = displayOffsetX ?? `Board \u0394x: ${offsetX.toFixed(2)}mm`;
12834
+ const yLabelText = displayOffsetY ?? `Board \u0394y: ${offsetY.toFixed(2)}mm`;
12797
12835
  return /* @__PURE__ */ jsxs9("g", { children: [
12798
12836
  /* @__PURE__ */ jsx12(
12799
12837
  "line",
12800
12838
  {
12801
12839
  x1: anchorMarkerScreen.x,
12802
12840
  y1: anchorMarkerScreen.y,
12803
- x2: componentScreen.x,
12841
+ x2: targetScreen.x,
12804
12842
  y2: anchorMarkerScreen.y,
12805
12843
  stroke: COLORS.OFFSET_LINE,
12806
12844
  strokeWidth: VISUAL_CONFIG.LINE_STROKE_WIDTH,
@@ -12810,10 +12848,10 @@ var BoardAnchorOffsetOverlay = ({
12810
12848
  /* @__PURE__ */ jsx12(
12811
12849
  "line",
12812
12850
  {
12813
- x1: componentScreen.x,
12851
+ x1: targetScreen.x,
12814
12852
  y1: anchorMarkerScreen.y,
12815
- x2: componentScreen.x,
12816
- y2: componentScreen.y,
12853
+ x2: targetScreen.x,
12854
+ y2: targetScreen.y,
12817
12855
  stroke: COLORS.OFFSET_LINE,
12818
12856
  strokeWidth: VISUAL_CONFIG.LINE_STROKE_WIDTH,
12819
12857
  strokeDasharray: VISUAL_CONFIG.LINE_DASH_PATTERN
@@ -12822,8 +12860,8 @@ var BoardAnchorOffsetOverlay = ({
12822
12860
  /* @__PURE__ */ jsx12(
12823
12861
  "circle",
12824
12862
  {
12825
- cx: componentScreen.x,
12826
- cy: componentScreen.y,
12863
+ cx: targetScreen.x,
12864
+ cy: targetScreen.y,
12827
12865
  r: VISUAL_CONFIG.COMPONENT_MARKER_RADIUS,
12828
12866
  fill: COLORS.COMPONENT_MARKER_FILL,
12829
12867
  stroke: COLORS.COMPONENT_MARKER_STROKE,
@@ -12833,9 +12871,9 @@ var BoardAnchorOffsetOverlay = ({
12833
12871
  shouldShowXLabel && /* @__PURE__ */ jsx12(
12834
12872
  "foreignObject",
12835
12873
  {
12836
- x: Math.min(anchorMarkerScreen.x, componentScreen.x),
12874
+ x: Math.min(anchorMarkerScreen.x, targetScreen.x),
12837
12875
  y: anchorMarkerScreen.y + xLabelOffset,
12838
- width: Math.abs(componentScreen.x - anchorMarkerScreen.x),
12876
+ width: Math.abs(targetScreen.x - anchorMarkerScreen.x),
12839
12877
  height: 20,
12840
12878
  style: { overflow: "visible" },
12841
12879
  children: /* @__PURE__ */ jsx12("div", { style: { ...labelStyle, textAlign: "center" }, children: xLabelText })
@@ -12844,10 +12882,10 @@ var BoardAnchorOffsetOverlay = ({
12844
12882
  shouldShowYLabel && /* @__PURE__ */ jsx12(
12845
12883
  "foreignObject",
12846
12884
  {
12847
- x: componentScreen.x + yLabelOffset,
12848
- y: Math.min(anchorMarkerScreen.y, componentScreen.y),
12885
+ x: targetScreen.x + yLabelOffset,
12886
+ y: Math.min(anchorMarkerScreen.y, targetScreen.y),
12849
12887
  width: 20,
12850
- height: Math.abs(componentScreen.y - anchorMarkerScreen.y),
12888
+ height: Math.abs(targetScreen.y - anchorMarkerScreen.y),
12851
12889
  style: { overflow: "visible" },
12852
12890
  children: /* @__PURE__ */ jsx12(
12853
12891
  "div",
@@ -12863,7 +12901,7 @@ var BoardAnchorOffsetOverlay = ({
12863
12901
  )
12864
12902
  }
12865
12903
  )
12866
- ] }, `${board.pcb_board_id}-${component.pcb_component_id}`);
12904
+ ] }, `${target.board.pcb_board_id}-${targetId}-${target.type}`);
12867
12905
  }),
12868
12906
  Array.from(boardAnchorScreens.entries()).map(
12869
12907
  ([boardId, anchorScreen]) => /* @__PURE__ */ jsxs9("g", { children: [
@@ -12900,26 +12938,6 @@ var BoardAnchorOffsetOverlay = ({
12900
12938
 
12901
12939
  // src/components/AnchorOffsetOverlay/Group/index.tsx
12902
12940
  import { applyToPoint as applyToPoint13 } from "transformation-matrix";
12903
-
12904
- // src/components/AnchorOffsetOverlay/Group/calculateGroupBoundingBox.ts
12905
- import { distance as distance3 } from "circuit-json";
12906
- var calculateGroupBoundingBox = (groupComponents) => {
12907
- const points = [];
12908
- for (const comp of groupComponents) {
12909
- if (!comp.center) {
12910
- continue;
12911
- }
12912
- const width = typeof comp.width === "number" ? comp.width : distance3.parse(comp.width);
12913
- const height = typeof comp.height === "number" ? comp.height : distance3.parse(comp.height);
12914
- const halfWidth = width / 2;
12915
- const halfHeight = height / 2;
12916
- points.push({ x: comp.center.x - halfWidth, y: comp.center.y - halfHeight });
12917
- points.push({ x: comp.center.x + halfWidth, y: comp.center.y + halfHeight });
12918
- }
12919
- return getBoundsFromPoints(points);
12920
- };
12921
-
12922
- // src/components/AnchorOffsetOverlay/Group/index.tsx
12923
12941
  import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
12924
12942
  var GroupAnchorOffsetOverlay = ({
12925
12943
  elements,
@@ -12941,29 +12959,65 @@ var GroupAnchorOffsetOverlay = ({
12941
12959
  }
12942
12960
  return null;
12943
12961
  }).filter((id) => Boolean(id));
12962
+ const collectParentGroups = (groupId, collected) => {
12963
+ if (collected.has(groupId)) return;
12964
+ collected.add(groupId);
12965
+ const group = groups.find((g) => g.pcb_group_id === groupId);
12966
+ if (group?.position_mode === "relative_to_group_anchor" && group.positioned_relative_to_pcb_group_id) {
12967
+ collectParentGroups(group.positioned_relative_to_pcb_group_id, collected);
12968
+ }
12969
+ };
12970
+ const hoveredGroupIds = /* @__PURE__ */ new Set();
12971
+ hoveredComponentIds.forEach((componentId) => {
12972
+ const component = components.find((c) => c.pcb_component_id === componentId);
12973
+ if (!component) return;
12974
+ if (component.position_mode === "relative_to_group_anchor" && component.positioned_relative_to_pcb_group_id) {
12975
+ collectParentGroups(
12976
+ component.positioned_relative_to_pcb_group_id,
12977
+ hoveredGroupIds
12978
+ );
12979
+ }
12980
+ if (component.pcb_group_id) {
12981
+ collectParentGroups(component.pcb_group_id, hoveredGroupIds);
12982
+ }
12983
+ });
12944
12984
  const isShowingAnchorOffsets = useGlobalStore(
12945
12985
  (s) => s.is_showing_group_anchor_offsets
12946
12986
  );
12947
12987
  if (!isShowingAnchorOffsets && hoveredComponentIds.length === 0) {
12948
12988
  return null;
12949
12989
  }
12950
- const targets = components.map((component) => {
12990
+ const componentTargets = components.map((component) => {
12951
12991
  if (component.position_mode === "relative_to_group_anchor" && component.positioned_relative_to_pcb_group_id) {
12952
12992
  const parentGroup = groups.find(
12953
12993
  (group) => group.pcb_group_id === component.positioned_relative_to_pcb_group_id
12954
12994
  );
12955
- return parentGroup && parentGroup.anchor_position ? { component, parentGroup } : null;
12995
+ return parentGroup && parentGroup.anchor_position ? { component, parentGroup, type: "component" } : null;
12956
12996
  }
12957
12997
  if (component.pcb_group_id) {
12958
12998
  const parentGroup = groups.find(
12959
12999
  (group) => group.pcb_group_id === component.pcb_group_id
12960
13000
  );
12961
- return parentGroup && parentGroup.anchor_position ? { component, parentGroup } : null;
13001
+ return parentGroup && parentGroup.anchor_position ? { component, parentGroup, type: "component" } : null;
13002
+ }
13003
+ return null;
13004
+ }).filter(
13005
+ (target) => Boolean(target)
13006
+ );
13007
+ const groupTargets = groups.map((group) => {
13008
+ if (group.position_mode === "relative_to_group_anchor" && group.positioned_relative_to_pcb_group_id) {
13009
+ const parentGroup = groups.find(
13010
+ (g) => g.pcb_group_id === group.positioned_relative_to_pcb_group_id
13011
+ );
13012
+ if (parentGroup && parentGroup.anchor_position && group.center) {
13013
+ return { group, parentGroup, type: "group" };
13014
+ }
12962
13015
  }
12963
13016
  return null;
12964
13017
  }).filter(
12965
13018
  (target) => Boolean(target)
12966
13019
  );
13020
+ const targets = [...componentTargets, ...groupTargets];
12967
13021
  if (targets.length === 0) return null;
12968
13022
  const shouldShowAllTargets = hoveredComponentIds.length === 0;
12969
13023
  const labelStyle = {
@@ -12974,15 +13028,22 @@ var GroupAnchorOffsetOverlay = ({
12974
13028
  fontFamily: "monospace",
12975
13029
  fontWeight: "bold"
12976
13030
  };
12977
- const targetEntries = targets.filter(
12978
- ({ component }) => shouldShowAllTargets || hoveredComponentIds.includes(component.pcb_component_id)
12979
- );
13031
+ const targetEntries = targets.filter((target) => {
13032
+ if (target.type === "component") {
13033
+ return shouldShowAllTargets || hoveredComponentIds.includes(target.component.pcb_component_id);
13034
+ } else {
13035
+ return shouldShowAllTargets || hoveredGroupIds.has(target.group.pcb_group_id) || hoveredGroupIds.has(target.parentGroup.pcb_group_id);
13036
+ }
13037
+ });
12980
13038
  if (targetEntries.length === 0) return null;
12981
13039
  const groupAnchorScreens = /* @__PURE__ */ new Map();
12982
- targetEntries.forEach(({ parentGroup }) => {
12983
- if (!parentGroup.anchor_position) return;
12984
- const anchorScreen = applyToPoint13(transform, parentGroup.anchor_position);
12985
- groupAnchorScreens.set(parentGroup.pcb_group_id, anchorScreen);
13040
+ targetEntries.forEach((target) => {
13041
+ if (!target.parentGroup.anchor_position) return;
13042
+ const anchorScreen = applyToPoint13(
13043
+ transform,
13044
+ target.parentGroup.anchor_position
13045
+ );
13046
+ groupAnchorScreens.set(target.parentGroup.pcb_group_id, anchorScreen);
12986
13047
  });
12987
13048
  return /* @__PURE__ */ jsx13(
12988
13049
  "div",
@@ -13009,34 +13070,48 @@ var GroupAnchorOffsetOverlay = ({
13009
13070
  width: containerWidth,
13010
13071
  height: containerHeight,
13011
13072
  children: [
13012
- targetEntries.map(({ component, parentGroup }) => {
13013
- const anchor = parentGroup.anchor_position;
13014
- const center = component.center;
13015
- if (!anchor || !center) return null;
13073
+ targetEntries.map((target) => {
13074
+ const anchor = target.parentGroup.anchor_position;
13075
+ if (!anchor) return null;
13016
13076
  const anchorMarkerPosition = { x: anchor.x, y: anchor.y };
13017
- const targetCenter = { x: center.x, y: center.y };
13018
- const groupComponents = components.filter(
13019
- (comp) => comp.pcb_group_id === parentGroup.pcb_group_id
13020
- );
13021
- const boundingBox = calculateGroupBoundingBox(groupComponents);
13022
- if (!boundingBox) return null;
13077
+ let targetCenter = null;
13078
+ let targetId;
13079
+ let displayOffsetX;
13080
+ let displayOffsetY;
13081
+ if (target.type === "component") {
13082
+ const center = target.component.center;
13083
+ if (!center) return null;
13084
+ targetCenter = { x: center.x, y: center.y };
13085
+ targetId = target.component.pcb_component_id;
13086
+ displayOffsetX = target.component.display_offset_x;
13087
+ displayOffsetY = target.component.display_offset_y;
13088
+ } else {
13089
+ if (!target.group.center) return null;
13090
+ targetCenter = {
13091
+ x: target.group.center.x,
13092
+ y: target.group.center.y
13093
+ };
13094
+ targetId = target.group.pcb_group_id;
13095
+ displayOffsetX = target.group.display_offset_x;
13096
+ displayOffsetY = target.group.display_offset_y;
13097
+ }
13023
13098
  const offsetX = targetCenter.x - anchorMarkerPosition.x;
13024
13099
  const offsetY = targetCenter.y - anchorMarkerPosition.y;
13025
13100
  const anchorMarkerScreen = applyToPoint13(
13026
13101
  transform,
13027
13102
  anchorMarkerPosition
13028
13103
  );
13029
- const componentScreen = applyToPoint13(transform, targetCenter);
13030
- const xLineLength = Math.abs(componentScreen.x - anchorMarkerScreen.x);
13031
- const yLineLength = Math.abs(componentScreen.y - anchorMarkerScreen.y);
13032
- const isComponentAboveAnchor = componentScreen.y < anchorMarkerScreen.y;
13033
- const isComponentRightOfAnchor = componentScreen.x > anchorMarkerScreen.x;
13034
- const xLabelOffset = isComponentAboveAnchor ? VISUAL_CONFIG.LABEL_OFFSET_ABOVE : VISUAL_CONFIG.LABEL_OFFSET_BELOW;
13035
- const yLabelOffset = isComponentRightOfAnchor ? VISUAL_CONFIG.LABEL_OFFSET_RIGHT : VISUAL_CONFIG.LABEL_OFFSET_LEFT;
13104
+ const targetScreen = applyToPoint13(transform, targetCenter);
13105
+ const xLineLength = Math.abs(targetScreen.x - anchorMarkerScreen.x);
13106
+ const yLineLength = Math.abs(targetScreen.y - anchorMarkerScreen.y);
13107
+ const isTargetAboveAnchor = targetScreen.y < anchorMarkerScreen.y;
13108
+ const isTargetRightOfAnchor = targetScreen.x > anchorMarkerScreen.x;
13109
+ const xLabelOffset = isTargetAboveAnchor ? VISUAL_CONFIG.LABEL_OFFSET_ABOVE : VISUAL_CONFIG.LABEL_OFFSET_BELOW;
13110
+ const yLabelOffset = isTargetRightOfAnchor ? VISUAL_CONFIG.LABEL_OFFSET_RIGHT : VISUAL_CONFIG.LABEL_OFFSET_LEFT;
13036
13111
  const shouldShowXLabel = xLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL;
13037
13112
  const shouldShowYLabel = yLineLength > VISUAL_CONFIG.MIN_LINE_LENGTH_FOR_LABEL;
13038
- const xLabelText = component.display_offset_x ?? `\u0394x: ${offsetX.toFixed(2)}mm`;
13039
- const yLabelText = component.display_offset_y ?? `\u0394y: ${offsetY.toFixed(2)}mm`;
13113
+ const xLabelText = displayOffsetX ?? `\u0394x: ${offsetX.toFixed(2)}mm`;
13114
+ const yLabelText = displayOffsetY ?? `\u0394y: ${offsetY.toFixed(2)}mm`;
13040
13115
  return /* @__PURE__ */ jsxs10(
13041
13116
  "g",
13042
13117
  {
@@ -13046,7 +13121,7 @@ var GroupAnchorOffsetOverlay = ({
13046
13121
  {
13047
13122
  x1: anchorMarkerScreen.x,
13048
13123
  y1: anchorMarkerScreen.y,
13049
- x2: componentScreen.x,
13124
+ x2: targetScreen.x,
13050
13125
  y2: anchorMarkerScreen.y,
13051
13126
  stroke: COLORS.OFFSET_LINE,
13052
13127
  strokeWidth: VISUAL_CONFIG.LINE_STROKE_WIDTH,
@@ -13056,10 +13131,10 @@ var GroupAnchorOffsetOverlay = ({
13056
13131
  /* @__PURE__ */ jsx13(
13057
13132
  "line",
13058
13133
  {
13059
- x1: componentScreen.x,
13134
+ x1: targetScreen.x,
13060
13135
  y1: anchorMarkerScreen.y,
13061
- x2: componentScreen.x,
13062
- y2: componentScreen.y,
13136
+ x2: targetScreen.x,
13137
+ y2: targetScreen.y,
13063
13138
  stroke: COLORS.OFFSET_LINE,
13064
13139
  strokeWidth: VISUAL_CONFIG.LINE_STROKE_WIDTH,
13065
13140
  strokeDasharray: VISUAL_CONFIG.LINE_DASH_PATTERN
@@ -13068,8 +13143,8 @@ var GroupAnchorOffsetOverlay = ({
13068
13143
  /* @__PURE__ */ jsx13(
13069
13144
  "circle",
13070
13145
  {
13071
- cx: componentScreen.x,
13072
- cy: componentScreen.y,
13146
+ cx: targetScreen.x,
13147
+ cy: targetScreen.y,
13073
13148
  r: VISUAL_CONFIG.COMPONENT_MARKER_RADIUS,
13074
13149
  fill: COLORS.COMPONENT_MARKER_FILL,
13075
13150
  stroke: COLORS.COMPONENT_MARKER_STROKE,
@@ -13079,9 +13154,9 @@ var GroupAnchorOffsetOverlay = ({
13079
13154
  shouldShowXLabel && /* @__PURE__ */ jsx13(
13080
13155
  "foreignObject",
13081
13156
  {
13082
- x: Math.min(anchorMarkerScreen.x, componentScreen.x),
13157
+ x: Math.min(anchorMarkerScreen.x, targetScreen.x),
13083
13158
  y: anchorMarkerScreen.y + xLabelOffset,
13084
- width: Math.abs(componentScreen.x - anchorMarkerScreen.x),
13159
+ width: Math.abs(targetScreen.x - anchorMarkerScreen.x),
13085
13160
  height: 20,
13086
13161
  style: { overflow: "visible" },
13087
13162
  children: /* @__PURE__ */ jsx13("div", { style: { ...labelStyle, textAlign: "center" }, children: xLabelText })
@@ -13090,10 +13165,10 @@ var GroupAnchorOffsetOverlay = ({
13090
13165
  shouldShowYLabel && /* @__PURE__ */ jsx13(
13091
13166
  "foreignObject",
13092
13167
  {
13093
- x: componentScreen.x + yLabelOffset,
13094
- y: Math.min(anchorMarkerScreen.y, componentScreen.y),
13168
+ x: targetScreen.x + yLabelOffset,
13169
+ y: Math.min(anchorMarkerScreen.y, targetScreen.y),
13095
13170
  width: 20,
13096
- height: Math.abs(componentScreen.y - anchorMarkerScreen.y),
13171
+ height: Math.abs(targetScreen.y - anchorMarkerScreen.y),
13097
13172
  style: { overflow: "visible" },
13098
13173
  children: /* @__PURE__ */ jsx13(
13099
13174
  "div",
@@ -13111,7 +13186,7 @@ var GroupAnchorOffsetOverlay = ({
13111
13186
  )
13112
13187
  ]
13113
13188
  },
13114
- `${parentGroup.pcb_group_id}-${component.pcb_component_id}`
13189
+ `${target.parentGroup.pcb_group_id}-${targetId}-${target.type}`
13115
13190
  );
13116
13191
  }),
13117
13192
  Array.from(groupAnchorScreens.entries()).map(
@@ -13190,22 +13265,22 @@ var getPrimitivesUnderPoint = (primitives, rwPoint, transform) => {
13190
13265
  for (const primitive of primitives) {
13191
13266
  if (!primitive._element) continue;
13192
13267
  if ("x1" in primitive && primitive._element?.type === "pcb_trace") {
13193
- const distance5 = pointToSegmentDistance(
13268
+ const distance4 = pointToSegmentDistance(
13194
13269
  { x: rwPoint.x, y: rwPoint.y },
13195
13270
  { x: primitive.x1, y: primitive.y1 },
13196
13271
  { x: primitive.x2, y: primitive.y2 }
13197
13272
  );
13198
13273
  const lineWidth = primitive.width || 0.5;
13199
13274
  const detectionThreshold = Math.max(lineWidth * 25, 2) / transform.a;
13200
- if (distance5 < detectionThreshold) {
13275
+ if (distance4 < detectionThreshold) {
13201
13276
  newMousedPrimitives.push(primitive);
13202
13277
  }
13203
13278
  continue;
13204
13279
  }
13205
13280
  if (primitive.pcb_drawing_type === "polygon") {
13206
13281
  const points = primitive.points.map((point) => ({
13207
- x: distance4.parse(point.x),
13208
- y: distance4.parse(point.y)
13282
+ x: distance3.parse(point.x),
13283
+ y: distance3.parse(point.y)
13209
13284
  }));
13210
13285
  const boundingBox = getPolygonBoundingBox(points);
13211
13286
  if (!boundingBox) continue;
@@ -13219,8 +13294,8 @@ var getPrimitivesUnderPoint = (primitives, rwPoint, transform) => {
13219
13294
  }
13220
13295
  if (primitive.pcb_drawing_type === "polygon_with_arcs") {
13221
13296
  const points = primitive.brep_shape.outer_ring.vertices.map((v) => ({
13222
- x: distance4.parse(v.x),
13223
- y: distance4.parse(v.y)
13297
+ x: distance3.parse(v.x),
13298
+ y: distance3.parse(v.y)
13224
13299
  }));
13225
13300
  const boundingBox = getPolygonBoundingBox(points);
13226
13301
  if (!boundingBox) continue;
@@ -13668,11 +13743,11 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
13668
13743
  connectedIds.forEach((id) => {
13669
13744
  const pos = getElementPosition(id);
13670
13745
  if (pos) {
13671
- const distance5 = Math.sqrt(
13746
+ const distance4 = Math.sqrt(
13672
13747
  (sourcePoint.x - pos.x) ** 2 + (sourcePoint.y - pos.y) ** 2
13673
13748
  );
13674
- if (distance5 < minDistance && distance5 > 0) {
13675
- minDistance = distance5;
13749
+ if (distance4 < minDistance && distance4 > 0) {
13750
+ minDistance = distance4;
13676
13751
  nearestPoint = pos;
13677
13752
  }
13678
13753
  }
@@ -13752,7 +13827,7 @@ import { css as css3 } from "@emotion/css";
13752
13827
  // package.json
13753
13828
  var package_default = {
13754
13829
  name: "@tscircuit/pcb-viewer",
13755
- version: "1.11.281",
13830
+ version: "1.11.283",
13756
13831
  main: "dist/index.js",
13757
13832
  type: "module",
13758
13833
  repository: "tscircuit/pcb-viewer",