fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap (#7663)

* fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap

* lint

* fix

* use non deleted elements where possible

* use non deleted elements map in actions

* pass elementsMap instead of array to elementOverlapsWithFrame

* lint

* fix

* pass elementsMap to getElementsCorners

* pass elementsMap to getEligibleElementsForBinding

* pass elementsMap in bindOrUnbindSelectedElements and unbindLinearElements

* pass elementsMap in elementsAreInFrameBounds,elementOverlapsWithFrame,isCursorInFrame,getElementsInResizingFrame

* pass elementsMap in getElementsWithinSelection, getElementsCompletelyInFrame, isElementContainingFrame, getElementsInNewFrame

* pass elementsMap to getElementWithTransformHandleType

* pass elementsMap to getVisibleGaps, getMaximumGroups,getReferenceSnapPoints,snapDraggedElements

* lint

* pass elementsMap to bindTextToShapeAfterDuplication,bindLinearElementToElement,getTextBindableContainerAtPosition

* revert changes for bindTextToShapeAfterDuplication
This commit is contained in:
Aakansha Doshi 2024-02-16 11:35:01 +05:30 committed by GitHub
parent 73bf50e8a8
commit 47f87f4ecb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 779 additions and 270 deletions

View file

@ -5,6 +5,7 @@ import { getTransformHandles } from "../element/transformHandles";
import { API } from "./helpers/api";
import { KEYS } from "../keys";
import { actionWrapTextInContainer } from "../actions/actionBoundText";
import { arrayToMap } from "../utils";
const { h } = window;
@ -91,8 +92,12 @@ describe("element binding", () => {
expect(arrow.startBinding?.elementId).toBe(rectLeft.id);
expect(arrow.endBinding?.elementId).toBe(rectRight.id);
const rotation = getTransformHandles(arrow, h.state.zoom, "mouse")
.rotation!;
const rotation = getTransformHandles(
arrow,
h.state.zoom,
arrayToMap(h.elements),
"mouse",
).rotation!;
const rotationHandleX = rotation[0] + rotation[2] / 2;
const rotationHandleY = rotation[1] + rotation[3] / 2;
mouse.down(rotationHandleX, rotationHandleY);

View file

@ -27,7 +27,7 @@ import * as blob from "../data/blob";
import { KEYS } from "../keys";
import { getBoundTextElementPosition } from "../element/textElement";
import { createPasteEvent } from "../clipboard";
import { cloneJSON } from "../utils";
import { arrayToMap, cloneJSON } from "../utils";
const { h } = window;
const mouse = new Pointer("mouse");
@ -194,9 +194,10 @@ const checkElementsBoundingBox = async (
element2: ExcalidrawElement,
toleranceInPx: number = 0,
) => {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element1);
const elementsMap = arrayToMap([element1, element2]);
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element1, elementsMap);
const [x12, y12, x22, y22] = getElementAbsoluteCoords(element2);
const [x12, y12, x22, y22] = getElementAbsoluteCoords(element2, elementsMap);
await waitFor(() => {
// Check if width and height did not change
@ -853,7 +854,11 @@ describe("mutliple elements", () => {
h.app.actionManager.executeAction(actionFlipVertical);
const arrowText = h.elements[1] as ExcalidrawTextElementWithContainer;
const arrowTextPos = getBoundTextElementPosition(arrow.get(), arrowText)!;
const arrowTextPos = getBoundTextElementPosition(
arrow.get(),
arrowText,
arrayToMap(h.elements),
)!;
const rectText = h.elements[3] as ExcalidrawTextElementWithContainer;
expect(arrow.x).toBeCloseTo(180);

View file

@ -32,6 +32,7 @@ import {
import { getCommonBounds, getElementPointsCoords } from "../../element/bounds";
import { rotatePoint } from "../../math";
import { getTextEditor } from "../queries/dom";
import { arrayToMap } from "../../utils";
const { h } = window;
@ -286,9 +287,12 @@ const transform = (
let handleCoords: TransformHandle | undefined;
if (elements.length === 1) {
handleCoords = getTransformHandles(elements[0], h.state.zoom, "mouse")[
handle
];
handleCoords = getTransformHandles(
elements[0],
h.state.zoom,
arrayToMap(h.elements),
"mouse",
)[handle];
} else {
const [x1, y1, x2, y2] = getCommonBounds(elements);
const isFrameSelected = elements.some(isFrameLikeElement);

View file

@ -343,6 +343,8 @@ describe("Test Linear Elements", () => {
});
it("should update all the midpoints when element position changed", async () => {
const elementsMap = arrayToMap(h.elements);
createThreePointerLinearElement("line", {
type: ROUNDNESS.PROPORTIONAL_RADIUS,
});
@ -351,7 +353,10 @@ describe("Test Linear Elements", () => {
expect(line.points.length).toEqual(3);
enterLineEditingMode(line);
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
expect([line.x, line.y]).toEqual(points[0]);
const midPoints = LinearElementEditor.getEditorMidPoints(
@ -465,7 +470,11 @@ describe("Test Linear Elements", () => {
});
it("should update only the first segment midpoint when its point is dragged", async () => {
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const elementsMap = arrayToMap(h.elements);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
const midPoints = LinearElementEditor.getEditorMidPoints(
line,
h.app.scene.getNonDeletedElementsMap(),
@ -482,7 +491,10 @@ describe("Test Linear Elements", () => {
);
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`8`);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(line);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
expect([newPoints[0][0], newPoints[0][1]]).toEqual([
points[0][0] - delta,
points[0][1] - delta,
@ -499,7 +511,11 @@ describe("Test Linear Elements", () => {
});
it("should hide midpoints in the segment when points moved close", async () => {
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const elementsMap = arrayToMap(h.elements);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
const midPoints = LinearElementEditor.getEditorMidPoints(
line,
h.app.scene.getNonDeletedElementsMap(),
@ -516,7 +532,10 @@ describe("Test Linear Elements", () => {
);
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`8`);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(line);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
expect([newPoints[0][0], newPoints[0][1]]).toEqual([
points[0][0] + delta,
points[0][1] + delta,
@ -535,7 +554,10 @@ describe("Test Linear Elements", () => {
it("should remove the midpoint when one of the points in the segment is deleted", async () => {
const line = h.elements[0] as ExcalidrawLinearElement;
enterLineEditingMode(line);
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
arrayToMap(h.elements),
);
// dragging line from last segment midpoint
drag(lastSegmentMidpoint, [
@ -637,7 +659,11 @@ describe("Test Linear Elements", () => {
});
it("should update all the midpoints when its point is dragged", async () => {
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const elementsMap = arrayToMap(h.elements);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
const midPoints = LinearElementEditor.getEditorMidPoints(
line,
h.app.scene.getNonDeletedElementsMap(),
@ -649,7 +675,10 @@ describe("Test Linear Elements", () => {
// Drag from first point
drag(hitCoords, [hitCoords[0] - delta, hitCoords[1] - delta]);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(line);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
expect([newPoints[0][0], newPoints[0][1]]).toEqual([
points[0][0] - delta,
points[0][1] - delta,
@ -678,7 +707,11 @@ describe("Test Linear Elements", () => {
});
it("should hide midpoints in the segment when points moved close", async () => {
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const elementsMap = arrayToMap(h.elements);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
const midPoints = LinearElementEditor.getEditorMidPoints(
line,
h.app.scene.getNonDeletedElementsMap(),
@ -695,7 +728,10 @@ describe("Test Linear Elements", () => {
);
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`8`);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(line);
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
expect([newPoints[0][0], newPoints[0][1]]).toEqual([
points[0][0] + delta,
points[0][1] + delta,
@ -712,6 +748,8 @@ describe("Test Linear Elements", () => {
});
it("should update all the midpoints when a point is deleted", async () => {
const elementsMap = arrayToMap(h.elements);
drag(lastSegmentMidpoint, [
lastSegmentMidpoint[0] + delta,
lastSegmentMidpoint[1] + delta,
@ -723,7 +761,10 @@ describe("Test Linear Elements", () => {
h.app.scene.getNonDeletedElementsMap(),
h.state,
);
const points = LinearElementEditor.getPointsGlobalCoordinates(line);
const points = LinearElementEditor.getPointsGlobalCoordinates(
line,
elementsMap,
);
// delete 3rd point
deletePoint(points[2]);
@ -837,6 +878,7 @@ describe("Test Linear Elements", () => {
const position = LinearElementEditor.getBoundTextElementPosition(
container,
textElement,
arrayToMap(h.elements),
);
expect(position).toMatchInlineSnapshot(`
{
@ -859,6 +901,7 @@ describe("Test Linear Elements", () => {
const position = LinearElementEditor.getBoundTextElementPosition(
container,
textElement,
arrayToMap(h.elements),
);
expect(position).toMatchInlineSnapshot(`
{
@ -893,6 +936,7 @@ describe("Test Linear Elements", () => {
const position = LinearElementEditor.getBoundTextElementPosition(
container,
textElement,
arrayToMap(h.elements),
);
expect(position).toMatchInlineSnapshot(`
{
@ -1012,8 +1056,13 @@ describe("Test Linear Elements", () => {
);
expect(container.width).toBe(70);
expect(container.height).toBe(50);
expect(getBoundTextElementPosition(container, textElement))
.toMatchInlineSnapshot(`
expect(
getBoundTextElementPosition(
container,
textElement,
arrayToMap(h.elements),
),
).toMatchInlineSnapshot(`
{
"x": 75,
"y": 60,
@ -1051,8 +1100,13 @@ describe("Test Linear Elements", () => {
}
`);
expect(getBoundTextElementPosition(container, textElement))
.toMatchInlineSnapshot(`
expect(
getBoundTextElementPosition(
container,
textElement,
arrayToMap(h.elements),
),
).toMatchInlineSnapshot(`
{
"x": 271.11716195150507,
"y": 45,
@ -1090,7 +1144,8 @@ describe("Test Linear Elements", () => {
arrow,
);
expect(container.width).toBe(40);
expect(getBoundTextElementPosition(container, textElement))
const elementsMap = arrayToMap(h.elements);
expect(getBoundTextElementPosition(container, textElement, elementsMap))
.toMatchInlineSnapshot(`
{
"x": 25,
@ -1102,7 +1157,10 @@ describe("Test Linear Elements", () => {
collaboration made
easy"
`);
const points = LinearElementEditor.getPointsGlobalCoordinates(container);
const points = LinearElementEditor.getPointsGlobalCoordinates(
container,
elementsMap,
);
// Drag from last point
drag(points[1], [points[1][0] + 300, points[1][1]]);
@ -1115,7 +1173,7 @@ describe("Test Linear Elements", () => {
}
`);
expect(getBoundTextElementPosition(container, textElement))
expect(getBoundTextElementPosition(container, textElement, elementsMap))
.toMatchInlineSnapshot(`
{
"x": 75,

View file

@ -13,6 +13,7 @@ import {
import { UI, Pointer, Keyboard } from "./helpers/ui";
import { KEYS } from "../keys";
import { vi } from "vitest";
import { arrayToMap } from "../utils";
// Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
@ -75,12 +76,13 @@ describe("move element", () => {
const rectA = UI.createElement("rectangle", { size: 100 });
const rectB = UI.createElement("rectangle", { x: 200, y: 0, size: 300 });
const line = UI.createElement("line", { x: 110, y: 50, size: 80 });
const elementsMap = arrayToMap(h.elements);
// bind line to two rectangles
bindOrUnbindLinearElement(
line.get() as NonDeleted<ExcalidrawLinearElement>,
rectA.get() as ExcalidrawRectangleElement,
rectB.get() as ExcalidrawRectangleElement,
elementsMap,
);
// select the second rectangles

View file

@ -13,6 +13,7 @@ import { API } from "./helpers/api";
import { KEYS } from "../keys";
import { isLinearElement } from "../element/typeChecks";
import { LinearElementEditor } from "../element/linearElementEditor";
import { arrayToMap } from "../utils";
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
@ -301,10 +302,12 @@ describe("arrow element", () => {
],
});
const label = await UI.editText(arrow, "Hello");
const elementsMap = arrayToMap(h.elements);
UI.resize(arrow, "se", [50, 30]);
let labelPos = LinearElementEditor.getBoundTextElementPosition(
arrow,
label,
elementsMap,
);
expect(labelPos.x + label.width / 2).toBeCloseTo(
@ -317,7 +320,11 @@ describe("arrow element", () => {
expect(label.fontSize).toEqual(20);
UI.resize(arrow, "w", [20, 0]);
labelPos = LinearElementEditor.getBoundTextElementPosition(arrow, label);
labelPos = LinearElementEditor.getBoundTextElementPosition(
arrow,
label,
elementsMap,
);
expect(labelPos.x + label.width / 2).toBeCloseTo(
arrow.x + arrow.points[2][0],
@ -743,15 +750,17 @@ describe("multiple selection", () => {
const selectionTop = 20 - topArrowLabel.height / 2;
const move = [80, 0] as [number, number];
const scale = move[0] / selectionWidth + 1;
const elementsMap = arrayToMap(h.elements);
UI.resize([topArrow.get(), bottomArrow.get()], "se", move);
const topArrowLabelPos = LinearElementEditor.getBoundTextElementPosition(
topArrow,
topArrowLabel,
elementsMap,
);
const bottomArrowLabelPos = LinearElementEditor.getBoundTextElementPosition(
bottomArrow,
bottomArrowLabel,
elementsMap,
);
expect(topArrow.x).toBeCloseTo(0);
@ -944,12 +953,13 @@ describe("multiple selection", () => {
const scaleX = move[0] / selectionWidth + 1;
const scaleY = -scaleX;
const lineOrigBounds = getBoundsFromPoints(line);
const elementsMap = arrayToMap(h.elements);
UI.resize([line, image, rectangle, boundArrow], "se", move);
const lineNewBounds = getBoundsFromPoints(line);
const arrowLabelPos = LinearElementEditor.getBoundTextElementPosition(
boundArrow,
arrowLabel,
elementsMap,
);
expect(line.x).toBeCloseTo(60 * scaleX);