fix: Centralized midpoint snap code

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs
2026-05-08 13:58:30 +00:00
parent 4e94b02375
commit 4a161c1764
15 changed files with 313 additions and 230 deletions
+1
View File
@@ -269,6 +269,7 @@ export const handleFocusPointDrag = (
newMode || "orbit", newMode || "orbit",
linearElementEditor.draggedFocusPointBinding, linearElementEditor.draggedFocusPointBinding,
scene, scene,
appState.zoom,
point, point,
); );
} }
+18 -116
View File
@@ -60,6 +60,7 @@ import { updateElbowArrowPoints } from "./elbowArrow";
import { import {
deconstructDiamondElement, deconstructDiamondElement,
deconstructRectanguloidElement, deconstructRectanguloidElement,
getSnapOutlineMidPoint,
projectFixedPointOntoDiagonal, projectFixedPointOntoDiagonal,
} from "./utils"; } from "./utils";
@@ -175,6 +176,7 @@ export const bindOrUnbindBindingElement = (
start, start,
"start", "start",
scene, scene,
appState.zoom,
appState.isBindingEnabled, appState.isBindingEnabled,
); );
bindOrUnbindBindingElementEdge( bindOrUnbindBindingElementEdge(
@@ -182,6 +184,7 @@ export const bindOrUnbindBindingElement = (
end, end,
"end", "end",
scene, scene,
appState.zoom,
appState.isBindingEnabled, appState.isBindingEnabled,
); );
if (start.focusPoint || end.focusPoint) { if (start.focusPoint || end.focusPoint) {
@@ -226,6 +229,7 @@ const bindOrUnbindBindingElementEdge = (
{ mode, element, focusPoint }: BindingStrategy, { mode, element, focusPoint }: BindingStrategy,
startOrEnd: "start" | "end", startOrEnd: "start" | "end",
scene: Scene, scene: Scene,
zoom: AppState["zoom"],
shouldSnapToOutline = true, shouldSnapToOutline = true,
): void => { ): void => {
if (mode === null) { if (mode === null) {
@@ -238,6 +242,7 @@ const bindOrUnbindBindingElementEdge = (
mode, mode,
startOrEnd, startOrEnd,
scene, scene,
zoom,
focusPoint, focusPoint,
shouldSnapToOutline, shouldSnapToOutline,
); );
@@ -1026,6 +1031,7 @@ export const bindBindingElement = (
mode: BindMode, mode: BindMode,
startOrEnd: "start" | "end", startOrEnd: "start" | "end",
scene: Scene, scene: Scene,
zoom: AppState["zoom"],
focusPoint?: GlobalPoint, focusPoint?: GlobalPoint,
shouldSnapToOutline = true, shouldSnapToOutline = true,
): void => { ): void => {
@@ -1042,6 +1048,7 @@ export const bindBindingElement = (
hoveredElement, hoveredElement,
startOrEnd, startOrEnd,
elementsMap, elementsMap,
zoom,
shouldSnapToOutline, shouldSnapToOutline,
), ),
}; };
@@ -1266,6 +1273,7 @@ const updateArrowBindings = (
strategy[strategyName].mode, strategy[strategyName].mode,
strategyName, strategyName,
scene, scene,
appState.zoom,
strategy[strategyName].focusPoint, strategy[strategyName].focusPoint,
); );
} }
@@ -1375,6 +1383,7 @@ export const bindPointToSnapToElementOutline = (
bindableElement: ExcalidrawBindableElement, bindableElement: ExcalidrawBindableElement,
startOrEnd: "start" | "end", startOrEnd: "start" | "end",
elementsMap: ElementsMap, elementsMap: ElementsMap,
zoom: AppState["zoom"],
customIntersector?: LineSegment<GlobalPoint>, customIntersector?: LineSegment<GlobalPoint>,
isMidpointSnappingEnabled = true, isMidpointSnappingEnabled = true,
): GlobalPoint => { ): GlobalPoint => {
@@ -1417,7 +1426,13 @@ export const bindPointToSnapToElementOutline = (
headingForPointFromElement(bindableElement, aabb, point), headingForPointFromElement(bindableElement, aabb, point),
); );
const snapPoint = isMidpointSnappingEnabled const snapPoint = isMidpointSnappingEnabled
? snapToMid(bindableElement, elementsMap, edgePoint, 0.05, arrowElement) ? getSnapOutlineMidPoint(
edgePoint,
bindableElement,
elementsMap,
zoom,
arrowElement,
)
: undefined; : undefined;
const resolved = snapPoint || point; const resolved = snapPoint || point;
const otherPoint = pointFrom<GlobalPoint>( const otherPoint = pointFrom<GlobalPoint>(
@@ -1599,121 +1614,6 @@ export const avoidRectangularCorner = (
return p; return p;
}; };
export const snapToMid = (
bindTarget: ExcalidrawBindableElement,
elementsMap: ElementsMap,
p: GlobalPoint,
tolerance: number = 0.05,
arrowElement?: ExcalidrawArrowElement,
): GlobalPoint | undefined => {
const { x, y, width, height, angle } = bindTarget;
const center = elementCenterPoint(bindTarget, elementsMap, -0.1, -0.1);
const nonRotated = pointRotateRads(p, center, -angle as Radians);
const bindingGap = arrowElement ? getBindingGap(bindTarget, arrowElement) : 0;
// snap-to-center point is adaptive to element size, but we don't want to go
// above and below certain px distance
const verticalThreshold = clamp(tolerance * height, 5, 80);
const horizontalThreshold = clamp(tolerance * width, 5, 80);
// Too close to the center makes it hard to resolve direction precisely
if (pointDistance(center, nonRotated) < bindingGap) {
return undefined;
}
if (
nonRotated[0] <= x + width / 2 &&
nonRotated[1] > center[1] - verticalThreshold &&
nonRotated[1] < center[1] + verticalThreshold
) {
// LEFT
return pointRotateRads(
pointFrom<GlobalPoint>(x - bindingGap, center[1]),
center,
angle,
);
} else if (
nonRotated[1] <= y + height / 2 &&
nonRotated[0] > center[0] - horizontalThreshold &&
nonRotated[0] < center[0] + horizontalThreshold
) {
// TOP
return pointRotateRads(
pointFrom<GlobalPoint>(center[0], y - bindingGap),
center,
angle,
);
} else if (
nonRotated[0] >= x + width / 2 &&
nonRotated[1] > center[1] - verticalThreshold &&
nonRotated[1] < center[1] + verticalThreshold
) {
// RIGHT
return pointRotateRads(
pointFrom<GlobalPoint>(x + width + bindingGap, center[1]),
center,
angle,
);
} else if (
nonRotated[1] >= y + height / 2 &&
nonRotated[0] > center[0] - horizontalThreshold &&
nonRotated[0] < center[0] + horizontalThreshold
) {
// DOWN
return pointRotateRads(
pointFrom<GlobalPoint>(center[0], y + height + bindingGap),
center,
angle,
);
} else if (bindTarget.type === "diamond") {
const distance = bindingGap;
const topLeft = pointFrom<GlobalPoint>(
x + width / 4 - distance,
y + height / 4 - distance,
);
const topRight = pointFrom<GlobalPoint>(
x + (3 * width) / 4 + distance,
y + height / 4 - distance,
);
const bottomLeft = pointFrom<GlobalPoint>(
x + width / 4 - distance,
y + (3 * height) / 4 + distance,
);
const bottomRight = pointFrom<GlobalPoint>(
x + (3 * width) / 4 + distance,
y + (3 * height) / 4 + distance,
);
if (
pointDistance(topLeft, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(topLeft, center, angle);
}
if (
pointDistance(topRight, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(topRight, center, angle);
}
if (
pointDistance(bottomLeft, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(bottomLeft, center, angle);
}
if (
pointDistance(bottomRight, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(bottomRight, center, angle);
}
}
return undefined;
};
const extractBinding = ( const extractBinding = (
arrow: ExcalidrawArrowElement, arrow: ExcalidrawArrowElement,
startOrEnd: "startBinding" | "endBinding", startOrEnd: "startBinding" | "endBinding",
@@ -1913,6 +1813,7 @@ export const calculateFixedPointForElbowArrowBinding = (
hoveredElement: ExcalidrawBindableElement, hoveredElement: ExcalidrawBindableElement,
startOrEnd: "start" | "end", startOrEnd: "start" | "end",
elementsMap: ElementsMap, elementsMap: ElementsMap,
zoom: AppState["zoom"],
shouldSnapToOutline = true, shouldSnapToOutline = true,
isMidpointSnappingEnabled = true, isMidpointSnappingEnabled = true,
): { fixedPoint: FixedPoint } => { ): { fixedPoint: FixedPoint } => {
@@ -1928,6 +1829,7 @@ export const calculateFixedPointForElbowArrowBinding = (
hoveredElement, hoveredElement,
startOrEnd, startOrEnd,
elementsMap, elementsMap,
zoom,
undefined, undefined,
isMidpointSnappingEnabled, isMidpointSnappingEnabled,
) )
+4
View File
@@ -1251,6 +1251,7 @@ const getElbowArrowData = (
"start", "start",
arrow.startBinding?.fixedPoint, arrow.startBinding?.fixedPoint,
origStartGlobalPoint, origStartGlobalPoint,
options?.zoom || ({ value: 1 } as AppState["zoom"]),
hoveredStartElement, hoveredStartElement,
elementsMap, elementsMap,
options?.isDragging, options?.isDragging,
@@ -1268,6 +1269,7 @@ const getElbowArrowData = (
"end", "end",
arrow.endBinding?.fixedPoint, arrow.endBinding?.fixedPoint,
origEndGlobalPoint, origEndGlobalPoint,
options?.zoom || ({ value: 1 } as AppState["zoom"]),
hoveredEndElement, hoveredEndElement,
elementsMap, elementsMap,
options?.isDragging, options?.isDragging,
@@ -2213,6 +2215,7 @@ const getGlobalPoint = (
startOrEnd: "start" | "end", startOrEnd: "start" | "end",
fixedPointRatio: [number, number] | undefined | null, fixedPointRatio: [number, number] | undefined | null,
initialPoint: GlobalPoint, initialPoint: GlobalPoint,
zoom: AppState["zoom"],
element?: ExcalidrawBindableElement | null, element?: ExcalidrawBindableElement | null,
elementsMap?: ElementsMap, elementsMap?: ElementsMap,
isDragging?: boolean, isDragging?: boolean,
@@ -2226,6 +2229,7 @@ const getGlobalPoint = (
element, element,
startOrEnd, startOrEnd,
elementsMap, elementsMap,
zoom,
undefined, undefined,
isMidpointSnappingEnabled, isMidpointSnappingEnabled,
); );
+9 -1
View File
@@ -452,8 +452,16 @@ const createBindingArrow = (
"orbit", "orbit",
"start", "start",
scene, scene,
appState.zoom,
);
bindBindingElement(
bindingArrow,
endBindingElement,
"orbit",
"end",
scene,
appState.zoom,
); );
bindBindingElement(bindingArrow, endBindingElement, "orbit", "end", scene);
const changedElements = new Map<string, OrderedExcalidrawElement>(); const changedElements = new Map<string, OrderedExcalidrawElement>();
changedElements.set( changedElements.set(
+7 -4
View File
@@ -48,7 +48,6 @@ import {
calculateFixedPointForNonElbowArrowBinding, calculateFixedPointForNonElbowArrowBinding,
getBindingStrategyForDraggingBindingElementEndpoints, getBindingStrategyForDraggingBindingElementEndpoints,
isBindingEnabled, isBindingEnabled,
snapToMid,
updateBoundPoint, updateBoundPoint,
} from "./binding"; } from "./binding";
import { import {
@@ -2200,13 +2199,15 @@ const pointDraggingUpdates = (
? { ? {
element: suggestedBindingElement, element: suggestedBindingElement,
midPoint: app.state.isMidpointSnappingEnabled midPoint: app.state.isMidpointSnappingEnabled
? snapToMid( ? getSnapOutlineMidPoint(
suggestedBindingElement,
elementsMap,
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
scenePointerX - linearElementEditor.pointerOffset.x, scenePointerX - linearElementEditor.pointerOffset.x,
scenePointerY - linearElementEditor.pointerOffset.y, scenePointerY - linearElementEditor.pointerOffset.y,
), ),
suggestedBindingElement,
elementsMap,
app.state.zoom,
element,
) )
: undefined, : undefined,
} }
@@ -2313,6 +2314,7 @@ const pointDraggingUpdates = (
start.element, start.element,
elementsMap, elementsMap,
app.state.zoom, app.state.zoom,
element,
), ),
} }
: null; : null;
@@ -2352,6 +2354,7 @@ const pointDraggingUpdates = (
end.element, end.element,
elementsMap, elementsMap,
app.state.zoom, app.state.zoom,
element,
), ),
} }
: null; : null;
+6
View File
@@ -17,6 +17,7 @@ import {
} from "@excalidraw/common"; } from "@excalidraw/common";
import type { MarkOptional } from "@excalidraw/common/utility-types"; import type { MarkOptional } from "@excalidraw/common/utility-types";
import type { Zoom } from "@excalidraw/excalidraw/types";
import { bindBindingElement } from "./binding"; import { bindBindingElement } from "./binding";
import { import {
@@ -248,6 +249,7 @@ const bindLinearElementToElement = (
end: ValidLinearElement["end"], end: ValidLinearElement["end"],
elementStore: ElementStore, elementStore: ElementStore,
scene: Scene, scene: Scene,
zoom: Zoom,
): { ): {
linearElement: ExcalidrawLinearElement; linearElement: ExcalidrawLinearElement;
startBoundElement?: ExcalidrawElement; startBoundElement?: ExcalidrawElement;
@@ -335,6 +337,7 @@ const bindLinearElementToElement = (
"orbit", "orbit",
"start", "start",
scene, scene,
zoom,
); );
} }
} }
@@ -411,6 +414,7 @@ const bindLinearElementToElement = (
"orbit", "orbit",
"end", "end",
scene, scene,
zoom,
); );
} }
} }
@@ -696,6 +700,7 @@ export const convertToExcalidrawElements = (
originalEnd, originalEnd,
elementStore, elementStore,
scene, scene,
{ value: 1 } as Zoom,
); );
container = linearElement; container = linearElement;
elementStore.add(linearElement); elementStore.add(linearElement);
@@ -721,6 +726,7 @@ export const convertToExcalidrawElements = (
end, end,
elementStore, elementStore,
scene, scene,
{ value: 1 } as Zoom,
); );
elementStore.add(linearElement); elementStore.add(linearElement);
+146 -21
View File
@@ -8,6 +8,7 @@ import {
import { import {
bezierEquation, bezierEquation,
clamp,
curve, curve,
curveCatmullRomCubicApproxPoints, curveCatmullRomCubicApproxPoints,
curveOffsetPoints, curveOffsetPoints,
@@ -26,7 +27,7 @@ import {
type GlobalPoint, type GlobalPoint,
} from "@excalidraw/math"; } from "@excalidraw/math";
import type { Curve, LineSegment, LocalPoint } from "@excalidraw/math"; import type { Curve, LineSegment, LocalPoint, Radians } from "@excalidraw/math";
import type { import type {
AppState, AppState,
@@ -41,7 +42,7 @@ import { generateLinearCollisionShape } from "./shape";
import { hitElementItself, isPointInElement } from "./collision"; import { hitElementItself, isPointInElement } from "./collision";
import { LinearElementEditor } from "./linearElementEditor"; import { LinearElementEditor } from "./linearElementEditor";
import { isRectangularElement } from "./typeChecks"; import { isRectangularElement } from "./typeChecks";
import { maxBindingDistance_simple } from "./binding"; import { getBindingGap, maxBindingDistance_simple } from "./binding";
import { import {
getGlobalFixedPointForBindableElement, getGlobalFixedPointForBindableElement,
@@ -592,16 +593,135 @@ export const getSnapOutlineMidPoint = (
element: ExcalidrawBindableElement, element: ExcalidrawBindableElement,
elementsMap: ElementsMap, elementsMap: ElementsMap,
zoom: AppState["zoom"], zoom: AppState["zoom"],
) => { arrow: { elbowed: boolean },
): GlobalPoint | undefined => {
const center = elementCenterPoint(element, elementsMap); const center = elementCenterPoint(element, elementsMap);
const TOLERANCE = 0.05;
const maxDistance = maxBindingDistance_simple(zoom) + element.strokeWidth / 2;
const { x, y, width, height, angle } = element;
// snap-to-center point is adaptive to element size, but we don't want to go
// above and below certain px distance
const verticalThreshold = clamp(TOLERANCE * height, 5, maxDistance);
const horizontalThreshold = clamp(TOLERANCE * width, 5, maxDistance);
if (arrow.elbowed) {
const nonRotated = pointRotateRads(point, center, -angle as Radians);
const bindingGap = getBindingGap(element, arrow);
// Too close to the center makes it hard to resolve direction precisely
if (pointDistance(center, nonRotated) < bindingGap) {
return undefined;
}
if (
nonRotated[0] <= x + width / 2 &&
nonRotated[1] > center[1] - verticalThreshold &&
nonRotated[1] < center[1] + verticalThreshold
) {
// LEFT
return pointRotateRads(
pointFrom<GlobalPoint>(x - bindingGap, center[1]),
center,
angle,
);
} else if (
nonRotated[1] <= y + height / 2 &&
nonRotated[0] > center[0] - horizontalThreshold &&
nonRotated[0] < center[0] + horizontalThreshold
) {
// TOP
return pointRotateRads(
pointFrom<GlobalPoint>(center[0], y - bindingGap),
center,
angle,
);
} else if (
nonRotated[0] >= x + width / 2 &&
nonRotated[1] > center[1] - verticalThreshold &&
nonRotated[1] < center[1] + verticalThreshold
) {
// RIGHT
return pointRotateRads(
pointFrom<GlobalPoint>(x + width + bindingGap, center[1]),
center,
angle,
);
} else if (
nonRotated[1] >= y + height / 2 &&
nonRotated[0] > center[0] - horizontalThreshold &&
nonRotated[0] < center[0] + horizontalThreshold
) {
// DOWN
return pointRotateRads(
pointFrom<GlobalPoint>(center[0], y + height + bindingGap),
center,
angle,
);
} else if (element.type === "diamond") {
const distance = bindingGap;
const topLeft = pointFrom<GlobalPoint>(
x + width / 4 - distance,
y + height / 4 - distance,
);
const topRight = pointFrom<GlobalPoint>(
x + (3 * width) / 4 + distance,
y + height / 4 - distance,
);
const bottomLeft = pointFrom<GlobalPoint>(
x + width / 4 - distance,
y + (3 * height) / 4 + distance,
);
const bottomRight = pointFrom<GlobalPoint>(
x + (3 * width) / 4 + distance,
y + (3 * height) / 4 + distance,
);
if (
pointDistance(topLeft, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(topLeft, center, angle);
}
if (
pointDistance(topRight, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(topRight, center, angle);
}
if (
pointDistance(bottomLeft, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(bottomLeft, center, angle);
}
if (
pointDistance(bottomRight, nonRotated) <
Math.max(horizontalThreshold, verticalThreshold)
) {
return pointRotateRads(bottomRight, center, angle);
}
}
return undefined;
}
const sideMidpoints = const sideMidpoints =
element.type === "diamond" element.type === "diamond"
? getDiamondBaseCorners(element).map((curve) => { ? getDiamondBaseCorners(element)
const point = bezierEquation(curve, 0.5); .map((curve) => {
const rotatedPoint = pointRotateRads(point, center, element.angle); const point = bezierEquation(curve, 0.5);
const rotatedPoint = pointRotateRads(point, center, element.angle);
return pointFrom<GlobalPoint>(rotatedPoint[0], rotatedPoint[1]); return pointFrom<GlobalPoint>(rotatedPoint[0], rotatedPoint[1]);
}) })
.map((midpoint) => {
return pointFrom<GlobalPoint>(
midpoint[0] + (midpoint[0] - center[0]) * 0.1,
midpoint[1] + (midpoint[1] - center[1]) * 0.1,
);
})
: [ : [
// RIGHT midpoint // RIGHT midpoint
pointRotateRads( pointRotateRads(
@@ -634,20 +754,24 @@ export const getSnapOutlineMidPoint = (
element.angle, element.angle,
), ),
]; ];
const candidate = sideMidpoints.find(
(midpoint) =>
pointDistance(point, midpoint) <=
maxBindingDistance_simple(zoom) + element.strokeWidth / 2 &&
!hitElementItself({
point,
element,
threshold: 0,
elementsMap,
overrideShouldTestInside: true,
}),
);
return candidate; return sideMidpoints
.map((midpoint, i) => {
const threshold = i % 2 === 0 ? horizontalThreshold : verticalThreshold;
return pointDistance(midpoint, point) <= threshold ? midpoint : undefined;
})
.find(
(midpoint) =>
midpoint &&
!hitElementItself({
point,
element,
threshold: 0,
elementsMap,
overrideShouldTestInside: true,
}),
);
}; };
export const projectFixedPointOntoDiagonal = ( export const projectFixedPointOntoDiagonal = (
@@ -670,6 +794,7 @@ export const projectFixedPointOntoDiagonal = (
element, element,
elementsMap, elementsMap,
zoom, zoom,
arrow,
); );
if (sideMidPoint) { if (sideMidPoint) {
return sideMidPoint; return sideMidPoint;
+7 -2
View File
@@ -16,6 +16,7 @@ import "@excalidraw/utils/test-utils";
import { bindBindingElement } from "@excalidraw/element"; import { bindBindingElement } from "@excalidraw/element";
import type { LocalPoint } from "@excalidraw/math"; import type { LocalPoint } from "@excalidraw/math";
import type { Zoom } from "@excalidraw/excalidraw/types";
import { Scene } from "../src/Scene"; import { Scene } from "../src/Scene";
@@ -187,8 +188,12 @@ describe("elbow arrow routing", () => {
}) as ExcalidrawElbowArrowElement; }) as ExcalidrawElbowArrowElement;
API.setElements([rectangle1, rectangle2, arrow]); API.setElements([rectangle1, rectangle2, arrow]);
bindBindingElement(arrow, rectangle1, "orbit", "start", h.scene); bindBindingElement(arrow, rectangle1, "orbit", "start", h.scene, {
bindBindingElement(arrow, rectangle2, "orbit", "end", h.scene); value: 1,
} as Zoom);
bindBindingElement(arrow, rectangle2, "orbit", "end", h.scene, {
value: 1,
} as Zoom);
expect(arrow.startBinding).not.toBe(null); expect(arrow.startBinding).not.toBe(null);
expect(arrow.endBinding).not.toBe(null); expect(arrow.endBinding).not.toBe(null);
@@ -1897,6 +1897,7 @@ export const actionChangeArrowType = register<keyof typeof ARROW_TYPE>({
startElement, startElement,
"start", "start",
elementsMap, elementsMap,
appState.zoom,
appState.isBindingEnabled, appState.isBindingEnabled,
), ),
} }
@@ -1911,6 +1912,7 @@ export const actionChangeArrowType = register<keyof typeof ARROW_TYPE>({
endElement, endElement,
"end", "end",
elementsMap, elementsMap,
appState.zoom,
appState.isBindingEnabled, appState.isBindingEnabled,
), ),
} }
@@ -1943,6 +1945,7 @@ export const actionChangeArrowType = register<keyof typeof ARROW_TYPE>({
appState.bindMode === "inside" ? "inside" : "orbit", appState.bindMode === "inside" ? "inside" : "orbit",
"start", "start",
app.scene, app.scene,
appState.zoom,
); );
} }
} }
@@ -1957,6 +1960,7 @@ export const actionChangeArrowType = register<keyof typeof ARROW_TYPE>({
appState.bindMode === "inside" ? "inside" : "orbit", appState.bindMode === "inside" ? "inside" : "orbit",
"end", "end",
app.scene, app.scene,
appState.zoom,
); );
} }
} }
+5
View File
@@ -7102,6 +7102,9 @@ class App extends React.Component<AppProps, AppState> {
hoveredElement, hoveredElement,
elementsMap, elementsMap,
this.state.zoom, this.state.zoom,
{
elbowed: this.state.currentItemArrowType === ARROW_TYPE.elbow,
},
), ),
}, },
}); });
@@ -7296,6 +7299,7 @@ class App extends React.Component<AppProps, AppState> {
hit, hit,
elementsMap, elementsMap,
this.state.zoom, this.state.zoom,
{ elbowed: this.state.currentItemArrowType === ARROW_TYPE.elbow },
), ),
}, },
}); });
@@ -9490,6 +9494,7 @@ class App extends React.Component<AppProps, AppState> {
boundElement, boundElement,
elementsMap, elementsMap,
this.state.zoom, this.state.zoom,
element,
), ),
} }
: null, : null,
@@ -17,7 +17,7 @@ import { EditorLocalStorage } from "../../data/EditorLocalStorage";
import type { MermaidToExcalidrawLibProps } from "./types"; import type { MermaidToExcalidrawLibProps } from "./types";
import type { AppClassProperties, BinaryFiles } from "../../types"; import type { AppClassProperties, BinaryFiles, Zoom } from "../../types";
export const resetPreview = ({ export const resetPreview = ({
canvasRef, canvasRef,
@@ -2374,7 +2374,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"endBinding": { "endBinding": {
"elementId": "id1", "elementId": "id1",
"fixedPoint": [ "fixedPoint": [
0, "0.50010",
"0.50010", "0.50010",
], ],
"mode": "orbit", "mode": "orbit",
@@ -2382,7 +2382,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": "439.20000", "height": "399.26547",
"id": "id4", "id": "id4",
"index": "a2", "index": "a2",
"isDeleted": false, "isDeleted": false,
@@ -2396,8 +2396,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
0, 0,
], ],
[ [
488, "488.00000",
"-439.20000", "-399.26547",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -2419,9 +2419,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"type": "arrow", "type": "arrow",
"updated": 1, "updated": 1,
"version": 11, "version": 11,
"width": 488, "width": "488.00000",
"x": 6, "x": 6,
"y": "-5.39000", "y": "-4.89900",
} }
`; `;
@@ -2542,7 +2542,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"endBinding": { "endBinding": {
"elementId": "id1", "elementId": "id1",
"fixedPoint": [ "fixedPoint": [
0, "0.50010",
"0.50010", "0.50010",
], ],
"mode": "orbit", "mode": "orbit",
@@ -2550,7 +2550,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": "439.20000", "height": "399.26547",
"index": "a2", "index": "a2",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@@ -2562,8 +2562,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
0, 0,
], ],
[ [
488, "488.00000",
"-439.20000", "-399.26547",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -2584,9 +2584,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"strokeWidth": 2, "strokeWidth": 2,
"type": "arrow", "type": "arrow",
"version": 11, "version": 11,
"width": 488, "width": "488.00000",
"x": 6, "x": 6,
"y": "-5.39000", "y": "-4.89900",
}, },
"inserted": { "inserted": {
"isDeleted": true, "isDeleted": true,
@@ -16703,7 +16703,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"id": "id13", "id": "id13",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
@@ -16718,7 +16718,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -16729,8 +16729,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -16742,7 +16742,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 10, "version": 10,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
} }
`; `;
@@ -16787,8 +16787,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -16807,8 +16807,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -17121,7 +17121,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@@ -17134,7 +17134,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -17145,8 +17145,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -17157,7 +17157,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 7, "version": 7,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
}, },
"inserted": { "inserted": {
"isDeleted": true, "isDeleted": true,
@@ -17451,7 +17451,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"id": "id13", "id": "id13",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
@@ -17466,7 +17466,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -17477,8 +17477,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -17490,7 +17490,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 10, "version": 10,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
} }
`; `;
@@ -17759,7 +17759,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@@ -17772,7 +17772,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -17783,8 +17783,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -17795,7 +17795,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 10, "version": 10,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
}, },
"inserted": { "inserted": {
"isDeleted": true, "isDeleted": true,
@@ -18097,7 +18097,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"id": "id13", "id": "id13",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
@@ -18112,7 +18112,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -18123,8 +18123,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -18136,7 +18136,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 10, "version": 10,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
} }
`; `;
@@ -18405,7 +18405,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@@ -18418,7 +18418,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -18429,8 +18429,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -18441,7 +18441,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 10, "version": 10,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
}, },
"inserted": { "inserted": {
"isDeleted": true, "isDeleted": true,
@@ -18741,7 +18741,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"id": "id13", "id": "id13",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
@@ -18756,7 +18756,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -18767,8 +18767,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -18780,7 +18780,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 10, "version": 10,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
} }
`; `;
@@ -18841,8 +18841,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -19135,7 +19135,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@@ -19148,7 +19148,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -19159,8 +19159,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -19171,7 +19171,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 7, "version": 7,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
}, },
"inserted": { "inserted": {
"isDeleted": true, "isDeleted": true,
@@ -19493,7 +19493,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"id": "id13", "id": "id13",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
@@ -19508,7 +19508,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -19519,8 +19519,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -19532,7 +19532,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 11, "version": 11,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
} }
`; `;
@@ -19604,8 +19604,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -19883,7 +19883,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": 0, "height": "0.00661",
"index": "a3", "index": "a3",
"isDeleted": false, "isDeleted": false,
"link": null, "link": null,
@@ -19896,7 +19896,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
], ],
[ [
"88.00000", "88.00000",
0, "-0.00661",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -19907,8 +19907,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"startBinding": { "startBinding": {
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
1, "0.50021",
"0.50010", "0.50021",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -19919,7 +19919,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
"version": 7, "version": 7,
"width": "88.00000", "width": "88.00000",
"x": 6, "x": 6,
"y": "0.01000", "y": "0.01706",
}, },
"inserted": { "inserted": {
"isDeleted": true, "isDeleted": true,
@@ -182,14 +182,14 @@ exports[`move element > rectangles with binding arrow 7`] = `
"elementId": "id3", "elementId": "id3",
"fixedPoint": [ "fixedPoint": [
"-0.02000", "-0.02000",
"0.48010", "0.47928",
], ],
"mode": "orbit", "mode": "orbit",
}, },
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": "90.01760", "height": "93.60377",
"id": "id6", "id": "id6",
"index": "a2", "index": "a2",
"isDeleted": false, "isDeleted": false,
@@ -204,7 +204,7 @@ exports[`move element > rectangles with binding arrow 7`] = `
], ],
[ [
89, 89,
"90.01760", "93.60377",
], ],
], ],
"roughness": 1, "roughness": 1,
@@ -217,7 +217,7 @@ exports[`move element > rectangles with binding arrow 7`] = `
"elementId": "id0", "elementId": "id0",
"fixedPoint": [ "fixedPoint": [
"1.06000", "1.06000",
"0.56011", "0.52181",
], ],
"mode": "orbit", "mode": "orbit",
}, },
@@ -230,6 +230,6 @@ exports[`move element > rectangles with binding arrow 7`] = `
"versionNonce": 271613161, "versionNonce": 271613161,
"width": 89, "width": 89,
"x": 106, "x": 106,
"y": "56.01120", "y": "52.18052",
} }
`; `;
+16 -6
View File
@@ -1590,7 +1590,9 @@ describe("history", () => {
expect(API.getUndoStack().length).toBe(5); expect(API.getUndoStack().length).toBe(5);
expect(arrow.startBinding).toEqual({ expect(arrow.startBinding).toEqual({
elementId: rect1.id, elementId: rect1.id,
fixedPoint: expect.arrayContaining([1, 0.5001]), fixedPoint: expect.arrayContaining([
0.5002127206977238, 0.5002127206977238,
]),
mode: "orbit", mode: "orbit",
}); });
expect(arrow.endBinding).toEqual({ expect(arrow.endBinding).toEqual({
@@ -1613,7 +1615,9 @@ describe("history", () => {
expect(API.getRedoStack().length).toBe(1); expect(API.getRedoStack().length).toBe(1);
expect(arrow.startBinding).toEqual({ expect(arrow.startBinding).toEqual({
elementId: rect1.id, elementId: rect1.id,
fixedPoint: expect.arrayContaining([1, 0.5001]), fixedPoint: expect.arrayContaining([
0.5002127206977238, 0.5002127206977238,
]),
mode: "orbit", mode: "orbit",
}); });
expect(arrow.endBinding).toEqual({ expect(arrow.endBinding).toEqual({
@@ -1636,7 +1640,9 @@ describe("history", () => {
expect(API.getRedoStack().length).toBe(0); expect(API.getRedoStack().length).toBe(0);
expect(arrow.startBinding).toEqual({ expect(arrow.startBinding).toEqual({
elementId: rect1.id, elementId: rect1.id,
fixedPoint: expect.arrayContaining([1, 0.5001]), fixedPoint: expect.arrayContaining([
0.5002127206977238, 0.5002127206977238,
]),
mode: "orbit", mode: "orbit",
}); });
expect(arrow.endBinding).toEqual({ expect(arrow.endBinding).toEqual({
@@ -1667,7 +1673,9 @@ describe("history", () => {
expect(API.getRedoStack().length).toBe(0); expect(API.getRedoStack().length).toBe(0);
expect(arrow.startBinding).toEqual({ expect(arrow.startBinding).toEqual({
elementId: rect1.id, elementId: rect1.id,
fixedPoint: expect.arrayContaining([1, 0.5001]), fixedPoint: expect.arrayContaining([
0.5002127206977238, 0.5002127206977238,
]),
mode: "orbit", mode: "orbit",
}); });
expect(arrow.endBinding).toEqual({ expect(arrow.endBinding).toEqual({
@@ -1690,7 +1698,9 @@ describe("history", () => {
expect(API.getRedoStack().length).toBe(1); expect(API.getRedoStack().length).toBe(1);
expect(arrow.startBinding).toEqual({ expect(arrow.startBinding).toEqual({
elementId: rect1.id, elementId: rect1.id,
fixedPoint: expect.arrayContaining([1, 0.5001]), fixedPoint: expect.arrayContaining([
0.5002127206977238, 0.5002127206977238,
]),
mode: "orbit", mode: "orbit",
}); });
expect(arrow.endBinding).toEqual({ expect(arrow.endBinding).toEqual({
@@ -5132,7 +5142,7 @@ describe("history", () => {
}), }),
endBinding: expect.objectContaining({ endBinding: expect.objectContaining({
elementId: rect2.id, elementId: rect2.id,
fixedPoint: expect.arrayContaining([0, 0.5001]), fixedPoint: expect.arrayContaining([0.5001, 0.5001]),
}), }),
isDeleted: true, isDeleted: true,
}), }),
+14 -4
View File
@@ -16,6 +16,8 @@ import * as StaticScene from "../renderer/staticScene";
import { UI, Pointer, Keyboard } from "./helpers/ui"; import { UI, Pointer, Keyboard } from "./helpers/ui";
import { render, fireEvent, act, unmountComponent } from "./test-utils"; import { render, fireEvent, act, unmountComponent } from "./test-utils";
import type { Zoom } from "../types";
unmountComponent(); unmountComponent();
const renderInteractiveScene = vi.spyOn( const renderInteractiveScene = vi.spyOn(
@@ -88,6 +90,7 @@ describe("move element", () => {
"orbit", "orbit",
"start", "start",
h.app.scene, h.app.scene,
{ value: 1 } as Zoom,
); );
bindBindingElement( bindBindingElement(
arrow.get() as NonDeleted<ExcalidrawArrowElement>, arrow.get() as NonDeleted<ExcalidrawArrowElement>,
@@ -95,6 +98,7 @@ describe("move element", () => {
"orbit", "orbit",
"end", "end",
h.app.scene, h.app.scene,
{ value: 1 } as Zoom,
); );
}); });
@@ -111,10 +115,13 @@ describe("move element", () => {
expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectA.x, rectA.y]).toEqual([0, 0]);
expect([rectB.x, rectB.y]).toEqual([200, 0]); expect([rectB.x, rectB.y]).toEqual([200, 0]);
expect([[arrow.x, arrow.y]]).toCloselyEqualPoints( expect([[arrow.x, arrow.y]]).toCloselyEqualPoints(
[[106.00000000000001, 55.6867741935484]], [[106, 52.18052313249668]],
0,
);
expect([[arrow.width, arrow.height]]).toCloselyEqualPoints(
[[88, 91.60376557808824]],
0, 0,
); );
expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[88, 88]], 0);
renderInteractiveScene.mockClear(); renderInteractiveScene.mockClear();
renderStaticScene.mockClear(); renderStaticScene.mockClear();
@@ -133,10 +140,13 @@ describe("move element", () => {
expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectA.x, rectA.y]).toEqual([0, 0]);
expect([rectB.x, rectB.y]).toEqual([201, 2]); expect([rectB.x, rectB.y]).toEqual([201, 2]);
expect([[arrow.x, arrow.y]]).toCloselyEqualPoints( expect([[arrow.x, arrow.y]]).toCloselyEqualPoints(
[[106, 55.6867741935484]], [[106, 52.18052313249668]],
0,
);
expect([[arrow.width, arrow.height]]).toCloselyEqualPoints(
[[89, 93.60376557808823]],
0, 0,
); );
expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[89, 90]], 0);
h.elements.forEach((element) => expect(element).toMatchSnapshot()); h.elements.forEach((element) => expect(element).toMatchSnapshot());
}); });