@tscircuit/pcb-viewer 1.11.369 → 1.11.370
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/README.md +1 -0
- package/dist/index.d.ts +20 -11
- package/dist/index.js +182 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ The PCBViewer component accepts these props:
|
|
|
75
75
|
- `allowEditing`: Enable/disable editing capabilities (default: true)
|
|
76
76
|
- `editEvents`: Array of edit events to apply
|
|
77
77
|
- `onEditEventsChanged`: Callback when edit events change
|
|
78
|
+
- `onBoundsSelected`: Callback when the Bounds tool completes a rectangle selection. Receives `{ minX, minY, maxX, maxY }`.
|
|
78
79
|
- `initialState`: Initial state for the viewer
|
|
79
80
|
|
|
80
81
|
### Features
|
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,23 @@ type StateProps = {
|
|
|
51
51
|
[key in keyof State]: State[key] extends boolean ? boolean : never;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
type GridConfig = {
|
|
55
|
+
spacing: number;
|
|
56
|
+
view_window: {
|
|
57
|
+
left: number;
|
|
58
|
+
right: number;
|
|
59
|
+
top: number;
|
|
60
|
+
bottom: number;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
interface BoundsSelection {
|
|
65
|
+
minX: number;
|
|
66
|
+
minY: number;
|
|
67
|
+
maxX: number;
|
|
68
|
+
maxY: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
54
71
|
type Props = {
|
|
55
72
|
circuitJson?: AnyCircuitElement[];
|
|
56
73
|
height?: number;
|
|
@@ -58,22 +75,13 @@ type Props = {
|
|
|
58
75
|
editEvents?: ManualEditEvent[];
|
|
59
76
|
initialState?: Partial<StateProps>;
|
|
60
77
|
onEditEventsChanged?: (editEvents: ManualEditEvent[]) => void;
|
|
78
|
+
onBoundsSelected?: (bounds: BoundsSelection) => void;
|
|
61
79
|
focusOnHover?: boolean;
|
|
62
80
|
clickToInteractEnabled?: boolean;
|
|
63
81
|
debugGraphics?: GraphicsObject | null;
|
|
64
82
|
disablePcbGroups?: boolean;
|
|
65
83
|
};
|
|
66
|
-
declare const PCBViewer: ({ circuitJson, debugGraphics, height, initialState, allowEditing, editEvents: editEventsProp, onEditEventsChanged, focusOnHover, clickToInteractEnabled, disablePcbGroups, }: Props) => react_jsx_runtime.JSX.Element;
|
|
67
|
-
|
|
68
|
-
type GridConfig = {
|
|
69
|
-
spacing: number;
|
|
70
|
-
view_window: {
|
|
71
|
-
left: number;
|
|
72
|
-
right: number;
|
|
73
|
-
top: number;
|
|
74
|
-
bottom: number;
|
|
75
|
-
};
|
|
76
|
-
};
|
|
84
|
+
declare const PCBViewer: ({ circuitJson, debugGraphics, height, initialState, allowEditing, editEvents: editEventsProp, onEditEventsChanged, onBoundsSelected, focusOnHover, clickToInteractEnabled, disablePcbGroups, }: Props) => react_jsx_runtime.JSX.Element;
|
|
77
85
|
|
|
78
86
|
interface CanvasElementsRendererProps {
|
|
79
87
|
elements: AnyCircuitElement[];
|
|
@@ -85,6 +93,7 @@ interface CanvasElementsRendererProps {
|
|
|
85
93
|
grid?: GridConfig;
|
|
86
94
|
allowEditing: boolean;
|
|
87
95
|
focusOnHover?: boolean;
|
|
96
|
+
onBoundsSelected?: (bounds: BoundsSelection) => void;
|
|
88
97
|
cancelPanDrag: () => void;
|
|
89
98
|
onCreateEditEvent: (event: ManualEditEvent) => void;
|
|
90
99
|
onModifyEditEvent: (event: Partial<ManualEditEvent>) => void;
|
package/dist/index.js
CHANGED
|
@@ -11611,12 +11611,17 @@ var DimensionOverlay = ({
|
|
|
11611
11611
|
children,
|
|
11612
11612
|
transform,
|
|
11613
11613
|
focusOnHover = false,
|
|
11614
|
-
primitives = []
|
|
11614
|
+
primitives = [],
|
|
11615
|
+
onBoundsSelected,
|
|
11616
|
+
cancelPanDrag
|
|
11615
11617
|
}) => {
|
|
11616
11618
|
if (!transform) transform = identity4();
|
|
11617
11619
|
const [dimensionToolVisible, setDimensionToolVisible] = useState4(false);
|
|
11618
11620
|
const [dimensionToolStretching, setDimensionToolStretching] = useState4(false);
|
|
11619
11621
|
const [measureToolArmed, setMeasureToolArmed] = useState4(false);
|
|
11622
|
+
const [boundsToolArmed, setBoundsToolArmed] = useState4(false);
|
|
11623
|
+
const [boundsToolVisible, setBoundsToolVisible] = useState4(false);
|
|
11624
|
+
const [boundsToolDragging, setBoundsToolDragging] = useState4(false);
|
|
11620
11625
|
const [activeSnapIds, setActiveSnapIds] = useState4({
|
|
11621
11626
|
start: null,
|
|
11622
11627
|
end: null
|
|
@@ -11628,8 +11633,16 @@ var DimensionOverlay = ({
|
|
|
11628
11633
|
window.dispatchEvent(new Event("disarm-dimension-tool"));
|
|
11629
11634
|
}
|
|
11630
11635
|
}, [measureToolArmed]);
|
|
11636
|
+
const disarmBounds = useCallback6(() => {
|
|
11637
|
+
if (boundsToolArmed) {
|
|
11638
|
+
setBoundsToolArmed(false);
|
|
11639
|
+
window.dispatchEvent(new Event("disarm-bounds-tool"));
|
|
11640
|
+
}
|
|
11641
|
+
}, [boundsToolArmed]);
|
|
11631
11642
|
const [dStart, setDStart] = useState4({ x: 0, y: 0 });
|
|
11632
11643
|
const [dEnd, setDEnd] = useState4({ x: 0, y: 0 });
|
|
11644
|
+
const [boundsStart, setBoundsStart] = useState4({ x: 0, y: 0 });
|
|
11645
|
+
const [boundsEnd, setBoundsEnd] = useState4({ x: 0, y: 0 });
|
|
11633
11646
|
const mousePosRef = useRef6({ x: 0, y: 0 });
|
|
11634
11647
|
const containerRef = useRef6(null);
|
|
11635
11648
|
const container = containerRef.current;
|
|
@@ -11768,22 +11781,74 @@ var DimensionOverlay = ({
|
|
|
11768
11781
|
setDimensionToolVisible(false);
|
|
11769
11782
|
setDimensionToolStretching(false);
|
|
11770
11783
|
setActiveSnapIds({ start: null, end: null });
|
|
11784
|
+
setBoundsToolVisible(false);
|
|
11785
|
+
setBoundsToolDragging(false);
|
|
11771
11786
|
disarmMeasure();
|
|
11787
|
+
disarmBounds();
|
|
11772
11788
|
}
|
|
11773
11789
|
};
|
|
11774
11790
|
const armMeasure = () => {
|
|
11775
11791
|
setMeasureToolArmed(true);
|
|
11792
|
+
setBoundsToolArmed(false);
|
|
11793
|
+
window.dispatchEvent(new Event("disarm-bounds-tool"));
|
|
11794
|
+
};
|
|
11795
|
+
const armBounds = () => {
|
|
11796
|
+
setBoundsToolArmed(true);
|
|
11797
|
+
setMeasureToolArmed(false);
|
|
11798
|
+
setDimensionToolVisible(false);
|
|
11799
|
+
setDimensionToolStretching(false);
|
|
11800
|
+
window.dispatchEvent(new Event("disarm-dimension-tool"));
|
|
11776
11801
|
};
|
|
11777
11802
|
window.addEventListener("keydown", down);
|
|
11778
11803
|
window.addEventListener("arm-dimension-tool", armMeasure);
|
|
11804
|
+
window.addEventListener("arm-bounds-tool", armBounds);
|
|
11779
11805
|
return () => {
|
|
11780
11806
|
window.removeEventListener("keydown", down);
|
|
11781
11807
|
window.removeEventListener("arm-dimension-tool", armMeasure);
|
|
11808
|
+
window.removeEventListener("arm-bounds-tool", armBounds);
|
|
11782
11809
|
disarmMeasure();
|
|
11810
|
+
disarmBounds();
|
|
11783
11811
|
};
|
|
11784
|
-
}, [
|
|
11812
|
+
}, [
|
|
11813
|
+
isMouseOverContainer,
|
|
11814
|
+
dimensionToolVisible,
|
|
11815
|
+
disarmMeasure,
|
|
11816
|
+
disarmBounds,
|
|
11817
|
+
findSnap
|
|
11818
|
+
]);
|
|
11785
11819
|
const screenDStart = applyToPoint8(transform, dStart);
|
|
11786
11820
|
const screenDEnd = applyToPoint8(transform, dEnd);
|
|
11821
|
+
const screenBoundsStart = applyToPoint8(transform, boundsStart);
|
|
11822
|
+
const screenBoundsEnd = applyToPoint8(transform, boundsEnd);
|
|
11823
|
+
const selectedBounds = {
|
|
11824
|
+
minX: Math.min(boundsStart.x, boundsEnd.x),
|
|
11825
|
+
minY: Math.min(boundsStart.y, boundsEnd.y),
|
|
11826
|
+
maxX: Math.max(boundsStart.x, boundsEnd.x),
|
|
11827
|
+
maxY: Math.max(boundsStart.y, boundsEnd.y)
|
|
11828
|
+
};
|
|
11829
|
+
const boundsScreenRect = {
|
|
11830
|
+
left: Math.min(screenBoundsStart.x, screenBoundsEnd.x),
|
|
11831
|
+
top: Math.min(screenBoundsStart.y, screenBoundsEnd.y),
|
|
11832
|
+
width: Math.abs(screenBoundsStart.x - screenBoundsEnd.x),
|
|
11833
|
+
height: Math.abs(screenBoundsStart.y - screenBoundsEnd.y)
|
|
11834
|
+
};
|
|
11835
|
+
const emitBounds = useCallback6(
|
|
11836
|
+
(start, end) => {
|
|
11837
|
+
const bounds = {
|
|
11838
|
+
minX: Math.min(start.x, end.x),
|
|
11839
|
+
minY: Math.min(start.y, end.y),
|
|
11840
|
+
maxX: Math.max(start.x, end.x),
|
|
11841
|
+
maxY: Math.max(start.y, end.y)
|
|
11842
|
+
};
|
|
11843
|
+
onBoundsSelected?.(bounds);
|
|
11844
|
+
window.dispatchEvent(
|
|
11845
|
+
new CustomEvent("pcb-viewer:bounds-selected", {
|
|
11846
|
+
detail: bounds
|
|
11847
|
+
})
|
|
11848
|
+
);
|
|
11849
|
+
},
|
|
11850
|
+
[onBoundsSelected]
|
|
11851
|
+
);
|
|
11787
11852
|
const arrowScreenBounds = {
|
|
11788
11853
|
left: Math.min(screenDStart.x, screenDEnd.x),
|
|
11789
11854
|
right: Math.max(screenDStart.x, screenDEnd.x),
|
|
@@ -11838,13 +11903,26 @@ var DimensionOverlay = ({
|
|
|
11838
11903
|
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
11839
11904
|
setActiveSnapIds((prev) => ({ ...prev, end: snap.id }));
|
|
11840
11905
|
}
|
|
11906
|
+
if (boundsToolDragging) {
|
|
11907
|
+
cancelPanDrag?.();
|
|
11908
|
+
setBoundsEnd({ x: rwPoint.x, y: rwPoint.y });
|
|
11909
|
+
}
|
|
11841
11910
|
},
|
|
11842
11911
|
onMouseDown: (e) => {
|
|
11843
11912
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
11844
11913
|
const x = e.clientX - rect.left;
|
|
11845
11914
|
const y = e.clientY - rect.top;
|
|
11846
11915
|
const rwPoint = applyToPoint8(inverse2(transform), { x, y });
|
|
11847
|
-
if (
|
|
11916
|
+
if (boundsToolArmed) {
|
|
11917
|
+
e.preventDefault();
|
|
11918
|
+
e.stopPropagation();
|
|
11919
|
+
cancelPanDrag?.();
|
|
11920
|
+
setBoundsStart({ x: rwPoint.x, y: rwPoint.y });
|
|
11921
|
+
setBoundsEnd({ x: rwPoint.x, y: rwPoint.y });
|
|
11922
|
+
setBoundsToolVisible(true);
|
|
11923
|
+
setBoundsToolDragging(true);
|
|
11924
|
+
disarmBounds();
|
|
11925
|
+
} else if (measureToolArmed && !dimensionToolVisible) {
|
|
11848
11926
|
const snap = findSnap(rwPoint);
|
|
11849
11927
|
setDStart({ x: snap.point.x, y: snap.point.y });
|
|
11850
11928
|
setDEnd({ x: snap.point.x, y: snap.point.y });
|
|
@@ -11860,8 +11938,82 @@ var DimensionOverlay = ({
|
|
|
11860
11938
|
setActiveSnapIds({ start: null, end: null });
|
|
11861
11939
|
}
|
|
11862
11940
|
},
|
|
11941
|
+
onMouseUp: (e) => {
|
|
11942
|
+
if (!boundsToolDragging) return;
|
|
11943
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
11944
|
+
const x = e.clientX - rect.left;
|
|
11945
|
+
const y = e.clientY - rect.top;
|
|
11946
|
+
const rwPoint = applyToPoint8(inverse2(transform), { x, y });
|
|
11947
|
+
const end = { x: rwPoint.x, y: rwPoint.y };
|
|
11948
|
+
e.preventDefault();
|
|
11949
|
+
e.stopPropagation();
|
|
11950
|
+
cancelPanDrag?.();
|
|
11951
|
+
setBoundsEnd(end);
|
|
11952
|
+
setBoundsToolDragging(false);
|
|
11953
|
+
emitBounds(boundsStart, end);
|
|
11954
|
+
},
|
|
11863
11955
|
children: [
|
|
11864
11956
|
children,
|
|
11957
|
+
boundsToolVisible && /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
11958
|
+
/* @__PURE__ */ jsx6(
|
|
11959
|
+
"svg",
|
|
11960
|
+
{
|
|
11961
|
+
style: {
|
|
11962
|
+
position: "absolute",
|
|
11963
|
+
left: 0,
|
|
11964
|
+
top: 0,
|
|
11965
|
+
pointerEvents: "none",
|
|
11966
|
+
mixBlendMode: "difference",
|
|
11967
|
+
zIndex: zIndexMap.dimensionOverlay
|
|
11968
|
+
},
|
|
11969
|
+
width: containerBounds.width,
|
|
11970
|
+
height: containerBounds.height,
|
|
11971
|
+
children: /* @__PURE__ */ jsx6(
|
|
11972
|
+
"rect",
|
|
11973
|
+
{
|
|
11974
|
+
x: boundsScreenRect.left,
|
|
11975
|
+
y: boundsScreenRect.top,
|
|
11976
|
+
width: boundsScreenRect.width,
|
|
11977
|
+
height: boundsScreenRect.height,
|
|
11978
|
+
stroke: "red",
|
|
11979
|
+
strokeWidth: 1.5,
|
|
11980
|
+
strokeDasharray: "4,3",
|
|
11981
|
+
fill: "rgba(255, 0, 0, 0.12)"
|
|
11982
|
+
}
|
|
11983
|
+
)
|
|
11984
|
+
}
|
|
11985
|
+
),
|
|
11986
|
+
/* @__PURE__ */ jsxs4(
|
|
11987
|
+
"div",
|
|
11988
|
+
{
|
|
11989
|
+
style: {
|
|
11990
|
+
left: 0,
|
|
11991
|
+
bottom: dimensionToolVisible ? 58 : 0,
|
|
11992
|
+
position: "absolute",
|
|
11993
|
+
color: "red",
|
|
11994
|
+
fontFamily: "sans-serif",
|
|
11995
|
+
fontSize: 12,
|
|
11996
|
+
margin: 4,
|
|
11997
|
+
pointerEvents: "none",
|
|
11998
|
+
mixBlendMode: "difference",
|
|
11999
|
+
zIndex: zIndexMap.dimensionOverlay
|
|
12000
|
+
},
|
|
12001
|
+
children: [
|
|
12002
|
+
"minX: ",
|
|
12003
|
+
selectedBounds.minX.toFixed(2),
|
|
12004
|
+
", minY:",
|
|
12005
|
+
" ",
|
|
12006
|
+
selectedBounds.minY.toFixed(2),
|
|
12007
|
+
/* @__PURE__ */ jsx6("br", {}),
|
|
12008
|
+
"maxX: ",
|
|
12009
|
+
selectedBounds.maxX.toFixed(2),
|
|
12010
|
+
", maxY:",
|
|
12011
|
+
" ",
|
|
12012
|
+
selectedBounds.maxY.toFixed(2)
|
|
12013
|
+
]
|
|
12014
|
+
}
|
|
12015
|
+
)
|
|
12016
|
+
] }),
|
|
11865
12017
|
dimensionToolVisible && /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
11866
12018
|
diagonalLabel.show && /* @__PURE__ */ jsx6(
|
|
11867
12019
|
"div",
|
|
@@ -14752,7 +14904,7 @@ import { css as css3 } from "@emotion/css";
|
|
|
14752
14904
|
// package.json
|
|
14753
14905
|
var package_default = {
|
|
14754
14906
|
name: "@tscircuit/pcb-viewer",
|
|
14755
|
-
version: "1.11.
|
|
14907
|
+
version: "1.11.369",
|
|
14756
14908
|
main: "dist/index.js",
|
|
14757
14909
|
type: "module",
|
|
14758
14910
|
repository: "tscircuit/pcb-viewer",
|
|
@@ -15564,14 +15716,21 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
15564
15716
|
const [isLayerMenuOpen, setLayerMenuOpen] = useState11(false);
|
|
15565
15717
|
const [isErrorsOpen, setErrorsOpen] = useState11(false);
|
|
15566
15718
|
const [measureToolArmed, setMeasureToolArmed] = useState11(false);
|
|
15719
|
+
const [boundsToolArmed, setBoundsToolArmed] = useState11(false);
|
|
15567
15720
|
useEffect17(() => {
|
|
15568
15721
|
const arm = () => setMeasureToolArmed(true);
|
|
15569
15722
|
const disarm = () => setMeasureToolArmed(false);
|
|
15723
|
+
const armBounds = () => setBoundsToolArmed(true);
|
|
15724
|
+
const disarmBounds = () => setBoundsToolArmed(false);
|
|
15570
15725
|
window.addEventListener("arm-dimension-tool", arm);
|
|
15571
15726
|
window.addEventListener("disarm-dimension-tool", disarm);
|
|
15727
|
+
window.addEventListener("arm-bounds-tool", armBounds);
|
|
15728
|
+
window.addEventListener("disarm-bounds-tool", disarmBounds);
|
|
15572
15729
|
return () => {
|
|
15573
15730
|
window.removeEventListener("arm-dimension-tool", arm);
|
|
15574
15731
|
window.removeEventListener("disarm-dimension-tool", disarm);
|
|
15732
|
+
window.removeEventListener("arm-bounds-tool", armBounds);
|
|
15733
|
+
window.removeEventListener("disarm-bounds-tool", disarmBounds);
|
|
15575
15734
|
};
|
|
15576
15735
|
}, []);
|
|
15577
15736
|
const pcbBoard = elements?.find((el) => el.type === "pcb_board");
|
|
@@ -15669,8 +15828,14 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
15669
15828
|
}, [viewSettings.is_showing_rats_nest, setIsShowingRatsNest]);
|
|
15670
15829
|
const handleMeasureToolClick = useCallback10(() => {
|
|
15671
15830
|
setMeasureToolArmed(true);
|
|
15831
|
+
setBoundsToolArmed(false);
|
|
15672
15832
|
window.dispatchEvent(new Event("arm-dimension-tool"));
|
|
15673
15833
|
}, []);
|
|
15834
|
+
const handleBoundsToolClick = useCallback10(() => {
|
|
15835
|
+
setBoundsToolArmed(true);
|
|
15836
|
+
setMeasureToolArmed(false);
|
|
15837
|
+
window.dispatchEvent(new Event("arm-bounds-tool"));
|
|
15838
|
+
}, []);
|
|
15674
15839
|
const handleViewMenuToggle = useCallback10(() => {
|
|
15675
15840
|
const newViewMenuOpen = !isViewMenuOpen;
|
|
15676
15841
|
setViewMenuOpen(newViewMenuOpen);
|
|
@@ -15842,6 +16007,15 @@ var ToolbarOverlay = ({ children, elements }) => {
|
|
|
15842
16007
|
children: /* @__PURE__ */ jsx23("div", { children: "\u{1F4CF}" })
|
|
15843
16008
|
}
|
|
15844
16009
|
),
|
|
16010
|
+
/* @__PURE__ */ jsx23(
|
|
16011
|
+
ToolbarButton,
|
|
16012
|
+
{
|
|
16013
|
+
isSmallScreen,
|
|
16014
|
+
style: boundsToolArmed ? { backgroundColor: "#444" } : {},
|
|
16015
|
+
onClick: handleBoundsToolClick,
|
|
16016
|
+
children: /* @__PURE__ */ jsx23("div", { children: "Bounds" })
|
|
16017
|
+
}
|
|
16018
|
+
),
|
|
15845
16019
|
/* @__PURE__ */ jsx23(
|
|
15846
16020
|
ToolbarButton,
|
|
15847
16021
|
{
|
|
@@ -16186,6 +16360,8 @@ var CanvasElementsRenderer = (props) => {
|
|
|
16186
16360
|
transform,
|
|
16187
16361
|
focusOnHover: props.focusOnHover,
|
|
16188
16362
|
primitives: primitivesWithoutInteractionMetadata,
|
|
16363
|
+
onBoundsSelected: props.onBoundsSelected,
|
|
16364
|
+
cancelPanDrag: props.cancelPanDrag,
|
|
16189
16365
|
children: /* @__PURE__ */ jsx24(ToolbarOverlay, { elements, children: /* @__PURE__ */ jsx24(ErrorOverlay, { transform, elements, children: /* @__PURE__ */ jsx24(RatsNestOverlay, { transform, soup: elements, children: /* @__PURE__ */ jsx24(
|
|
16190
16366
|
PcbGroupOverlay,
|
|
16191
16367
|
{
|
|
@@ -16294,6 +16470,7 @@ var PCBViewer = ({
|
|
|
16294
16470
|
allowEditing = true,
|
|
16295
16471
|
editEvents: editEventsProp,
|
|
16296
16472
|
onEditEventsChanged,
|
|
16473
|
+
onBoundsSelected,
|
|
16297
16474
|
focusOnHover = false,
|
|
16298
16475
|
clickToInteractEnabled = false,
|
|
16299
16476
|
disablePcbGroups = false
|
|
@@ -16415,6 +16592,7 @@ var PCBViewer = ({
|
|
|
16415
16592
|
width: refDimensions.width,
|
|
16416
16593
|
allowEditing,
|
|
16417
16594
|
focusOnHover,
|
|
16595
|
+
onBoundsSelected,
|
|
16418
16596
|
cancelPanDrag,
|
|
16419
16597
|
onCreateEditEvent,
|
|
16420
16598
|
onModifyEditEvent,
|