@tscircuit/pcb-viewer 1.11.237 → 1.11.239
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 +360 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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) {
|
|
@@ -8394,6 +8394,7 @@ var zIndexMap = {
|
|
|
8394
8394
|
};
|
|
8395
8395
|
|
|
8396
8396
|
// src/lib/Drawer.ts
|
|
8397
|
+
import colorParser from "color";
|
|
8397
8398
|
var LAYER_NAME_TO_COLOR = {
|
|
8398
8399
|
// Standard colors, you shouldn't use these except for testing
|
|
8399
8400
|
red: "red",
|
|
@@ -8762,11 +8763,14 @@ var Drawer = class {
|
|
|
8762
8763
|
ctx.lineCap = "round";
|
|
8763
8764
|
if (mode === "add") {
|
|
8764
8765
|
ctx.globalCompositeOperation = "source-over";
|
|
8765
|
-
let colorString =
|
|
8766
|
-
if (colorString
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8766
|
+
let colorString = LAYER_NAME_TO_COLOR[color2.toLowerCase()];
|
|
8767
|
+
if (!colorString)
|
|
8768
|
+
try {
|
|
8769
|
+
colorString = colorParser(color2).rgb().toString();
|
|
8770
|
+
} catch (error) {
|
|
8771
|
+
console.warn(`Invalid color format: '${color2}'`);
|
|
8772
|
+
colorString = "white";
|
|
8773
|
+
}
|
|
8770
8774
|
ctx.fillStyle = colorString;
|
|
8771
8775
|
ctx.strokeStyle = colorString;
|
|
8772
8776
|
} else {
|
|
@@ -9698,43 +9702,306 @@ var WarningGraphicsOverlay = ({
|
|
|
9698
9702
|
};
|
|
9699
9703
|
|
|
9700
9704
|
// src/components/DimensionOverlay.tsx
|
|
9701
|
-
import { useEffect as useEffect7, useRef as useRef5, useState as useState3 } from "react";
|
|
9705
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef5, useState as useState3 } from "react";
|
|
9702
9706
|
import { applyToPoint as applyToPoint8, identity as identity4, inverse as inverse2 } from "transformation-matrix";
|
|
9707
|
+
|
|
9708
|
+
// src/lib/util/get-primitive-bounding-box.ts
|
|
9709
|
+
var mergeNumber = (a, b, fn) => fn(a, b);
|
|
9710
|
+
var rotatePoint = (x, y, centerX, centerY, rotationDeg) => {
|
|
9711
|
+
const radians = rotationDeg * Math.PI / 180;
|
|
9712
|
+
const cos = Math.cos(radians);
|
|
9713
|
+
const sin = Math.sin(radians);
|
|
9714
|
+
const translatedX = x - centerX;
|
|
9715
|
+
const translatedY = y - centerY;
|
|
9716
|
+
const rotatedX = translatedX * cos - translatedY * sin;
|
|
9717
|
+
const rotatedY = translatedX * sin + translatedY * cos;
|
|
9718
|
+
return {
|
|
9719
|
+
x: rotatedX + centerX,
|
|
9720
|
+
y: rotatedY + centerY
|
|
9721
|
+
};
|
|
9722
|
+
};
|
|
9723
|
+
var createBoxFromPoints = (points) => {
|
|
9724
|
+
if (points.length === 0) return null;
|
|
9725
|
+
let minX = points[0].x;
|
|
9726
|
+
let maxX = points[0].x;
|
|
9727
|
+
let minY = points[0].y;
|
|
9728
|
+
let maxY = points[0].y;
|
|
9729
|
+
for (const point of points) {
|
|
9730
|
+
minX = mergeNumber(minX, point.x, Math.min);
|
|
9731
|
+
maxX = mergeNumber(maxX, point.x, Math.max);
|
|
9732
|
+
minY = mergeNumber(minY, point.y, Math.min);
|
|
9733
|
+
maxY = mergeNumber(maxY, point.y, Math.max);
|
|
9734
|
+
}
|
|
9735
|
+
return { minX, maxX, minY, maxY };
|
|
9736
|
+
};
|
|
9737
|
+
var mergeBoundingBoxesInternal = (a, b) => ({
|
|
9738
|
+
minX: Math.min(a.minX, b.minX),
|
|
9739
|
+
maxX: Math.max(a.maxX, b.maxX),
|
|
9740
|
+
minY: Math.min(a.minY, b.minY),
|
|
9741
|
+
maxY: Math.max(a.maxY, b.maxY)
|
|
9742
|
+
});
|
|
9743
|
+
var mergeBoundingBoxes = (existing, next) => {
|
|
9744
|
+
if (!existing) return next;
|
|
9745
|
+
return mergeBoundingBoxesInternal(existing, next);
|
|
9746
|
+
};
|
|
9747
|
+
var getPrimitiveBoundingBox = (primitive) => {
|
|
9748
|
+
switch (primitive.pcb_drawing_type) {
|
|
9749
|
+
case "line": {
|
|
9750
|
+
const halfWidth = (primitive.width ?? 0) / 2;
|
|
9751
|
+
const points = [
|
|
9752
|
+
{ x: primitive.x1, y: primitive.y1 },
|
|
9753
|
+
{ x: primitive.x2, y: primitive.y2 }
|
|
9754
|
+
];
|
|
9755
|
+
const baseBox = createBoxFromPoints(points);
|
|
9756
|
+
if (!baseBox) return null;
|
|
9757
|
+
return {
|
|
9758
|
+
minX: baseBox.minX - halfWidth,
|
|
9759
|
+
maxX: baseBox.maxX + halfWidth,
|
|
9760
|
+
minY: baseBox.minY - halfWidth,
|
|
9761
|
+
maxY: baseBox.maxY + halfWidth
|
|
9762
|
+
};
|
|
9763
|
+
}
|
|
9764
|
+
case "rect": {
|
|
9765
|
+
const halfW = primitive.w / 2;
|
|
9766
|
+
const halfH = primitive.h / 2;
|
|
9767
|
+
const corners = [
|
|
9768
|
+
{ x: primitive.x - halfW, y: primitive.y - halfH },
|
|
9769
|
+
{ x: primitive.x + halfW, y: primitive.y - halfH },
|
|
9770
|
+
{ x: primitive.x + halfW, y: primitive.y + halfH },
|
|
9771
|
+
{ x: primitive.x - halfW, y: primitive.y + halfH }
|
|
9772
|
+
];
|
|
9773
|
+
const rotation = primitive.ccw_rotation ?? 0;
|
|
9774
|
+
const rotatedCorners = rotation === 0 ? corners : corners.map(
|
|
9775
|
+
(corner) => rotatePoint(
|
|
9776
|
+
corner.x,
|
|
9777
|
+
corner.y,
|
|
9778
|
+
primitive.x,
|
|
9779
|
+
primitive.y,
|
|
9780
|
+
rotation
|
|
9781
|
+
)
|
|
9782
|
+
);
|
|
9783
|
+
return createBoxFromPoints(rotatedCorners);
|
|
9784
|
+
}
|
|
9785
|
+
case "circle": {
|
|
9786
|
+
return {
|
|
9787
|
+
minX: primitive.x - primitive.r,
|
|
9788
|
+
maxX: primitive.x + primitive.r,
|
|
9789
|
+
minY: primitive.y - primitive.r,
|
|
9790
|
+
maxY: primitive.y + primitive.r
|
|
9791
|
+
};
|
|
9792
|
+
}
|
|
9793
|
+
case "oval": {
|
|
9794
|
+
return {
|
|
9795
|
+
minX: primitive.x - primitive.rX,
|
|
9796
|
+
maxX: primitive.x + primitive.rX,
|
|
9797
|
+
minY: primitive.y - primitive.rY,
|
|
9798
|
+
maxY: primitive.y + primitive.rY
|
|
9799
|
+
};
|
|
9800
|
+
}
|
|
9801
|
+
case "pill": {
|
|
9802
|
+
const halfW = primitive.w / 2;
|
|
9803
|
+
const halfH = primitive.h / 2;
|
|
9804
|
+
const corners = [
|
|
9805
|
+
{ x: primitive.x - halfW, y: primitive.y - halfH },
|
|
9806
|
+
{ x: primitive.x + halfW, y: primitive.y - halfH },
|
|
9807
|
+
{ x: primitive.x + halfW, y: primitive.y + halfH },
|
|
9808
|
+
{ x: primitive.x - halfW, y: primitive.y + halfH }
|
|
9809
|
+
];
|
|
9810
|
+
const rotation = primitive.ccw_rotation ?? 0;
|
|
9811
|
+
const rotatedCorners = rotation === 0 ? corners : corners.map(
|
|
9812
|
+
(corner) => rotatePoint(
|
|
9813
|
+
corner.x,
|
|
9814
|
+
corner.y,
|
|
9815
|
+
primitive.x,
|
|
9816
|
+
primitive.y,
|
|
9817
|
+
rotation
|
|
9818
|
+
)
|
|
9819
|
+
);
|
|
9820
|
+
return createBoxFromPoints(rotatedCorners);
|
|
9821
|
+
}
|
|
9822
|
+
case "polygon": {
|
|
9823
|
+
return createBoxFromPoints(primitive.points);
|
|
9824
|
+
}
|
|
9825
|
+
case "polygon_with_arcs": {
|
|
9826
|
+
const points = primitive.brep_shape.outer_ring.vertices.map((vertex) => ({
|
|
9827
|
+
x: vertex.x,
|
|
9828
|
+
y: vertex.y
|
|
9829
|
+
}));
|
|
9830
|
+
return createBoxFromPoints(points);
|
|
9831
|
+
}
|
|
9832
|
+
case "text": {
|
|
9833
|
+
const size = primitive.size ?? 0;
|
|
9834
|
+
const width = primitive.text ? primitive.text.length * size * 0.6 : 0;
|
|
9835
|
+
const height = size;
|
|
9836
|
+
if (width === 0 && height === 0) {
|
|
9837
|
+
return {
|
|
9838
|
+
minX: primitive.x,
|
|
9839
|
+
maxX: primitive.x,
|
|
9840
|
+
minY: primitive.y,
|
|
9841
|
+
maxY: primitive.y
|
|
9842
|
+
};
|
|
9843
|
+
}
|
|
9844
|
+
const halfW = width / 2;
|
|
9845
|
+
const halfH = height / 2;
|
|
9846
|
+
return {
|
|
9847
|
+
minX: primitive.x - halfW,
|
|
9848
|
+
maxX: primitive.x + halfW,
|
|
9849
|
+
minY: primitive.y - halfH,
|
|
9850
|
+
maxY: primitive.y + halfH
|
|
9851
|
+
};
|
|
9852
|
+
}
|
|
9853
|
+
default:
|
|
9854
|
+
return null;
|
|
9855
|
+
}
|
|
9856
|
+
};
|
|
9857
|
+
|
|
9858
|
+
// src/components/DimensionOverlay.tsx
|
|
9703
9859
|
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9860
|
+
var SNAP_THRESHOLD_PX = 16;
|
|
9861
|
+
var SNAP_MARKER_SIZE = 5;
|
|
9862
|
+
var shouldExcludePrimitiveFromSnapping = (primitive) => {
|
|
9863
|
+
if (primitive.pcb_drawing_type === "text") return true;
|
|
9864
|
+
const element = primitive._element;
|
|
9865
|
+
if (!element || typeof element !== "object") {
|
|
9866
|
+
return false;
|
|
9867
|
+
}
|
|
9868
|
+
const elementType = typeof element.type === "string" ? element.type : void 0;
|
|
9869
|
+
if (!elementType) return false;
|
|
9870
|
+
if (elementType.startsWith("pcb_silkscreen_")) return true;
|
|
9871
|
+
if (elementType.startsWith("pcb_note_")) return true;
|
|
9872
|
+
if (elementType === "pcb_text") return true;
|
|
9873
|
+
if (elementType.startsWith("pcb_fabrication_note_") && elementType !== "pcb_fabrication_note_rect") {
|
|
9874
|
+
return true;
|
|
9875
|
+
}
|
|
9876
|
+
return false;
|
|
9877
|
+
};
|
|
9704
9878
|
var DimensionOverlay = ({
|
|
9705
9879
|
children,
|
|
9706
9880
|
transform,
|
|
9707
|
-
focusOnHover = false
|
|
9881
|
+
focusOnHover = false,
|
|
9882
|
+
primitives = []
|
|
9708
9883
|
}) => {
|
|
9709
9884
|
if (!transform) transform = identity4();
|
|
9710
9885
|
const [dimensionToolVisible, setDimensionToolVisible] = useState3(false);
|
|
9711
9886
|
const [dimensionToolStretching, setDimensionToolStretching] = useState3(false);
|
|
9712
9887
|
const [measureToolArmed, setMeasureToolArmed] = useState3(false);
|
|
9713
|
-
const
|
|
9888
|
+
const [activeSnapIds, setActiveSnapIds] = useState3({
|
|
9889
|
+
start: null,
|
|
9890
|
+
end: null
|
|
9891
|
+
});
|
|
9892
|
+
const disarmMeasure = useCallback3(() => {
|
|
9714
9893
|
if (measureToolArmed) {
|
|
9715
9894
|
setMeasureToolArmed(false);
|
|
9716
9895
|
window.dispatchEvent(new Event("disarm-dimension-tool"));
|
|
9717
9896
|
}
|
|
9718
|
-
};
|
|
9897
|
+
}, [measureToolArmed]);
|
|
9719
9898
|
const [dStart, setDStart] = useState3({ x: 0, y: 0 });
|
|
9720
9899
|
const [dEnd, setDEnd] = useState3({ x: 0, y: 0 });
|
|
9721
9900
|
const mousePosRef = useRef5({ x: 0, y: 0 });
|
|
9722
9901
|
const containerRef = useRef5(null);
|
|
9723
9902
|
const container = containerRef.current;
|
|
9724
9903
|
const containerBounds = container?.getBoundingClientRect();
|
|
9904
|
+
const elementBoundingBoxes = useMemo3(() => {
|
|
9905
|
+
const boundingBoxes = /* @__PURE__ */ new Map();
|
|
9906
|
+
for (const primitive of primitives) {
|
|
9907
|
+
if (!primitive._element) continue;
|
|
9908
|
+
if (shouldExcludePrimitiveFromSnapping(primitive)) continue;
|
|
9909
|
+
const bbox = getPrimitiveBoundingBox(primitive);
|
|
9910
|
+
if (!bbox) continue;
|
|
9911
|
+
const existing = boundingBoxes.get(primitive._element);
|
|
9912
|
+
boundingBoxes.set(
|
|
9913
|
+
primitive._element,
|
|
9914
|
+
mergeBoundingBoxes(existing ?? void 0, bbox)
|
|
9915
|
+
);
|
|
9916
|
+
}
|
|
9917
|
+
return boundingBoxes;
|
|
9918
|
+
}, [primitives]);
|
|
9919
|
+
const snappingPoints = useMemo3(() => {
|
|
9920
|
+
const points = [];
|
|
9921
|
+
elementBoundingBoxes.forEach((bounds, element) => {
|
|
9922
|
+
if (!bounds) return;
|
|
9923
|
+
const centerX = (bounds.minX + bounds.maxX) / 2;
|
|
9924
|
+
const centerY = (bounds.minY + bounds.maxY) / 2;
|
|
9925
|
+
const anchorPoints = {
|
|
9926
|
+
top_left: { x: bounds.minX, y: bounds.minY },
|
|
9927
|
+
top_center: { x: centerX, y: bounds.minY },
|
|
9928
|
+
top_right: { x: bounds.maxX, y: bounds.minY },
|
|
9929
|
+
center_left: { x: bounds.minX, y: centerY },
|
|
9930
|
+
center: { x: centerX, y: centerY },
|
|
9931
|
+
center_right: { x: bounds.maxX, y: centerY },
|
|
9932
|
+
bottom_left: { x: bounds.minX, y: bounds.maxY },
|
|
9933
|
+
bottom_center: { x: centerX, y: bounds.maxY },
|
|
9934
|
+
bottom_right: { x: bounds.maxX, y: bounds.maxY }
|
|
9935
|
+
};
|
|
9936
|
+
for (const [anchor, point] of Object.entries(anchorPoints)) {
|
|
9937
|
+
points.push({
|
|
9938
|
+
anchor,
|
|
9939
|
+
point,
|
|
9940
|
+
element
|
|
9941
|
+
});
|
|
9942
|
+
}
|
|
9943
|
+
});
|
|
9944
|
+
return points;
|
|
9945
|
+
}, [elementBoundingBoxes]);
|
|
9946
|
+
const snappingPointsWithScreen = useMemo3(() => {
|
|
9947
|
+
return snappingPoints.map((snap, index) => ({
|
|
9948
|
+
...snap,
|
|
9949
|
+
id: `${index}-${snap.anchor}`,
|
|
9950
|
+
screenPoint: applyToPoint8(transform, snap.point)
|
|
9951
|
+
}));
|
|
9952
|
+
}, [snappingPoints, transform]);
|
|
9953
|
+
const findSnap = useCallback3(
|
|
9954
|
+
(rwPoint) => {
|
|
9955
|
+
if (snappingPointsWithScreen.length === 0) {
|
|
9956
|
+
return { point: rwPoint, id: null };
|
|
9957
|
+
}
|
|
9958
|
+
const screenPoint = applyToPoint8(transform, rwPoint);
|
|
9959
|
+
let bestMatch = null;
|
|
9960
|
+
for (const snap of snappingPointsWithScreen) {
|
|
9961
|
+
const dx = snap.screenPoint.x - screenPoint.x;
|
|
9962
|
+
const dy = snap.screenPoint.y - screenPoint.y;
|
|
9963
|
+
const distance5 = Math.hypot(dx, dy);
|
|
9964
|
+
if (distance5 > SNAP_THRESHOLD_PX) continue;
|
|
9965
|
+
if (!bestMatch || distance5 < bestMatch.distance) {
|
|
9966
|
+
bestMatch = {
|
|
9967
|
+
distance: distance5,
|
|
9968
|
+
id: snap.id,
|
|
9969
|
+
point: snap.point
|
|
9970
|
+
};
|
|
9971
|
+
}
|
|
9972
|
+
}
|
|
9973
|
+
if (!bestMatch) {
|
|
9974
|
+
return { point: rwPoint, id: null };
|
|
9975
|
+
}
|
|
9976
|
+
return { point: bestMatch.point, id: bestMatch.id };
|
|
9977
|
+
},
|
|
9978
|
+
[snappingPointsWithScreen, transform]
|
|
9979
|
+
);
|
|
9725
9980
|
useEffect7(() => {
|
|
9726
9981
|
const container2 = containerRef.current;
|
|
9727
9982
|
const down = (e) => {
|
|
9728
9983
|
if (e.key === "d") {
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
|
|
9984
|
+
const snap = findSnap({
|
|
9985
|
+
x: mousePosRef.current.x,
|
|
9986
|
+
y: mousePosRef.current.y
|
|
9987
|
+
});
|
|
9988
|
+
setDStart({ x: snap.point.x, y: snap.point.y });
|
|
9989
|
+
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
9990
|
+
setActiveSnapIds({ start: snap.id, end: snap.id });
|
|
9991
|
+
if (dimensionToolVisible) {
|
|
9992
|
+
setDimensionToolVisible(false);
|
|
9993
|
+
setDimensionToolStretching(false);
|
|
9994
|
+
setActiveSnapIds({ start: null, end: null });
|
|
9995
|
+
} else {
|
|
9996
|
+
setDimensionToolVisible(true);
|
|
9997
|
+
setDimensionToolStretching(true);
|
|
9998
|
+
}
|
|
9733
9999
|
disarmMeasure();
|
|
9734
10000
|
}
|
|
9735
10001
|
if (e.key === "Escape") {
|
|
9736
10002
|
setDimensionToolVisible(false);
|
|
9737
10003
|
setDimensionToolStretching(false);
|
|
10004
|
+
setActiveSnapIds({ start: null, end: null });
|
|
9738
10005
|
disarmMeasure();
|
|
9739
10006
|
}
|
|
9740
10007
|
};
|
|
@@ -9768,7 +10035,7 @@ var DimensionOverlay = ({
|
|
|
9768
10035
|
container2.removeEventListener("mouseleave", removeKeyListener);
|
|
9769
10036
|
}
|
|
9770
10037
|
};
|
|
9771
|
-
}, [containerRef]);
|
|
10038
|
+
}, [containerRef, dimensionToolVisible, disarmMeasure, findSnap]);
|
|
9772
10039
|
const screenDStart = applyToPoint8(transform, dStart);
|
|
9773
10040
|
const screenDEnd = applyToPoint8(transform, dEnd);
|
|
9774
10041
|
const arrowScreenBounds = {
|
|
@@ -9807,7 +10074,9 @@ var DimensionOverlay = ({
|
|
|
9807
10074
|
mousePosRef.current.x = rwPoint.x;
|
|
9808
10075
|
mousePosRef.current.y = rwPoint.y;
|
|
9809
10076
|
if (dimensionToolStretching) {
|
|
9810
|
-
|
|
10077
|
+
const snap = findSnap(rwPoint);
|
|
10078
|
+
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
10079
|
+
setActiveSnapIds((prev) => ({ ...prev, end: snap.id }));
|
|
9811
10080
|
}
|
|
9812
10081
|
},
|
|
9813
10082
|
onMouseDown: (e) => {
|
|
@@ -9816,15 +10085,19 @@ var DimensionOverlay = ({
|
|
|
9816
10085
|
const y = e.clientY - rect.top;
|
|
9817
10086
|
const rwPoint = applyToPoint8(inverse2(transform), { x, y });
|
|
9818
10087
|
if (measureToolArmed && !dimensionToolVisible) {
|
|
9819
|
-
|
|
9820
|
-
|
|
10088
|
+
const snap = findSnap(rwPoint);
|
|
10089
|
+
setDStart({ x: snap.point.x, y: snap.point.y });
|
|
10090
|
+
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
10091
|
+
setActiveSnapIds({ start: snap.id, end: snap.id });
|
|
9821
10092
|
setDimensionToolVisible(true);
|
|
9822
10093
|
setDimensionToolStretching(true);
|
|
9823
10094
|
disarmMeasure();
|
|
9824
10095
|
} else if (dimensionToolStretching) {
|
|
9825
10096
|
setDimensionToolStretching(false);
|
|
10097
|
+
setActiveSnapIds((prev) => ({ ...prev, end: null }));
|
|
9826
10098
|
} else if (dimensionToolVisible) {
|
|
9827
10099
|
setDimensionToolVisible(false);
|
|
10100
|
+
setActiveSnapIds({ start: null, end: null });
|
|
9828
10101
|
}
|
|
9829
10102
|
},
|
|
9830
10103
|
children: [
|
|
@@ -9948,6 +10221,49 @@ var DimensionOverlay = ({
|
|
|
9948
10221
|
]
|
|
9949
10222
|
}
|
|
9950
10223
|
),
|
|
10224
|
+
dimensionToolStretching && snappingPointsWithScreen.map((snap) => {
|
|
10225
|
+
const isActive = snap.id === activeSnapIds.start || snap.id === activeSnapIds.end;
|
|
10226
|
+
const half = SNAP_MARKER_SIZE / 2;
|
|
10227
|
+
return /* @__PURE__ */ jsxs4(
|
|
10228
|
+
"svg",
|
|
10229
|
+
{
|
|
10230
|
+
width: SNAP_MARKER_SIZE,
|
|
10231
|
+
height: SNAP_MARKER_SIZE,
|
|
10232
|
+
style: {
|
|
10233
|
+
position: "absolute",
|
|
10234
|
+
left: snap.screenPoint.x - half,
|
|
10235
|
+
top: snap.screenPoint.y - half,
|
|
10236
|
+
pointerEvents: "none",
|
|
10237
|
+
zIndex: zIndexMap.dimensionOverlay
|
|
10238
|
+
},
|
|
10239
|
+
children: [
|
|
10240
|
+
/* @__PURE__ */ jsx6(
|
|
10241
|
+
"line",
|
|
10242
|
+
{
|
|
10243
|
+
x1: 0,
|
|
10244
|
+
y1: 0,
|
|
10245
|
+
x2: SNAP_MARKER_SIZE,
|
|
10246
|
+
y2: SNAP_MARKER_SIZE,
|
|
10247
|
+
stroke: isActive ? "#66ccff" : "white",
|
|
10248
|
+
strokeWidth: 1
|
|
10249
|
+
}
|
|
10250
|
+
),
|
|
10251
|
+
/* @__PURE__ */ jsx6(
|
|
10252
|
+
"line",
|
|
10253
|
+
{
|
|
10254
|
+
x1: SNAP_MARKER_SIZE,
|
|
10255
|
+
y1: 0,
|
|
10256
|
+
x2: 0,
|
|
10257
|
+
y2: SNAP_MARKER_SIZE,
|
|
10258
|
+
stroke: isActive ? "#66ccff" : "white",
|
|
10259
|
+
strokeWidth: 1
|
|
10260
|
+
}
|
|
10261
|
+
)
|
|
10262
|
+
]
|
|
10263
|
+
},
|
|
10264
|
+
snap.id
|
|
10265
|
+
);
|
|
10266
|
+
}),
|
|
9951
10267
|
/* @__PURE__ */ jsxs4(
|
|
9952
10268
|
"div",
|
|
9953
10269
|
{
|
|
@@ -11051,7 +11367,7 @@ var ErrorOverlay = ({
|
|
|
11051
11367
|
};
|
|
11052
11368
|
|
|
11053
11369
|
// src/components/MouseElementTracker.tsx
|
|
11054
|
-
import { useState as useState7, useMemo as
|
|
11370
|
+
import { useState as useState7, useMemo as useMemo4 } from "react";
|
|
11055
11371
|
import { applyToPoint as applyToPoint12, inverse as inverse5 } from "transformation-matrix";
|
|
11056
11372
|
|
|
11057
11373
|
// src/components/ElementOverlayBox.tsx
|
|
@@ -11468,7 +11784,7 @@ var MouseElementTracker = ({
|
|
|
11468
11784
|
}) => {
|
|
11469
11785
|
const [mousedPrimitives, setMousedPrimitives] = useState7([]);
|
|
11470
11786
|
const [mousePos, setMousePos] = useState7({ x: 0, y: 0 });
|
|
11471
|
-
const highlightedPrimitives =
|
|
11787
|
+
const highlightedPrimitives = useMemo4(() => {
|
|
11472
11788
|
const highlightedPrimitives2 = [];
|
|
11473
11789
|
for (const primitive of mousedPrimitives) {
|
|
11474
11790
|
if (primitive._element?.type === "pcb_via") continue;
|
|
@@ -11832,15 +12148,15 @@ var PcbGroupOverlay = ({
|
|
|
11832
12148
|
|
|
11833
12149
|
// src/components/RatsNestOverlay.tsx
|
|
11834
12150
|
import { applyToPoint as applyToPoint14, identity as identity9 } from "transformation-matrix";
|
|
11835
|
-
import { useMemo as
|
|
12151
|
+
import { useMemo as useMemo5 } from "react";
|
|
11836
12152
|
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
11837
12153
|
var RatsNestOverlay = ({ transform, soup, children }) => {
|
|
11838
12154
|
const isShowingRatsNest = useGlobalStore((s) => s.is_showing_rats_nest);
|
|
11839
|
-
const { netMap, idToNetMap } =
|
|
12155
|
+
const { netMap, idToNetMap } = useMemo5(
|
|
11840
12156
|
() => getFullConnectivityMapFromCircuitJson(soup || []),
|
|
11841
12157
|
[soup]
|
|
11842
12158
|
);
|
|
11843
|
-
const ratsNestLines =
|
|
12159
|
+
const ratsNestLines = useMemo5(() => {
|
|
11844
12160
|
if (!soup || !isShowingRatsNest) return [];
|
|
11845
12161
|
const getElementPosition = (id) => {
|
|
11846
12162
|
const element = su(soup)[id.replace(/_\d+$/, "")].get(id);
|
|
@@ -11937,7 +12253,7 @@ var RatsNestOverlay = ({ transform, soup, children }) => {
|
|
|
11937
12253
|
import {
|
|
11938
12254
|
useEffect as useEffect15,
|
|
11939
12255
|
useState as useState9,
|
|
11940
|
-
useCallback as
|
|
12256
|
+
useCallback as useCallback4,
|
|
11941
12257
|
useRef as useRef10
|
|
11942
12258
|
} from "react";
|
|
11943
12259
|
import { css as css3 } from "@emotion/css";
|
|
@@ -11945,7 +12261,7 @@ import { css as css3 } from "@emotion/css";
|
|
|
11945
12261
|
// package.json
|
|
11946
12262
|
var package_default = {
|
|
11947
12263
|
name: "@tscircuit/pcb-viewer",
|
|
11948
|
-
version: "1.11.
|
|
12264
|
+
version: "1.11.238",
|
|
11949
12265
|
main: "dist/index.js",
|
|
11950
12266
|
type: "module",
|
|
11951
12267
|
repository: "tscircuit/pcb-viewer",
|
|
@@ -12290,20 +12606,20 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
12290
12606
|
useHotKey("6", hotKeyCallbacks["6"]);
|
|
12291
12607
|
useHotKey("7", hotKeyCallbacks["7"]);
|
|
12292
12608
|
useHotKey("8", hotKeyCallbacks["8"]);
|
|
12293
|
-
const handleMouseEnter =
|
|
12609
|
+
const handleMouseEnter = useCallback4(() => {
|
|
12294
12610
|
setIsMouseOverContainer(true);
|
|
12295
12611
|
}, [setIsMouseOverContainer]);
|
|
12296
|
-
const handleMouseLeave =
|
|
12612
|
+
const handleMouseLeave = useCallback4(() => {
|
|
12297
12613
|
setIsMouseOverContainer(false);
|
|
12298
12614
|
setLayerMenuOpen(false);
|
|
12299
12615
|
setViewMenuOpen(false);
|
|
12300
12616
|
setErrorsOpen(false);
|
|
12301
12617
|
setHoveredErrorId(null);
|
|
12302
12618
|
}, [setIsMouseOverContainer, setHoveredErrorId]);
|
|
12303
|
-
const handleLayerMenuToggle =
|
|
12619
|
+
const handleLayerMenuToggle = useCallback4(() => {
|
|
12304
12620
|
setLayerMenuOpen(!isLayerMenuOpen);
|
|
12305
12621
|
}, [isLayerMenuOpen]);
|
|
12306
|
-
const handleErrorsToggle =
|
|
12622
|
+
const handleErrorsToggle = useCallback4(() => {
|
|
12307
12623
|
const newErrorsOpen = !isErrorsOpen;
|
|
12308
12624
|
setErrorsOpen(newErrorsOpen);
|
|
12309
12625
|
if (newErrorsOpen) {
|
|
@@ -12313,20 +12629,20 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
12313
12629
|
setHoveredErrorId(null);
|
|
12314
12630
|
}
|
|
12315
12631
|
}, [isErrorsOpen, setHoveredErrorId]);
|
|
12316
|
-
const handleEditTraceToggle =
|
|
12632
|
+
const handleEditTraceToggle = useCallback4(() => {
|
|
12317
12633
|
setEditMode(editModes.in_draw_trace_mode ? "off" : "draw_trace");
|
|
12318
12634
|
}, [editModes.in_draw_trace_mode, setEditMode]);
|
|
12319
|
-
const handleMoveComponentToggle =
|
|
12635
|
+
const handleMoveComponentToggle = useCallback4(() => {
|
|
12320
12636
|
setEditMode(editModes.in_move_footprint_mode ? "off" : "move_footprint");
|
|
12321
12637
|
}, [editModes.in_move_footprint_mode, setEditMode]);
|
|
12322
|
-
const handleRatsNestToggle =
|
|
12638
|
+
const handleRatsNestToggle = useCallback4(() => {
|
|
12323
12639
|
setIsShowingRatsNest(!viewSettings.is_showing_rats_nest);
|
|
12324
12640
|
}, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest]);
|
|
12325
|
-
const handleMeasureToolClick =
|
|
12641
|
+
const handleMeasureToolClick = useCallback4(() => {
|
|
12326
12642
|
setMeasureToolArmed(true);
|
|
12327
12643
|
window.dispatchEvent(new Event("arm-dimension-tool"));
|
|
12328
12644
|
}, []);
|
|
12329
|
-
const handleViewMenuToggle =
|
|
12645
|
+
const handleViewMenuToggle = useCallback4(() => {
|
|
12330
12646
|
const newViewMenuOpen = !isViewMenuOpen;
|
|
12331
12647
|
setViewMenuOpen(newViewMenuOpen);
|
|
12332
12648
|
if (newViewMenuOpen) {
|
|
@@ -12761,7 +13077,7 @@ import { jsx as jsx16 } from "react/jsx-runtime";
|
|
|
12761
13077
|
var CanvasElementsRenderer = (props) => {
|
|
12762
13078
|
const { transform, elements } = props;
|
|
12763
13079
|
const hoveredErrorId = useGlobalStore((state) => state.hovered_error_id);
|
|
12764
|
-
const [primitivesWithoutInteractionMetadata, connectivityMap] =
|
|
13080
|
+
const [primitivesWithoutInteractionMetadata, connectivityMap] = useMemo6(() => {
|
|
12765
13081
|
const primitivesWithoutInteractionMetadata2 = props.elements.flatMap(
|
|
12766
13082
|
(elm) => convertElementToPrimitives(elm, props.elements)
|
|
12767
13083
|
);
|
|
@@ -12774,7 +13090,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12774
13090
|
drawingObjectIdsWithMouseOver: /* @__PURE__ */ new Set(),
|
|
12775
13091
|
primitiveIdsInMousedOverNet: []
|
|
12776
13092
|
});
|
|
12777
|
-
const errorRelatedIds =
|
|
13093
|
+
const errorRelatedIds = useMemo6(() => {
|
|
12778
13094
|
if (!hoveredErrorId) return [];
|
|
12779
13095
|
const errorElements = elements.filter(
|
|
12780
13096
|
(el) => el.type.includes("error")
|
|
@@ -12793,7 +13109,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12793
13109
|
}
|
|
12794
13110
|
return relatedIds;
|
|
12795
13111
|
}, [hoveredErrorId, elements]);
|
|
12796
|
-
const primitives =
|
|
13112
|
+
const primitives = useMemo6(() => {
|
|
12797
13113
|
const combinedPrimitiveIds = [
|
|
12798
13114
|
...hoverState.primitiveIdsInMousedOverNet,
|
|
12799
13115
|
...errorRelatedIds
|
|
@@ -12804,7 +13120,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12804
13120
|
primitiveIdsInMousedOverNet: combinedPrimitiveIds
|
|
12805
13121
|
});
|
|
12806
13122
|
}, [primitivesWithoutInteractionMetadata, hoverState, errorRelatedIds]);
|
|
12807
|
-
const onMouseOverPrimitives =
|
|
13123
|
+
const onMouseOverPrimitives = useCallback5(
|
|
12808
13124
|
(primitivesHoveredOver) => {
|
|
12809
13125
|
const primitiveIdsInMousedOverNet = [];
|
|
12810
13126
|
for (const primitive of primitivesHoveredOver) {
|
|
@@ -12857,6 +13173,7 @@ var CanvasElementsRenderer = (props) => {
|
|
|
12857
13173
|
{
|
|
12858
13174
|
transform,
|
|
12859
13175
|
focusOnHover: props.focusOnHover,
|
|
13176
|
+
primitives: primitivesWithoutInteractionMetadata,
|
|
12860
13177
|
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(
|
|
12861
13178
|
DebugGraphicsOverlay,
|
|
12862
13179
|
{
|
|
@@ -12966,7 +13283,7 @@ var PCBViewer = ({
|
|
|
12966
13283
|
editEvents = editEventsProp ?? editEvents;
|
|
12967
13284
|
const initialRenderCompleted = useRef11(false);
|
|
12968
13285
|
const touchStartRef = useRef11(null);
|
|
12969
|
-
const circuitJsonKey =
|
|
13286
|
+
const circuitJsonKey = useMemo7(
|
|
12970
13287
|
() => calculateCircuitJsonKey(circuitJson),
|
|
12971
13288
|
[circuitJson]
|
|
12972
13289
|
);
|
|
@@ -12999,12 +13316,12 @@ var PCBViewer = ({
|
|
|
12999
13316
|
initialRenderCompleted.current = true;
|
|
13000
13317
|
}
|
|
13001
13318
|
}, [circuitJson, refDimensions]);
|
|
13002
|
-
const pcbElmsPreEdit =
|
|
13319
|
+
const pcbElmsPreEdit = useMemo7(() => {
|
|
13003
13320
|
return circuitJson?.filter(
|
|
13004
13321
|
(e) => e.type.startsWith("pcb_") || e.type.startsWith("source_")
|
|
13005
13322
|
) ?? [];
|
|
13006
13323
|
}, [circuitJsonKey]);
|
|
13007
|
-
const elements =
|
|
13324
|
+
const elements = useMemo7(() => {
|
|
13008
13325
|
return applyEditEvents({
|
|
13009
13326
|
circuitJson: pcbElmsPreEdit,
|
|
13010
13327
|
editEvents
|
|
@@ -13021,7 +13338,7 @@ var PCBViewer = ({
|
|
|
13021
13338
|
setEditEvents(newEditEvents);
|
|
13022
13339
|
onEditEventsChanged?.(newEditEvents);
|
|
13023
13340
|
};
|
|
13024
|
-
const mergedInitialState =
|
|
13341
|
+
const mergedInitialState = useMemo7(
|
|
13025
13342
|
() => ({
|
|
13026
13343
|
...initialState,
|
|
13027
13344
|
...disablePcbGroups && { is_showing_pcb_groups: false }
|