@tscircuit/pcb-viewer 1.11.238 → 1.11.240
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 +406 -40
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6412,7 +6412,7 @@ var ToastContainer = () => {
|
|
|
6412
6412
|
};
|
|
6413
6413
|
|
|
6414
6414
|
// src/PCBViewer.tsx
|
|
6415
|
-
import { useEffect as useEffect16, useMemo as
|
|
6415
|
+
import { useEffect as useEffect16, useMemo as useMemo7, useRef as useRef11, useState as useState11 } from "react";
|
|
6416
6416
|
|
|
6417
6417
|
// node_modules/react-use/esm/misc/util.js
|
|
6418
6418
|
var noop = function() {
|
|
@@ -6963,7 +6963,7 @@ function addInteractionMetadataToPrimitives({
|
|
|
6963
6963
|
}
|
|
6964
6964
|
|
|
6965
6965
|
// src/components/CanvasElementsRenderer.tsx
|
|
6966
|
-
import { useCallback as
|
|
6966
|
+
import { useCallback as useCallback5, useMemo as useMemo6, useState as useState10 } from "react";
|
|
6967
6967
|
|
|
6968
6968
|
// src/lib/util/expand-stroke.ts
|
|
6969
6969
|
function getExpandedStroke(strokeInput, defaultWidth) {
|
|
@@ -7062,6 +7062,59 @@ var convertElementToPrimitives = (element, allElements) => {
|
|
|
7062
7062
|
(e) => e.type === "source_port" && e.source_port_id === _source_port_id
|
|
7063
7063
|
) : void 0;
|
|
7064
7064
|
switch (element.type) {
|
|
7065
|
+
case "pcb_panel": {
|
|
7066
|
+
const { width, height } = element;
|
|
7067
|
+
return [
|
|
7068
|
+
{
|
|
7069
|
+
_pcb_drawing_object_id: `line_${globalPcbDrawingObjectCount++}`,
|
|
7070
|
+
pcb_drawing_type: "line",
|
|
7071
|
+
x1: 0,
|
|
7072
|
+
y1: 0,
|
|
7073
|
+
x2: width,
|
|
7074
|
+
y2: 0,
|
|
7075
|
+
width: 1,
|
|
7076
|
+
zoomIndependent: true,
|
|
7077
|
+
layer: "board",
|
|
7078
|
+
_element: element
|
|
7079
|
+
},
|
|
7080
|
+
{
|
|
7081
|
+
_pcb_drawing_object_id: `line_${globalPcbDrawingObjectCount++}`,
|
|
7082
|
+
pcb_drawing_type: "line",
|
|
7083
|
+
x1: 0,
|
|
7084
|
+
y1: height,
|
|
7085
|
+
x2: width,
|
|
7086
|
+
y2: height,
|
|
7087
|
+
width: 1,
|
|
7088
|
+
zoomIndependent: true,
|
|
7089
|
+
layer: "board",
|
|
7090
|
+
_element: element
|
|
7091
|
+
},
|
|
7092
|
+
{
|
|
7093
|
+
_pcb_drawing_object_id: `line_${globalPcbDrawingObjectCount++}`,
|
|
7094
|
+
pcb_drawing_type: "line",
|
|
7095
|
+
x1: 0,
|
|
7096
|
+
y1: 0,
|
|
7097
|
+
x2: 0,
|
|
7098
|
+
y2: height,
|
|
7099
|
+
width: 1,
|
|
7100
|
+
zoomIndependent: true,
|
|
7101
|
+
layer: "board",
|
|
7102
|
+
_element: element
|
|
7103
|
+
},
|
|
7104
|
+
{
|
|
7105
|
+
_pcb_drawing_object_id: `line_${globalPcbDrawingObjectCount++}`,
|
|
7106
|
+
pcb_drawing_type: "line",
|
|
7107
|
+
x1: width,
|
|
7108
|
+
y1: 0,
|
|
7109
|
+
x2: width,
|
|
7110
|
+
y2: height,
|
|
7111
|
+
width: 1,
|
|
7112
|
+
zoomIndependent: true,
|
|
7113
|
+
layer: "board",
|
|
7114
|
+
_element: element
|
|
7115
|
+
}
|
|
7116
|
+
];
|
|
7117
|
+
}
|
|
7065
7118
|
case "pcb_board": {
|
|
7066
7119
|
const { width, height, center, outline } = element;
|
|
7067
7120
|
if (outline && outline.length > 2) {
|
|
@@ -8017,7 +8070,7 @@ var convertElementToPrimitives = (element, allElements) => {
|
|
|
8017
8070
|
y: noteTextElement.anchor_position.y,
|
|
8018
8071
|
layer: "notes",
|
|
8019
8072
|
align: noteTextElement.anchor_alignment ?? "center",
|
|
8020
|
-
text: noteTextElement.text,
|
|
8073
|
+
text: noteTextElement.text || "",
|
|
8021
8074
|
size: noteTextElement.font_size,
|
|
8022
8075
|
color: noteTextElement.color,
|
|
8023
8076
|
_element: element,
|
|
@@ -9702,43 +9755,306 @@ var WarningGraphicsOverlay = ({
|
|
|
9702
9755
|
};
|
|
9703
9756
|
|
|
9704
9757
|
// src/components/DimensionOverlay.tsx
|
|
9705
|
-
import { useEffect as useEffect7, useRef as useRef5, useState as useState3 } from "react";
|
|
9758
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef5, useState as useState3 } from "react";
|
|
9706
9759
|
import { applyToPoint as applyToPoint8, identity as identity4, inverse as inverse2 } from "transformation-matrix";
|
|
9760
|
+
|
|
9761
|
+
// src/lib/util/get-primitive-bounding-box.ts
|
|
9762
|
+
var mergeNumber = (a, b, fn) => fn(a, b);
|
|
9763
|
+
var rotatePoint = (x, y, centerX, centerY, rotationDeg) => {
|
|
9764
|
+
const radians = rotationDeg * Math.PI / 180;
|
|
9765
|
+
const cos = Math.cos(radians);
|
|
9766
|
+
const sin = Math.sin(radians);
|
|
9767
|
+
const translatedX = x - centerX;
|
|
9768
|
+
const translatedY = y - centerY;
|
|
9769
|
+
const rotatedX = translatedX * cos - translatedY * sin;
|
|
9770
|
+
const rotatedY = translatedX * sin + translatedY * cos;
|
|
9771
|
+
return {
|
|
9772
|
+
x: rotatedX + centerX,
|
|
9773
|
+
y: rotatedY + centerY
|
|
9774
|
+
};
|
|
9775
|
+
};
|
|
9776
|
+
var createBoxFromPoints = (points) => {
|
|
9777
|
+
if (points.length === 0) return null;
|
|
9778
|
+
let minX = points[0].x;
|
|
9779
|
+
let maxX = points[0].x;
|
|
9780
|
+
let minY = points[0].y;
|
|
9781
|
+
let maxY = points[0].y;
|
|
9782
|
+
for (const point of points) {
|
|
9783
|
+
minX = mergeNumber(minX, point.x, Math.min);
|
|
9784
|
+
maxX = mergeNumber(maxX, point.x, Math.max);
|
|
9785
|
+
minY = mergeNumber(minY, point.y, Math.min);
|
|
9786
|
+
maxY = mergeNumber(maxY, point.y, Math.max);
|
|
9787
|
+
}
|
|
9788
|
+
return { minX, maxX, minY, maxY };
|
|
9789
|
+
};
|
|
9790
|
+
var mergeBoundingBoxesInternal = (a, b) => ({
|
|
9791
|
+
minX: Math.min(a.minX, b.minX),
|
|
9792
|
+
maxX: Math.max(a.maxX, b.maxX),
|
|
9793
|
+
minY: Math.min(a.minY, b.minY),
|
|
9794
|
+
maxY: Math.max(a.maxY, b.maxY)
|
|
9795
|
+
});
|
|
9796
|
+
var mergeBoundingBoxes = (existing, next) => {
|
|
9797
|
+
if (!existing) return next;
|
|
9798
|
+
return mergeBoundingBoxesInternal(existing, next);
|
|
9799
|
+
};
|
|
9800
|
+
var getPrimitiveBoundingBox = (primitive) => {
|
|
9801
|
+
switch (primitive.pcb_drawing_type) {
|
|
9802
|
+
case "line": {
|
|
9803
|
+
const halfWidth = (primitive.width ?? 0) / 2;
|
|
9804
|
+
const points = [
|
|
9805
|
+
{ x: primitive.x1, y: primitive.y1 },
|
|
9806
|
+
{ x: primitive.x2, y: primitive.y2 }
|
|
9807
|
+
];
|
|
9808
|
+
const baseBox = createBoxFromPoints(points);
|
|
9809
|
+
if (!baseBox) return null;
|
|
9810
|
+
return {
|
|
9811
|
+
minX: baseBox.minX - halfWidth,
|
|
9812
|
+
maxX: baseBox.maxX + halfWidth,
|
|
9813
|
+
minY: baseBox.minY - halfWidth,
|
|
9814
|
+
maxY: baseBox.maxY + halfWidth
|
|
9815
|
+
};
|
|
9816
|
+
}
|
|
9817
|
+
case "rect": {
|
|
9818
|
+
const halfW = primitive.w / 2;
|
|
9819
|
+
const halfH = primitive.h / 2;
|
|
9820
|
+
const corners = [
|
|
9821
|
+
{ x: primitive.x - halfW, y: primitive.y - halfH },
|
|
9822
|
+
{ x: primitive.x + halfW, y: primitive.y - halfH },
|
|
9823
|
+
{ x: primitive.x + halfW, y: primitive.y + halfH },
|
|
9824
|
+
{ x: primitive.x - halfW, y: primitive.y + halfH }
|
|
9825
|
+
];
|
|
9826
|
+
const rotation = primitive.ccw_rotation ?? 0;
|
|
9827
|
+
const rotatedCorners = rotation === 0 ? corners : corners.map(
|
|
9828
|
+
(corner) => rotatePoint(
|
|
9829
|
+
corner.x,
|
|
9830
|
+
corner.y,
|
|
9831
|
+
primitive.x,
|
|
9832
|
+
primitive.y,
|
|
9833
|
+
rotation
|
|
9834
|
+
)
|
|
9835
|
+
);
|
|
9836
|
+
return createBoxFromPoints(rotatedCorners);
|
|
9837
|
+
}
|
|
9838
|
+
case "circle": {
|
|
9839
|
+
return {
|
|
9840
|
+
minX: primitive.x - primitive.r,
|
|
9841
|
+
maxX: primitive.x + primitive.r,
|
|
9842
|
+
minY: primitive.y - primitive.r,
|
|
9843
|
+
maxY: primitive.y + primitive.r
|
|
9844
|
+
};
|
|
9845
|
+
}
|
|
9846
|
+
case "oval": {
|
|
9847
|
+
return {
|
|
9848
|
+
minX: primitive.x - primitive.rX,
|
|
9849
|
+
maxX: primitive.x + primitive.rX,
|
|
9850
|
+
minY: primitive.y - primitive.rY,
|
|
9851
|
+
maxY: primitive.y + primitive.rY
|
|
9852
|
+
};
|
|
9853
|
+
}
|
|
9854
|
+
case "pill": {
|
|
9855
|
+
const halfW = primitive.w / 2;
|
|
9856
|
+
const halfH = primitive.h / 2;
|
|
9857
|
+
const corners = [
|
|
9858
|
+
{ x: primitive.x - halfW, y: primitive.y - halfH },
|
|
9859
|
+
{ x: primitive.x + halfW, y: primitive.y - halfH },
|
|
9860
|
+
{ x: primitive.x + halfW, y: primitive.y + halfH },
|
|
9861
|
+
{ x: primitive.x - halfW, y: primitive.y + halfH }
|
|
9862
|
+
];
|
|
9863
|
+
const rotation = primitive.ccw_rotation ?? 0;
|
|
9864
|
+
const rotatedCorners = rotation === 0 ? corners : corners.map(
|
|
9865
|
+
(corner) => rotatePoint(
|
|
9866
|
+
corner.x,
|
|
9867
|
+
corner.y,
|
|
9868
|
+
primitive.x,
|
|
9869
|
+
primitive.y,
|
|
9870
|
+
rotation
|
|
9871
|
+
)
|
|
9872
|
+
);
|
|
9873
|
+
return createBoxFromPoints(rotatedCorners);
|
|
9874
|
+
}
|
|
9875
|
+
case "polygon": {
|
|
9876
|
+
return createBoxFromPoints(primitive.points);
|
|
9877
|
+
}
|
|
9878
|
+
case "polygon_with_arcs": {
|
|
9879
|
+
const points = primitive.brep_shape.outer_ring.vertices.map((vertex) => ({
|
|
9880
|
+
x: vertex.x,
|
|
9881
|
+
y: vertex.y
|
|
9882
|
+
}));
|
|
9883
|
+
return createBoxFromPoints(points);
|
|
9884
|
+
}
|
|
9885
|
+
case "text": {
|
|
9886
|
+
const size = primitive.size ?? 0;
|
|
9887
|
+
const width = primitive.text ? primitive.text.length * size * 0.6 : 0;
|
|
9888
|
+
const height = size;
|
|
9889
|
+
if (width === 0 && height === 0) {
|
|
9890
|
+
return {
|
|
9891
|
+
minX: primitive.x,
|
|
9892
|
+
maxX: primitive.x,
|
|
9893
|
+
minY: primitive.y,
|
|
9894
|
+
maxY: primitive.y
|
|
9895
|
+
};
|
|
9896
|
+
}
|
|
9897
|
+
const halfW = width / 2;
|
|
9898
|
+
const halfH = height / 2;
|
|
9899
|
+
return {
|
|
9900
|
+
minX: primitive.x - halfW,
|
|
9901
|
+
maxX: primitive.x + halfW,
|
|
9902
|
+
minY: primitive.y - halfH,
|
|
9903
|
+
maxY: primitive.y + halfH
|
|
9904
|
+
};
|
|
9905
|
+
}
|
|
9906
|
+
default:
|
|
9907
|
+
return null;
|
|
9908
|
+
}
|
|
9909
|
+
};
|
|
9910
|
+
|
|
9911
|
+
// src/components/DimensionOverlay.tsx
|
|
9707
9912
|
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9913
|
+
var SNAP_THRESHOLD_PX = 16;
|
|
9914
|
+
var SNAP_MARKER_SIZE = 5;
|
|
9915
|
+
var shouldExcludePrimitiveFromSnapping = (primitive) => {
|
|
9916
|
+
if (primitive.pcb_drawing_type === "text") return true;
|
|
9917
|
+
const element = primitive._element;
|
|
9918
|
+
if (!element || typeof element !== "object") {
|
|
9919
|
+
return false;
|
|
9920
|
+
}
|
|
9921
|
+
const elementType = typeof element.type === "string" ? element.type : void 0;
|
|
9922
|
+
if (!elementType) return false;
|
|
9923
|
+
if (elementType.startsWith("pcb_silkscreen_")) return true;
|
|
9924
|
+
if (elementType.startsWith("pcb_note_")) return true;
|
|
9925
|
+
if (elementType === "pcb_text") return true;
|
|
9926
|
+
if (elementType.startsWith("pcb_fabrication_note_") && elementType !== "pcb_fabrication_note_rect") {
|
|
9927
|
+
return true;
|
|
9928
|
+
}
|
|
9929
|
+
return false;
|
|
9930
|
+
};
|
|
9708
9931
|
var DimensionOverlay = ({
|
|
9709
9932
|
children,
|
|
9710
9933
|
transform,
|
|
9711
|
-
focusOnHover = false
|
|
9934
|
+
focusOnHover = false,
|
|
9935
|
+
primitives = []
|
|
9712
9936
|
}) => {
|
|
9713
9937
|
if (!transform) transform = identity4();
|
|
9714
9938
|
const [dimensionToolVisible, setDimensionToolVisible] = useState3(false);
|
|
9715
9939
|
const [dimensionToolStretching, setDimensionToolStretching] = useState3(false);
|
|
9716
9940
|
const [measureToolArmed, setMeasureToolArmed] = useState3(false);
|
|
9717
|
-
const
|
|
9941
|
+
const [activeSnapIds, setActiveSnapIds] = useState3({
|
|
9942
|
+
start: null,
|
|
9943
|
+
end: null
|
|
9944
|
+
});
|
|
9945
|
+
const disarmMeasure = useCallback3(() => {
|
|
9718
9946
|
if (measureToolArmed) {
|
|
9719
9947
|
setMeasureToolArmed(false);
|
|
9720
9948
|
window.dispatchEvent(new Event("disarm-dimension-tool"));
|
|
9721
9949
|
}
|
|
9722
|
-
};
|
|
9950
|
+
}, [measureToolArmed]);
|
|
9723
9951
|
const [dStart, setDStart] = useState3({ x: 0, y: 0 });
|
|
9724
9952
|
const [dEnd, setDEnd] = useState3({ x: 0, y: 0 });
|
|
9725
9953
|
const mousePosRef = useRef5({ x: 0, y: 0 });
|
|
9726
9954
|
const containerRef = useRef5(null);
|
|
9727
9955
|
const container = containerRef.current;
|
|
9728
9956
|
const containerBounds = container?.getBoundingClientRect();
|
|
9957
|
+
const elementBoundingBoxes = useMemo3(() => {
|
|
9958
|
+
const boundingBoxes = /* @__PURE__ */ new Map();
|
|
9959
|
+
for (const primitive of primitives) {
|
|
9960
|
+
if (!primitive._element) continue;
|
|
9961
|
+
if (shouldExcludePrimitiveFromSnapping(primitive)) continue;
|
|
9962
|
+
const bbox = getPrimitiveBoundingBox(primitive);
|
|
9963
|
+
if (!bbox) continue;
|
|
9964
|
+
const existing = boundingBoxes.get(primitive._element);
|
|
9965
|
+
boundingBoxes.set(
|
|
9966
|
+
primitive._element,
|
|
9967
|
+
mergeBoundingBoxes(existing ?? void 0, bbox)
|
|
9968
|
+
);
|
|
9969
|
+
}
|
|
9970
|
+
return boundingBoxes;
|
|
9971
|
+
}, [primitives]);
|
|
9972
|
+
const snappingPoints = useMemo3(() => {
|
|
9973
|
+
const points = [];
|
|
9974
|
+
elementBoundingBoxes.forEach((bounds, element) => {
|
|
9975
|
+
if (!bounds) return;
|
|
9976
|
+
const centerX = (bounds.minX + bounds.maxX) / 2;
|
|
9977
|
+
const centerY = (bounds.minY + bounds.maxY) / 2;
|
|
9978
|
+
const anchorPoints = {
|
|
9979
|
+
top_left: { x: bounds.minX, y: bounds.minY },
|
|
9980
|
+
top_center: { x: centerX, y: bounds.minY },
|
|
9981
|
+
top_right: { x: bounds.maxX, y: bounds.minY },
|
|
9982
|
+
center_left: { x: bounds.minX, y: centerY },
|
|
9983
|
+
center: { x: centerX, y: centerY },
|
|
9984
|
+
center_right: { x: bounds.maxX, y: centerY },
|
|
9985
|
+
bottom_left: { x: bounds.minX, y: bounds.maxY },
|
|
9986
|
+
bottom_center: { x: centerX, y: bounds.maxY },
|
|
9987
|
+
bottom_right: { x: bounds.maxX, y: bounds.maxY }
|
|
9988
|
+
};
|
|
9989
|
+
for (const [anchor, point] of Object.entries(anchorPoints)) {
|
|
9990
|
+
points.push({
|
|
9991
|
+
anchor,
|
|
9992
|
+
point,
|
|
9993
|
+
element
|
|
9994
|
+
});
|
|
9995
|
+
}
|
|
9996
|
+
});
|
|
9997
|
+
return points;
|
|
9998
|
+
}, [elementBoundingBoxes]);
|
|
9999
|
+
const snappingPointsWithScreen = useMemo3(() => {
|
|
10000
|
+
return snappingPoints.map((snap, index) => ({
|
|
10001
|
+
...snap,
|
|
10002
|
+
id: `${index}-${snap.anchor}`,
|
|
10003
|
+
screenPoint: applyToPoint8(transform, snap.point)
|
|
10004
|
+
}));
|
|
10005
|
+
}, [snappingPoints, transform]);
|
|
10006
|
+
const findSnap = useCallback3(
|
|
10007
|
+
(rwPoint) => {
|
|
10008
|
+
if (snappingPointsWithScreen.length === 0) {
|
|
10009
|
+
return { point: rwPoint, id: null };
|
|
10010
|
+
}
|
|
10011
|
+
const screenPoint = applyToPoint8(transform, rwPoint);
|
|
10012
|
+
let bestMatch = null;
|
|
10013
|
+
for (const snap of snappingPointsWithScreen) {
|
|
10014
|
+
const dx = snap.screenPoint.x - screenPoint.x;
|
|
10015
|
+
const dy = snap.screenPoint.y - screenPoint.y;
|
|
10016
|
+
const distance5 = Math.hypot(dx, dy);
|
|
10017
|
+
if (distance5 > SNAP_THRESHOLD_PX) continue;
|
|
10018
|
+
if (!bestMatch || distance5 < bestMatch.distance) {
|
|
10019
|
+
bestMatch = {
|
|
10020
|
+
distance: distance5,
|
|
10021
|
+
id: snap.id,
|
|
10022
|
+
point: snap.point
|
|
10023
|
+
};
|
|
10024
|
+
}
|
|
10025
|
+
}
|
|
10026
|
+
if (!bestMatch) {
|
|
10027
|
+
return { point: rwPoint, id: null };
|
|
10028
|
+
}
|
|
10029
|
+
return { point: bestMatch.point, id: bestMatch.id };
|
|
10030
|
+
},
|
|
10031
|
+
[snappingPointsWithScreen, transform]
|
|
10032
|
+
);
|
|
9729
10033
|
useEffect7(() => {
|
|
9730
10034
|
const container2 = containerRef.current;
|
|
9731
10035
|
const down = (e) => {
|
|
9732
10036
|
if (e.key === "d") {
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
|
|
10037
|
+
const snap = findSnap({
|
|
10038
|
+
x: mousePosRef.current.x,
|
|
10039
|
+
y: mousePosRef.current.y
|
|
10040
|
+
});
|
|
10041
|
+
setDStart({ x: snap.point.x, y: snap.point.y });
|
|
10042
|
+
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
10043
|
+
setActiveSnapIds({ start: snap.id, end: snap.id });
|
|
10044
|
+
if (dimensionToolVisible) {
|
|
10045
|
+
setDimensionToolVisible(false);
|
|
10046
|
+
setDimensionToolStretching(false);
|
|
10047
|
+
setActiveSnapIds({ start: null, end: null });
|
|
10048
|
+
} else {
|
|
10049
|
+
setDimensionToolVisible(true);
|
|
10050
|
+
setDimensionToolStretching(true);
|
|
10051
|
+
}
|
|
9737
10052
|
disarmMeasure();
|
|
9738
10053
|
}
|
|
9739
10054
|
if (e.key === "Escape") {
|
|
9740
10055
|
setDimensionToolVisible(false);
|
|
9741
10056
|
setDimensionToolStretching(false);
|
|
10057
|
+
setActiveSnapIds({ start: null, end: null });
|
|
9742
10058
|
disarmMeasure();
|
|
9743
10059
|
}
|
|
9744
10060
|
};
|
|
@@ -9772,7 +10088,7 @@ var DimensionOverlay = ({
|
|
|
9772
10088
|
container2.removeEventListener("mouseleave", removeKeyListener);
|
|
9773
10089
|
}
|
|
9774
10090
|
};
|
|
9775
|
-
}, [containerRef]);
|
|
10091
|
+
}, [containerRef, dimensionToolVisible, disarmMeasure, findSnap]);
|
|
9776
10092
|
const screenDStart = applyToPoint8(transform, dStart);
|
|
9777
10093
|
const screenDEnd = applyToPoint8(transform, dEnd);
|
|
9778
10094
|
const arrowScreenBounds = {
|
|
@@ -9811,7 +10127,9 @@ var DimensionOverlay = ({
|
|
|
9811
10127
|
mousePosRef.current.x = rwPoint.x;
|
|
9812
10128
|
mousePosRef.current.y = rwPoint.y;
|
|
9813
10129
|
if (dimensionToolStretching) {
|
|
9814
|
-
|
|
10130
|
+
const snap = findSnap(rwPoint);
|
|
10131
|
+
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
10132
|
+
setActiveSnapIds((prev) => ({ ...prev, end: snap.id }));
|
|
9815
10133
|
}
|
|
9816
10134
|
},
|
|
9817
10135
|
onMouseDown: (e) => {
|
|
@@ -9820,15 +10138,19 @@ var DimensionOverlay = ({
|
|
|
9820
10138
|
const y = e.clientY - rect.top;
|
|
9821
10139
|
const rwPoint = applyToPoint8(inverse2(transform), { x, y });
|
|
9822
10140
|
if (measureToolArmed && !dimensionToolVisible) {
|
|
9823
|
-
|
|
9824
|
-
|
|
10141
|
+
const snap = findSnap(rwPoint);
|
|
10142
|
+
setDStart({ x: snap.point.x, y: snap.point.y });
|
|
10143
|
+
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
10144
|
+
setActiveSnapIds({ start: snap.id, end: snap.id });
|
|
9825
10145
|
setDimensionToolVisible(true);
|
|
9826
10146
|
setDimensionToolStretching(true);
|
|
9827
10147
|
disarmMeasure();
|
|
9828
10148
|
} else if (dimensionToolStretching) {
|
|
9829
10149
|
setDimensionToolStretching(false);
|
|
10150
|
+
setActiveSnapIds((prev) => ({ ...prev, end: null }));
|
|
9830
10151
|
} else if (dimensionToolVisible) {
|
|
9831
10152
|
setDimensionToolVisible(false);
|
|
10153
|
+
setActiveSnapIds({ start: null, end: null });
|
|
9832
10154
|
}
|
|
9833
10155
|
},
|
|
9834
10156
|
children: [
|
|
@@ -9952,6 +10274,49 @@ var DimensionOverlay = ({
|
|
|
9952
10274
|
]
|
|
9953
10275
|
}
|
|
9954
10276
|
),
|
|
10277
|
+
dimensionToolStretching && snappingPointsWithScreen.map((snap) => {
|
|
10278
|
+
const isActive = snap.id === activeSnapIds.start || snap.id === activeSnapIds.end;
|
|
10279
|
+
const half = SNAP_MARKER_SIZE / 2;
|
|
10280
|
+
return /* @__PURE__ */ jsxs4(
|
|
10281
|
+
"svg",
|
|
10282
|
+
{
|
|
10283
|
+
width: SNAP_MARKER_SIZE,
|
|
10284
|
+
height: SNAP_MARKER_SIZE,
|
|
10285
|
+
style: {
|
|
10286
|
+
position: "absolute",
|
|
10287
|
+
left: snap.screenPoint.x - half,
|
|
10288
|
+
top: snap.screenPoint.y - half,
|
|
10289
|
+
pointerEvents: "none",
|
|
10290
|
+
zIndex: zIndexMap.dimensionOverlay
|
|
10291
|
+
},
|
|
10292
|
+
children: [
|
|
10293
|
+
/* @__PURE__ */ jsx6(
|
|
10294
|
+
"line",
|
|
10295
|
+
{
|
|
10296
|
+
x1: 0,
|
|
10297
|
+
y1: 0,
|
|
10298
|
+
x2: SNAP_MARKER_SIZE,
|
|
10299
|
+
y2: SNAP_MARKER_SIZE,
|
|
10300
|
+
stroke: isActive ? "#66ccff" : "white",
|
|
10301
|
+
strokeWidth: 1
|
|
10302
|
+
}
|
|
10303
|
+
),
|
|
10304
|
+
/* @__PURE__ */ jsx6(
|
|
10305
|
+
"line",
|
|
10306
|
+
{
|
|
10307
|
+
x1: SNAP_MARKER_SIZE,
|
|
10308
|
+
y1: 0,
|
|
10309
|
+
x2: 0,
|
|
10310
|
+
y2: SNAP_MARKER_SIZE,
|
|
10311
|
+
stroke: isActive ? "#66ccff" : "white",
|
|
10312
|
+
strokeWidth: 1
|
|
10313
|
+
}
|
|
10314
|
+
)
|
|
10315
|
+
]
|
|
10316
|
+
},
|
|
10317
|
+
snap.id
|
|
10318
|
+
);
|
|
10319
|
+
}),
|
|
9955
10320
|
/* @__PURE__ */ jsxs4(
|
|
9956
10321
|
"div",
|
|
9957
10322
|
{
|
|
@@ -11055,7 +11420,7 @@ var ErrorOverlay = ({
|
|
|
11055
11420
|
};
|
|
11056
11421
|
|
|
11057
11422
|
// src/components/MouseElementTracker.tsx
|
|
11058
|
-
import { useState as useState7, useMemo as
|
|
11423
|
+
import { useState as useState7, useMemo as useMemo4 } from "react";
|
|
11059
11424
|
import { applyToPoint as applyToPoint12, inverse as inverse5 } from "transformation-matrix";
|
|
11060
11425
|
|
|
11061
11426
|
// src/components/ElementOverlayBox.tsx
|
|
@@ -11472,7 +11837,7 @@ var MouseElementTracker = ({
|
|
|
11472
11837
|
}) => {
|
|
11473
11838
|
const [mousedPrimitives, setMousedPrimitives] = useState7([]);
|
|
11474
11839
|
const [mousePos, setMousePos] = useState7({ x: 0, y: 0 });
|
|
11475
|
-
const highlightedPrimitives =
|
|
11840
|
+
const highlightedPrimitives = useMemo4(() => {
|
|
11476
11841
|
const highlightedPrimitives2 = [];
|
|
11477
11842
|
for (const primitive of mousedPrimitives) {
|
|
11478
11843
|
if (primitive._element?.type === "pcb_via") continue;
|
|
@@ -11836,15 +12201,15 @@ var PcbGroupOverlay = ({
|
|
|
11836
12201
|
|
|
11837
12202
|
// src/components/RatsNestOverlay.tsx
|
|
11838
12203
|
import { applyToPoint as applyToPoint14, identity as identity9 } from "transformation-matrix";
|
|
11839
|
-
import { useMemo as
|
|
12204
|
+
import { useMemo as useMemo5 } from "react";
|
|
11840
12205
|
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
11841
12206
|
var RatsNestOverlay = ({ transform, soup, children }) => {
|
|
11842
12207
|
const isShowingRatsNest = useGlobalStore((s) => s.is_showing_rats_nest);
|
|
11843
|
-
const { netMap, idToNetMap } =
|
|
12208
|
+
const { netMap, idToNetMap } = useMemo5(
|
|
11844
12209
|
() => getFullConnectivityMapFromCircuitJson(soup || []),
|
|
11845
12210
|
[soup]
|
|
11846
12211
|
);
|
|
11847
|
-
const ratsNestLines =
|
|
12212
|
+
const ratsNestLines = useMemo5(() => {
|
|
11848
12213
|
if (!soup || !isShowingRatsNest) return [];
|
|
11849
12214
|
const getElementPosition = (id) => {
|
|
11850
12215
|
const element = su(soup)[id.replace(/_\d+$/, "")].get(id);
|
|
@@ -11941,7 +12306,7 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
|
|
|
11941
12306
|
import {
|
|
11942
12307
|
useEffect as useEffect15,
|
|
11943
12308
|
useState as useState9,
|
|
11944
|
-
useCallback as
|
|
12309
|
+
useCallback as useCallback4,
|
|
11945
12310
|
useRef as useRef10
|
|
11946
12311
|
} from "react";
|
|
11947
12312
|
import { css as css3 } from "@emotion/css";
|
|
@@ -11949,7 +12314,7 @@ import { css as css3 } from "@emotion/css";
|
|
|
11949
12314
|
// package.json
|
|
11950
12315
|
var package_default = {
|
|
11951
12316
|
name: "@tscircuit/pcb-viewer",
|
|
11952
|
-
version: "1.11.
|
|
12317
|
+
version: "1.11.239",
|
|
11953
12318
|
main: "dist/index.js",
|
|
11954
12319
|
type: "module",
|
|
11955
12320
|
repository: "tscircuit/pcb-viewer",
|
|
@@ -12001,7 +12366,7 @@ var package_default = {
|
|
|
12001
12366
|
"@emotion/css": "^11.11.2",
|
|
12002
12367
|
"@tscircuit/alphabet": "^0.0.3",
|
|
12003
12368
|
"@vitejs/plugin-react": "^5.0.2",
|
|
12004
|
-
"circuit-json": "^0.0.
|
|
12369
|
+
"circuit-json": "^0.0.295",
|
|
12005
12370
|
"circuit-to-svg": "^0.0.240",
|
|
12006
12371
|
color: "^4.2.3",
|
|
12007
12372
|
"react-supergrid": "^1.0.10",
|
|
@@ -12294,20 +12659,20 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
12294
12659
|
useHotKey("6", hotKeyCallbacks["6"]);
|
|
12295
12660
|
useHotKey("7", hotKeyCallbacks["7"]);
|
|
12296
12661
|
useHotKey("8", hotKeyCallbacks["8"]);
|
|
12297
|
-
const handleMouseEnter =
|
|
12662
|
+
const handleMouseEnter = useCallback4(() => {
|
|
12298
12663
|
setIsMouseOverContainer(true);
|
|
12299
12664
|
}, [setIsMouseOverContainer]);
|
|
12300
|
-
const handleMouseLeave =
|
|
12665
|
+
const handleMouseLeave = useCallback4(() => {
|
|
12301
12666
|
setIsMouseOverContainer(false);
|
|
12302
12667
|
setLayerMenuOpen(false);
|
|
12303
12668
|
setViewMenuOpen(false);
|
|
12304
12669
|
setErrorsOpen(false);
|
|
12305
12670
|
setHoveredErrorId(null);
|
|
12306
12671
|
}, [setIsMouseOverContainer, setHoveredErrorId]);
|
|
12307
|
-
const handleLayerMenuToggle =
|
|
12672
|
+
const handleLayerMenuToggle = useCallback4(() => {
|
|
12308
12673
|
setLayerMenuOpen(!isLayerMenuOpen);
|
|
12309
12674
|
}, [isLayerMenuOpen]);
|
|
12310
|
-
const handleErrorsToggle =
|
|
12675
|
+
const handleErrorsToggle = useCallback4(() => {
|
|
12311
12676
|
const newErrorsOpen = !isErrorsOpen;
|
|
12312
12677
|
setErrorsOpen(newErrorsOpen);
|
|
12313
12678
|
if (newErrorsOpen) {
|
|
@@ -12317,20 +12682,20 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
12317
12682
|
setHoveredErrorId(null);
|
|
12318
12683
|
}
|
|
12319
12684
|
}, [isErrorsOpen, setHoveredErrorId]);
|
|
12320
|
-
const handleEditTraceToggle =
|
|
12685
|
+
const handleEditTraceToggle = useCallback4(() => {
|
|
12321
12686
|
setEditMode(editModes.in_draw_trace_mode ? "off" : "draw_trace");
|
|
12322
12687
|
}, [editModes.in_draw_trace_mode, setEditMode]);
|
|
12323
|
-
const handleMoveComponentToggle =
|
|
12688
|
+
const handleMoveComponentToggle = useCallback4(() => {
|
|
12324
12689
|
setEditMode(editModes.in_move_footprint_mode ? "off" : "move_footprint");
|
|
12325
12690
|
}, [editModes.in_move_footprint_mode, setEditMode]);
|
|
12326
|
-
const handleRatsNestToggle =
|
|
12691
|
+
const handleRatsNestToggle = useCallback4(() => {
|
|
12327
12692
|
setIsShowingRatsNest(!viewSettings.is_showing_rats_nest);
|
|
12328
12693
|
}, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest]);
|
|
12329
|
-
const handleMeasureToolClick =
|
|
12694
|
+
const handleMeasureToolClick = useCallback4(() => {
|
|
12330
12695
|
setMeasureToolArmed(true);
|
|
12331
12696
|
window.dispatchEvent(new Event("arm-dimension-tool"));
|
|
12332
12697
|
}, []);
|
|
12333
|
-
const handleViewMenuToggle =
|
|
12698
|
+
const handleViewMenuToggle = useCallback4(() => {
|
|
12334
12699
|
const newViewMenuOpen = !isViewMenuOpen;
|
|
12335
12700
|
setViewMenuOpen(newViewMenuOpen);
|
|
12336
12701
|
if (newViewMenuOpen) {
|
|
@@ -12765,7 +13130,7 @@ import { jsx as jsx16 } from "react/jsx-runtime";
|
|
|
12765
13130
|
var CanvasElementsRenderer = (props) => {
|
|
12766
13131
|
const { transform, elements } = props;
|
|
12767
13132
|
const hoveredErrorId = useGlobalStore((state) => state.hovered_error_id);
|
|
12768
|
-
const [primitivesWithoutInteractionMetadata, connectivityMap] =
|
|
13133
|
+
const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo6(() => {
|
|
12769
13134
|
const primitivesWithoutInteractionMetadata2 = props.elements.flatMap(
|
|
12770
13135
|
(elm) => convertElementToPrimitives(elm, props.elements)
|
|
12771
13136
|
);
|
|
@@ -12778,7 +13143,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12778
13143
|
drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
|
|
12779
13144
|
primitiveIdsInMousedOverNet: []
|
|
12780
13145
|
});
|
|
12781
|
-
const errorRelatedIds =
|
|
13146
|
+
const errorRelatedIds = useMemo6(() => {
|
|
12782
13147
|
if (!hoveredErrorId) return [];
|
|
12783
13148
|
const errorElements = elements.filter(
|
|
12784
13149
|
(el) => el.type.includes("error")
|
|
@@ -12797,7 +13162,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12797
13162
|
}
|
|
12798
13163
|
return relatedIds;
|
|
12799
13164
|
}, [hoveredErrorId, elements]);
|
|
12800
|
-
const primitives =
|
|
13165
|
+
const primitives = useMemo6(() => {
|
|
12801
13166
|
const combinedPrimitiveIds = [
|
|
12802
13167
|
...hoverState.primitiveIdsInMousedOverNet,
|
|
12803
13168
|
...errorRelatedIds
|
|
@@ -12808,7 +13173,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12808
13173
|
primitiveIdsInMousedOverNet: combinedPrimitiveIds
|
|
12809
13174
|
});
|
|
12810
13175
|
}, [primitivesWithoutInteractionMetadata, hoverState, errorRelatedIds]);
|
|
12811
|
-
const onMouseOverPrimitives =
|
|
13176
|
+
const onMouseOverPrimitives = useCallback5(
|
|
12812
13177
|
(primitivesHoveredOver) => {
|
|
12813
13178
|
const primitiveIdsInMousedOverNet = [];
|
|
12814
13179
|
for (const primitive of primitivesHoveredOver) {
|
|
@@ -12861,6 +13226,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12861
13226
|
{
|
|
12862
13227
|
transform,
|
|
12863
13228
|
focusOnHover: props.focusOnHover,
|
|
13229
|
+
primitives: primitivesWithoutInteractionMetadata,
|
|
12864
13230
|
children: /* @__PURE__ */ jsx16(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx16(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx16(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx16(PcbGroupOverlay, { transform, elements, children: /* @__PURE__ */ jsx16(
|
|
12865
13231
|
DebugGraphicsOverlay,
|
|
12866
13232
|
{
|
|
@@ -12970,7 +13336,7 @@ var PCBViewer = ({
|
|
|
12970
13336
|
editEvents = editEventsProp ?? editEvents;
|
|
12971
13337
|
const initialRenderCompleted = useRef11(false);
|
|
12972
13338
|
const touchStartRef = useRef11(null);
|
|
12973
|
-
const circuitJsonKey =
|
|
13339
|
+
const circuitJsonKey = useMemo7(
|
|
12974
13340
|
() => calculateCircuitJsonKey(circuitJson),
|
|
12975
13341
|
[circuitJson]
|
|
12976
13342
|
);
|
|
@@ -13003,12 +13369,12 @@ var PCBViewer = ({
|
|
|
13003
13369
|
initialRenderCompleted.current = true;
|
|
13004
13370
|
}
|
|
13005
13371
|
}, [circuitJson, refDimensions]);
|
|
13006
|
-
const pcbElmsPreEdit =
|
|
13372
|
+
const pcbElmsPreEdit = useMemo7(() => {
|
|
13007
13373
|
return circuitJson?.filter(
|
|
13008
13374
|
(e) => e.type.startsWith("pcb_") || e.type.startsWith("source_")
|
|
13009
13375
|
) ?? [];
|
|
13010
13376
|
}, [circuitJsonKey]);
|
|
13011
|
-
const elements =
|
|
13377
|
+
const elements = useMemo7(() => {
|
|
13012
13378
|
return applyEditEvents({
|
|
13013
13379
|
circuitJson: pcbElmsPreEdit,
|
|
13014
13380
|
editEvents
|
|
@@ -13025,7 +13391,7 @@ var PCBViewer = ({
|
|
|
13025
13391
|
setEditEvents(newEditEvents);
|
|
13026
13392
|
onEditEventsChanged?.(newEditEvents);
|
|
13027
13393
|
};
|
|
13028
|
-
const mergedInitialState =
|
|
13394
|
+
const mergedInitialState = useMemo7(
|
|
13029
13395
|
() => ({
|
|
13030
13396
|
...initialState,
|
|
13031
13397
|
...disablePcbGroups && { is_showing_pcb_groups: false }
|