diff --git a/excalidraw-app/data/LocalData.ts b/excalidraw-app/data/LocalData.ts index 9ad6dc9256..35a6837b7d 100644 --- a/excalidraw-app/data/LocalData.ts +++ b/excalidraw-app/data/LocalData.ts @@ -16,7 +16,6 @@ import { DEFAULT_SIDEBAR, debounce, } from "@excalidraw/common"; -import { clearElementsForLocalStorage } from "@excalidraw/element"; import { createStore, entries, @@ -81,7 +80,7 @@ const saveDataStateToLocalStorage = ( localStorage.setItem( STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS, - JSON.stringify(clearElementsForLocalStorage(elements)), + JSON.stringify(elements), ); localStorage.setItem( STORAGE_KEYS.LOCAL_STORAGE_APP_STATE, diff --git a/excalidraw-app/data/localStorage.ts b/excalidraw-app/data/localStorage.ts index bc0df4a678..28c166cd74 100644 --- a/excalidraw-app/data/localStorage.ts +++ b/excalidraw-app/data/localStorage.ts @@ -2,7 +2,6 @@ import { clearAppStateForLocalStorage, getDefaultAppState, } from "@excalidraw/excalidraw/appState"; -import { clearElementsForLocalStorage } from "@excalidraw/element"; import type { ExcalidrawElement } from "@excalidraw/element/types"; import type { AppState } from "@excalidraw/excalidraw/types"; @@ -50,7 +49,7 @@ export const importFromLocalStorage = () => { let elements: ExcalidrawElement[] = []; if (savedElements) { try { - elements = clearElementsForLocalStorage(JSON.parse(savedElements)); + elements = JSON.parse(savedElements); } catch (error: any) { console.error(error); // Do nothing because elements array is already empty diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index 01d153bf61..fa79eda26f 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -278,7 +278,7 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = ( // With new arrows it represents the continuous dragging of the end point if (endDragged) { - const origin = appState?.selectedLinearElement?.pointerDownState.origin; + const origin = appState?.selectedLinearElement?.initialState.origin; // Inside -> inside binding if (hit && arrow.startBinding?.elementId === hit.id) { @@ -309,7 +309,7 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = ( invariant(otherElement, "Other element must be in the elements map"); const otherIsInsideBinding = - !!appState.selectedLinearElement?.pointerDownState.arrowStartIsInside; + !!appState.selectedLinearElement?.initialState.arrowStartIsInside; const other: BindingStrategy = { mode: otherIsInsideBinding ? "inside" : "orbit", diff --git a/packages/element/src/index.ts b/packages/element/src/index.ts index 4fc1ef5579..b8427a2923 100644 --- a/packages/element/src/index.ts +++ b/packages/element/src/index.ts @@ -1,7 +1,6 @@ import { toIterable } from "@excalidraw/common"; import { isInvisiblySmallElement } from "./sizeHelpers"; -import { isLinearElementType } from "./typeChecks"; import type { ExcalidrawElement, @@ -52,27 +51,6 @@ export const isNonDeletedElement = ( element: T, ): element is NonDeleted => !element.isDeleted; -const _clearElements = ( - elements: readonly ExcalidrawElement[], -): ExcalidrawElement[] => - getNonDeletedElements(elements).map((element) => - isLinearElementType(element.type) - ? { ...element, lastCommittedPoint: null } - : element, - ); - -export const clearElementsForDatabase = ( - elements: readonly ExcalidrawElement[], -) => _clearElements(elements); - -export const clearElementsForExport = ( - elements: readonly ExcalidrawElement[], -) => _clearElements(elements); - -export const clearElementsForLocalStorage = ( - elements: readonly ExcalidrawElement[], -) => _clearElements(elements); - export * from "./align"; export * from "./binding"; export * from "./bounds"; diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 70a3432a7c..5e742d0569 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -126,7 +126,7 @@ export class LinearElementEditor { /** indices */ public readonly selectedPointsIndices: readonly number[] | null; - public readonly pointerDownState: Readonly<{ + public readonly initialState: Readonly<{ prevSelectedPointsIndices: readonly number[] | null; /** index */ lastClickedPoint: number; @@ -142,6 +142,7 @@ export class LinearElementEditor { /** whether you're dragging a point */ public readonly isDragging: boolean; public readonly lastUncommittedPoint: LocalPoint | null; + public readonly lastCommittedPoint: LocalPoint | null; public readonly pointerOffset: Readonly<{ x: number; y: number }>; public readonly hoverPointIndex: number; public readonly segmentMidPointHoveredCoords: GlobalPoint | null; @@ -149,6 +150,11 @@ export class LinearElementEditor { public readonly customLineAngle: number | null; public readonly isEditing: boolean; + // @deprecated renamed to initialState because the data is used during linear + // element click creation as well (with multiple pointer down events) + // @ts-ignore + public readonly pointerDownState: never; + constructor( element: NonDeleted, elementsMap: ElementsMap, @@ -167,9 +173,10 @@ export class LinearElementEditor { } this.selectedPointsIndices = null; this.lastUncommittedPoint = null; + this.lastCommittedPoint = null; this.isDragging = false; this.pointerOffset = { x: 0, y: 0 }; - this.pointerDownState = { + this.initialState = { prevSelectedPointsIndices: null, lastClickedPoint: -1, origin: null, @@ -396,25 +403,31 @@ export class LinearElementEditor { ): Pick | null { const elementsMap = app.scene.getNonDeletedElementsMap(); const elements = app.scene.getNonDeletedElements(); - const { elbowed, elementId, pointerDownState, selectedPointsIndices } = + const { elbowed, elementId, initialState, selectedPointsIndices } = linearElementEditor; - const { lastClickedPoint } = pointerDownState; + const { lastClickedPoint } = initialState; const element = LinearElementEditor.getElement(elementId, elementsMap); invariant(element, "Element being dragged must exist in the scene"); + invariant(element.points.length > 1, "Element must have at least 2 points"); + invariant( selectedPointsIndices, "There must be selected points in order to drag them", ); invariant( - lastClickedPoint > -1 && selectedPointsIndices.includes(lastClickedPoint), - "There must be a valid lastClickedPoint in order to drag it", + lastClickedPoint > -1 && + selectedPointsIndices.includes(lastClickedPoint) && + element.points[lastClickedPoint], + `There must be a valid lastClickedPoint in order to drag it. selectedPointsIndices(${JSON.stringify( + selectedPointsIndices, + )}) points(0..${ + element.points.length - 1 + }) lastClickedPoint(${lastClickedPoint})`, ); - invariant(element.points.length > 1, "Element must have at least 2 points"); - invariant( !elbowed || selectedPointsIndices?.filter( @@ -551,8 +564,8 @@ export class LinearElementEditor { const newLinearElementEditor = { ...linearElementEditor, selectedPointsIndices: newSelectedPointsIndices, - pointerDownState: { - ...linearElementEditor.pointerDownState, + initialState: { + ...linearElementEditor.initialState, lastClickedPoint: newLastClickedPoint, }, segmentMidPointHoveredCoords: newSelectedMidPointHoveredCoords, @@ -575,8 +588,12 @@ export class LinearElementEditor { ): LinearElementEditor { const elementsMap = scene.getNonDeletedElementsMap(); - const { elementId, selectedPointsIndices, isDragging, pointerDownState } = - editingLinearElement; + const { + elementId, + selectedPointsIndices, + isDragging, + initialState: pointerDownState, + } = editingLinearElement; const element = LinearElementEditor.getElement(elementId, elementsMap); if (!element) { return editingLinearElement; @@ -647,8 +664,8 @@ export class LinearElementEditor { isDragging: false, pointerOffset: { x: 0, y: 0 }, customLineAngle: null, - pointerDownState: { - ...editingLinearElement.pointerDownState, + initialState: { + ...editingLinearElement.initialState, origin: null, arrowStartIsInside: false, }, @@ -948,7 +965,7 @@ export class LinearElementEditor { store.scheduleCapture(); ret.linearElementEditor = { ...linearElementEditor, - pointerDownState: { + initialState: { prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices, lastClickedPoint: -1, origin: pointFrom(scenePointer.x, scenePointer.y), @@ -1009,7 +1026,7 @@ export class LinearElementEditor { : null; ret.linearElementEditor = { ...linearElementEditor, - pointerDownState: { + initialState: { prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices, lastClickedPoint: clickedPointIndex, origin: pointFrom(scenePointer.x, scenePointer.y), @@ -1082,19 +1099,16 @@ export class LinearElementEditor { let newPoint: LocalPoint; if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) { - const lastCommittedPoint = points[points.length - 2]; + const anchor = points[points.length - 2]; const [width, height] = LinearElementEditor._getShiftLockedDelta( element, elementsMap, - lastCommittedPoint, + anchor, pointFrom(scenePointerX, scenePointerY), event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(), ); - newPoint = pointFrom( - width + lastCommittedPoint[0], - height + lastCommittedPoint[1], - ); + newPoint = pointFrom(width + anchor[0], height + anchor[1]); } else { newPoint = LinearElementEditor.createPointAt( element, @@ -1530,18 +1544,18 @@ export class LinearElementEditor { return false; } - const { segmentMidpoint } = linearElementEditor.pointerDownState; + const { segmentMidpoint } = linearElementEditor.initialState; if ( segmentMidpoint.added || segmentMidpoint.value === null || segmentMidpoint.index === null || - linearElementEditor.pointerDownState.origin === null + linearElementEditor.initialState.origin === null ) { return false; } - const origin = linearElementEditor.pointerDownState.origin!; + const origin = linearElementEditor.initialState.origin!; const dist = pointDistance( origin, pointFrom(pointerCoords.x, pointerCoords.y), @@ -1570,12 +1584,12 @@ export class LinearElementEditor { if (!element) { return; } - const { segmentMidpoint } = linearElementEditor.pointerDownState; + const { segmentMidpoint } = linearElementEditor.initialState; const ret: { - pointerDownState: LinearElementEditor["pointerDownState"]; + pointerDownState: LinearElementEditor["initialState"]; selectedPointsIndices: LinearElementEditor["selectedPointsIndices"]; } = { - pointerDownState: linearElementEditor.pointerDownState, + pointerDownState: linearElementEditor.initialState, selectedPointsIndices: linearElementEditor.selectedPointsIndices, }; @@ -1595,9 +1609,9 @@ export class LinearElementEditor { scene.mutateElement(element, { points }); ret.pointerDownState = { - ...linearElementEditor.pointerDownState, + ...linearElementEditor.initialState, segmentMidpoint: { - ...linearElementEditor.pointerDownState.segmentMidpoint, + ...linearElementEditor.initialState.segmentMidpoint, added: true, }, lastClickedPoint: segmentMidpoint.index!, @@ -1915,7 +1929,7 @@ export class LinearElementEditor { scene: Scene, ): Pick< LinearElementEditor, - "segmentMidPointHoveredCoords" | "pointerDownState" + "segmentMidPointHoveredCoords" | "initialState" > { const elementsMap = scene.getNonDeletedElementsMap(); const element = LinearElementEditor.getElement( @@ -1978,8 +1992,8 @@ export class LinearElementEditor { return { ...linearElement, segmentMidPointHoveredCoords: point, - pointerDownState: { - ...linearElement.pointerDownState, + initialState: { + ...linearElement.initialState, segmentMidpoint: { added: false, index: element.fixedSegments![offset].index, diff --git a/packages/element/src/newElement.ts b/packages/element/src/newElement.ts index 69ccaf595f..ec50a81ff2 100644 --- a/packages/element/src/newElement.ts +++ b/packages/element/src/newElement.ts @@ -452,7 +452,6 @@ export const newFreeDrawElement = ( points: opts.points || [], pressures: opts.pressures || [], simulatePressure: opts.simulatePressure, - lastCommittedPoint: null, }; }; @@ -466,7 +465,7 @@ export const newLinearElement = ( const element = { ..._newElementBase(opts.type, opts), points: opts.points || [], - lastCommittedPoint: null, + startBinding: null, endBinding: null, startArrowhead: null, @@ -501,7 +500,6 @@ export const newArrowElement = ( return { ..._newElementBase(opts.type, opts), points: opts.points || [], - lastCommittedPoint: null, startBinding: null, endBinding: null, startArrowhead: opts.startArrowhead || null, @@ -516,7 +514,6 @@ export const newArrowElement = ( return { ..._newElementBase(opts.type, opts), points: opts.points || [], - lastCommittedPoint: null, startBinding: null, endBinding: null, startArrowhead: opts.startArrowhead || null, diff --git a/packages/element/src/renderElement.ts b/packages/element/src/renderElement.ts index 843bd110bf..06f79b09a2 100644 --- a/packages/element/src/renderElement.ts +++ b/packages/element/src/renderElement.ts @@ -1103,7 +1103,7 @@ export function getFreeDrawSvgPath(element: ExcalidrawFreeDrawElement) { smoothing: 0.5, streamline: 0.5, easing: (t) => Math.sin((t * Math.PI) / 2), // https://easings.net/#easeOutSine - last: !!element.lastCommittedPoint, // LastCommittedPoint is added on pointerup + last: true, }; return getSvgPathFromStroke(getStroke(inputPoints as number[][], options)); diff --git a/packages/element/src/types.ts b/packages/element/src/types.ts index 4e05df0ad9..8067342a20 100644 --- a/packages/element/src/types.ts +++ b/packages/element/src/types.ts @@ -321,7 +321,6 @@ export type ExcalidrawLinearElement = _ExcalidrawElementBase & Readonly<{ type: "line" | "arrow"; points: readonly LocalPoint[]; - lastCommittedPoint: LocalPoint | null; startBinding: FixedPointBinding | null; endBinding: FixedPointBinding | null; startArrowhead: Arrowhead | null; @@ -378,7 +377,6 @@ export type ExcalidrawFreeDrawElement = _ExcalidrawElementBase & points: readonly LocalPoint[]; pressures: readonly number[]; simulatePressure: boolean; - lastCommittedPoint: LocalPoint | null; }>; export type FileId = string & { _brand: "FileId" }; diff --git a/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap b/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap index 35e940d32e..67639e5bde 100644 --- a/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap +++ b/packages/element/tests/__snapshots__/linearElementEditor.test.tsx.snap @@ -44,3 +44,14 @@ exports[`Test Linear Elements > Test bound text element > should resize and posi "Online whiteboard collaboration made easy" `; + +exports[`Test Linear Elements > Test bound text element > should wrap the bound text when arrow bound container moves 1`] = ` +"Online whiteboard +collaboration made easy" +`; + +exports[`Test Linear Elements > Test bound text element > should wrap the bound text when arrow bound container moves 2`] = ` +"Online whiteboard +collaboration made +easy" +`; diff --git a/packages/element/tests/binding.test.tsx b/packages/element/tests/binding.test.tsx index 35892d1c53..735ac715c9 100644 --- a/packages/element/tests/binding.test.tsx +++ b/packages/element/tests/binding.test.tsx @@ -257,8 +257,8 @@ describe("binding for simple arrows", () => { const arrow = API.getSelectedElement() as ExcalidrawLinearElement; expect(arrow.x).toBe(10); expect(arrow.y).toBe(10); - expect(arrow.width).toBeCloseTo(86.4669660940663); - expect(arrow.height).toBeCloseTo(86.46696609406821); + expect(arrow.width).toBeCloseTo(85.75985931287957); + expect(arrow.height).toBeCloseTo(85.75985931288186); // Should bind to the rectangle since endpoint is inside expect(arrow.startBinding).toBe(null); @@ -280,8 +280,8 @@ describe("binding for simple arrows", () => { // Check if the arrow moved expect(arrow.x).toBe(10); expect(arrow.y).toBe(10); - expect(arrow.width).toBeCloseTo(235); - expect(arrow.height).toBeCloseTo(117.5); + expect(arrow.width).toBeCloseTo(234); + expect(arrow.height).toBeCloseTo(117); // Restore bindable mouse.reset(); @@ -309,49 +309,9 @@ describe("binding for simple arrows", () => { expect(arrow.width).toBeCloseTo(86, 0); expect(arrow.height).toBeCloseTo(86, 0); }); - - it("should happen even if the arrow is not pointing at the element", () => { - // Create a rectangle positioned so the extended arrow segment will miss it - const rect = API.createElement({ - type: "rectangle", - x: 100, - y: 100, - width: 100, - height: 100, - }); - - API.setElements([rect]); - - // Draw an arrow that doesn't point at the rectangle (extended segment will miss) - UI.clickTool("arrow"); - mouse.reset(); - mouse.downAt(125, 93); // Start point - mouse.moveTo(175, 93); // End point - arrow direction is horizontal, misses rectangle - mouse.up(); - - const arrow = API.getSelectedElement() as ExcalidrawLinearElement; - - // Should create a fixed point binding since the extended line segment - // from the last arrow segment misses the rectangle - expect(arrow.startBinding?.elementId).toBe(rect.id); - expect(arrow.startBinding).toHaveProperty("fixedPoint"); - expect( - (arrow.startBinding as FixedPointBinding).fixedPoint[0], - ).toBeGreaterThanOrEqual(0); - expect( - (arrow.startBinding as FixedPointBinding).fixedPoint[0], - ).toBeLessThanOrEqual(1); - expect( - (arrow.startBinding as FixedPointBinding).fixedPoint[1], - ).toBeLessThanOrEqual(0.5); - expect( - (arrow.startBinding as FixedPointBinding).fixedPoint[1], - ).toBeLessThanOrEqual(1); - expect(arrow.endBinding).toBe(null); - }); }); - describe("", () => { + describe("additional binding behavior", () => { beforeEach(async () => { mouse.reset(); @@ -411,8 +371,8 @@ describe("binding for simple arrows", () => { const arrow = UI.createElement("arrow", { x: 0, - y: 0, - size: 50, + y: 5, + size: 70, }); expect(arrow.endBinding?.elementId).toBe(rectangle.id); @@ -435,9 +395,9 @@ describe("binding for simple arrows", () => { height: 500, }); const arrow = UI.createElement("arrow", { - x: 210, + x: 190, y: 250, - width: 180, + width: 220, height: 1, }); expect(arrow.startBinding?.elementId).toBe(rectLeft.id); @@ -475,11 +435,11 @@ describe("binding for simple arrows", () => { UI.clickTool("arrow"); mouse.reset(); - mouse.clickAt(210, 250); + mouse.clickAt(190, 250); mouse.moveTo(300, 200); mouse.clickAt(300, 200); - mouse.moveTo(390, 251); - mouse.clickAt(390, 251); + mouse.moveTo(410, 251); + mouse.clickAt(410, 251); const arrow = API.getSelectedElement() as ExcalidrawArrowElement; @@ -517,9 +477,9 @@ describe("binding for simple arrows", () => { height: 500, }); const arrow = UI.createElement("arrow", { - x: 210, + x: 190, y: 250, - width: 177, + width: 217, height: 1, }); expect(arrow.startBinding?.elementId).toBe(rectLeft.id); @@ -668,7 +628,7 @@ describe("binding for simple arrows", () => { const arrow = UI.createElement("arrow", { x: 0, y: 0, - size: 50, + size: 65, }); expect(arrow.endBinding?.elementId).toBe(text.id); @@ -693,7 +653,7 @@ describe("binding for simple arrows", () => { it("should unbind on text element deletion by submitting empty text", async () => { const text = API.createElement({ type: "text", - text: "ola", + text: "¡olá!", x: 60, y: 0, width: 100, @@ -705,7 +665,7 @@ describe("binding for simple arrows", () => { const arrow = UI.createElement("arrow", { x: 0, y: 0, - size: 50, + size: 65, }); expect(arrow.endBinding?.elementId).toBe(text.id); diff --git a/packages/element/tests/duplicate.test.tsx b/packages/element/tests/duplicate.test.tsx index 60c5e6d83e..b8c5bede27 100644 --- a/packages/element/tests/duplicate.test.tsx +++ b/packages/element/tests/duplicate.test.tsx @@ -814,7 +814,7 @@ describe("duplication z-order", () => { const arrow = UI.createElement("arrow", { x: -100, y: 50, - width: 95, + width: 115, height: 0, }); diff --git a/packages/element/tests/elbowArrow.test.tsx b/packages/element/tests/elbowArrow.test.tsx index 25ef2b2ac0..7eece3d2b3 100644 --- a/packages/element/tests/elbowArrow.test.tsx +++ b/packages/element/tests/elbowArrow.test.tsx @@ -131,6 +131,11 @@ describe("elbow arrow segment move", () => { }); describe("elbow arrow routing", () => { + beforeEach(async () => { + localStorage.clear(); + await render(); + }); + it("can properly generate orthogonal arrow points", () => { const scene = new Scene(); const arrow = API.createElement({ @@ -194,9 +199,9 @@ describe("elbow arrow routing", () => { expect(arrow.points).toEqual([ [0, 0], - [45, 0], - [45, 200], - [90, 200], + [44, 0], + [44, 200], + [88, 200], ]); }); }); @@ -235,9 +240,9 @@ describe("elbow arrow ui", () => { expect(h.state.currentItemArrowType).toBe(ARROW_TYPE.elbow); mouse.reset(); - mouse.moveTo(-43, -99); + mouse.moveTo(-53, -99); mouse.click(); - mouse.moveTo(43, 99); + mouse.moveTo(53, 99); mouse.click(); const arrow = h.scene.getSelectedElements( @@ -248,9 +253,9 @@ describe("elbow arrow ui", () => { expect(arrow.elbowed).toBe(true); expect(arrow.points).toEqual([ [0, 0], - [45, 0], - [45, 200], - [90, 200], + [44, 0], + [44, 200], + [88, 200], ]); }); @@ -272,9 +277,9 @@ describe("elbow arrow ui", () => { UI.clickOnTestId("elbow-arrow"); mouse.reset(); - mouse.moveTo(-43, -99); + mouse.moveTo(-53, -99); mouse.click(); - mouse.moveTo(43, 99); + mouse.moveTo(53, 99); mouse.click(); const arrow = h.scene.getSelectedElements( @@ -290,9 +295,11 @@ describe("elbow arrow ui", () => { expect(arrow.points.map((point) => point.map(Math.round))).toEqual([ [0, 0], - [35, 0], - [35, 165], - [103, 165], + [36, 0], + [36, 90], + [28, 90], + [28, 164], + [101, 164], ]); }); @@ -314,9 +321,9 @@ describe("elbow arrow ui", () => { UI.clickOnTestId("elbow-arrow"); mouse.reset(); - mouse.moveTo(-43, -99); + mouse.moveTo(-53, -99); mouse.click(); - mouse.moveTo(43, 99); + mouse.moveTo(53, 99); mouse.click(); const arrow = h.scene.getSelectedElements( @@ -346,9 +353,9 @@ describe("elbow arrow ui", () => { expect(duplicatedArrow.elbowed).toBe(true); expect(duplicatedArrow.points).toEqual([ [0, 0], - [45, 0], - [45, 200], - [90, 200], + [44, 0], + [44, 200], + [88, 200], ]); expect(arrow.startBinding).not.toBe(null); expect(arrow.endBinding).not.toBe(null); @@ -372,9 +379,9 @@ describe("elbow arrow ui", () => { UI.clickOnTestId("elbow-arrow"); mouse.reset(); - mouse.moveTo(-43, -99); + mouse.moveTo(-53, -99); mouse.click(); - mouse.moveTo(43, 99); + mouse.moveTo(53, 99); mouse.click(); const arrow = h.scene.getSelectedElements( @@ -401,8 +408,8 @@ describe("elbow arrow ui", () => { expect(duplicatedArrow.points).toEqual([ [0, 0], [0, 100], - [90, 100], - [90, 200], + [88, 100], + [88, 200], ]); }); }); diff --git a/packages/element/tests/linearElementEditor.test.tsx b/packages/element/tests/linearElementEditor.test.tsx index d53492541e..0d6524fd9c 100644 --- a/packages/element/tests/linearElementEditor.test.tsx +++ b/packages/element/tests/linearElementEditor.test.tsx @@ -1303,7 +1303,7 @@ describe("Test Linear Elements", () => { const arrow = UI.createElement("arrow", { x: -10, y: 250, - width: 400, + width: 410, height: 1, }); @@ -1316,7 +1316,7 @@ describe("Test Linear Elements", () => { const textElement = h.elements[2] as ExcalidrawTextElementWithContainer; expect(arrow.endBinding?.elementId).toBe(rect.id); - expect(arrow.width).toBeCloseTo(405); + expect(arrow.width).toBeCloseTo(404); expect(rect.x).toBe(400); expect(rect.y).toBe(0); expect( @@ -1335,7 +1335,7 @@ describe("Test Linear Elements", () => { mouse.downAt(rect.x, rect.y); mouse.moveTo(200, 0); mouse.upAt(200, 0); - expect(arrow.width).toBeCloseTo(205); + expect(arrow.width).toBeCloseTo(204); expect(rect.x).toBe(200); expect(rect.y).toBe(0); expect(handleBindTextResizeSpy).toHaveBeenCalledWith( diff --git a/packages/element/tests/resize.test.tsx b/packages/element/tests/resize.test.tsx index 1ab1fafcec..039d519120 100644 --- a/packages/element/tests/resize.test.tsx +++ b/packages/element/tests/resize.test.tsx @@ -510,12 +510,12 @@ describe("arrow element", () => { h.state, )[0] as ExcalidrawElbowArrowElement; - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.06); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); UI.resize(rectangle, "se", [-200, -150]); - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.06); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); }); @@ -538,11 +538,11 @@ describe("arrow element", () => { h.state, )[0] as ExcalidrawElbowArrowElement; - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.06); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); UI.resize([rectangle, arrow], "nw", [300, 350]); - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(-0.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(-0.06); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.25); }); }); @@ -1350,8 +1350,8 @@ describe("multiple selection", () => { expect(boundArrow.x).toBeCloseTo(380 * scaleX); expect(boundArrow.y).toBeCloseTo(240 * scaleY); - expect(boundArrow.points[1][0]).toBeCloseTo(64.1246); - expect(boundArrow.points[1][1]).toBeCloseTo(-85.4995); + expect(boundArrow.points[1][0]).toBeCloseTo(66.3157); + expect(boundArrow.points[1][1]).toBeCloseTo(-88.421); expect(arrowLabelPos.x + arrowLabel.width / 2).toBeCloseTo( boundArrow.x + boundArrow.points[1][0] / 2, diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index 7e29a935b9..4ccee7182c 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -151,6 +151,10 @@ export const actionFinalize = register({ ...linearElementEditor, selectedPointsIndices: null, isEditing: false, + initialState: { + ...linearElementEditor.initialState, + lastClickedPoint: -1, + }, }, selectionElement: null, suggestedBinding: null, @@ -186,11 +190,13 @@ export const actionFinalize = register({ if (element) { // pen and mouse have hover if ( + appState.selectedLinearElement && appState.multiElement && element.type !== "freedraw" && appState.lastPointerDownWith !== "touch" ) { - const { points, lastCommittedPoint } = element; + const { points } = element; + const { lastCommittedPoint } = appState.selectedLinearElement; if ( !lastCommittedPoint || points[points.length - 1] !== lastCommittedPoint @@ -278,8 +284,9 @@ export const actionFinalize = register({ isEditing: appState.newElement ? false : selectedLinearElement.isEditing, - pointerDownState: { - ...selectedLinearElement.pointerDownState, + initialState: { + ...selectedLinearElement.initialState, + lastClickedPoint: -1, origin: null, }, } diff --git a/packages/excalidraw/actions/actionFlip.test.tsx b/packages/excalidraw/actions/actionFlip.test.tsx index 69050e9b25..0be29c9800 100644 --- a/packages/excalidraw/actions/actionFlip.test.tsx +++ b/packages/excalidraw/actions/actionFlip.test.tsx @@ -72,11 +72,11 @@ describe("flipping re-centers selection", () => { const rec1 = h.elements.find((el) => el.id === "rec1")!; expect(rec1.x).toBeCloseTo(100, 0); - expect(rec1.y).toBeCloseTo(100, 0); + expect(rec1.y).toBeCloseTo(101, 0); const rec2 = h.elements.find((el) => el.id === "rec2")!; expect(rec2.x).toBeCloseTo(220, 0); - expect(rec2.y).toBeCloseTo(250, 0); + expect(rec2.y).toBeCloseTo(251, 0); }); }); diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 57bfb422c8..c4b68a0411 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -866,8 +866,8 @@ class App extends React.Component { private handleSkipBindMode() { if ( - this.state.selectedLinearElement?.pointerDownState && - !this.state.selectedLinearElement.pointerDownState.arrowStartIsInside + this.state.selectedLinearElement?.initialState && + !this.state.selectedLinearElement.initialState.arrowStartIsInside ) { invariant( this.lastPointerMoveCoords, @@ -894,8 +894,8 @@ class App extends React.Component { this.setState({ selectedLinearElement: { ...this.state.selectedLinearElement, - pointerDownState: { - ...this.state.selectedLinearElement.pointerDownState, + initialState: { + ...this.state.selectedLinearElement.initialState, arrowStartIsInside: true, }, }, @@ -983,8 +983,7 @@ class App extends React.Component { // Once the start is set to inside binding, it remains so const arrowStartIsInside = !this.state.newElement && - (this.state.selectedLinearElement.pointerDownState - .arrowStartIsInside || + (this.state.selectedLinearElement.initialState.arrowStartIsInside || arrow.startBinding?.elementId === hoveredElement.id); // Change the global binding mode @@ -998,8 +997,8 @@ class App extends React.Component { bindMode: "inside", selectedLinearElement: { ...this.state.selectedLinearElement, - pointerDownState: { - ...this.state.selectedLinearElement.pointerDownState, + initialState: { + ...this.state.selectedLinearElement.initialState, arrowStartIsInside, }, }, @@ -5841,8 +5840,8 @@ class App extends React.Component { this.setState({ selectedLinearElement: { ...this.state.selectedLinearElement, - pointerDownState: { - ...this.state.selectedLinearElement.pointerDownState, + initialState: { + ...this.state.selectedLinearElement.initialState, segmentMidpoint: { index: nextIndex, value: hitCoords, @@ -6260,10 +6259,17 @@ class App extends React.Component { } if (this.state.multiElement) { - const { multiElement } = this.state; - const { x: rx, y: ry, points, lastCommittedPoint } = multiElement; + const { multiElement, selectedLinearElement } = this.state; + const { x: rx, y: ry, points } = multiElement; const lastPoint = points[points.length - 1]; + invariant( + selectedLinearElement, + "There must be a selected linear element instace", + ); + + const { lastCommittedPoint } = selectedLinearElement; + setCursorForShape(this.interactiveCanvas, this.state); if (lastPoint === lastCommittedPoint) { @@ -6285,13 +6291,18 @@ class App extends React.Component { }, { informMutation: false, isDragging: false }, ); - if (this.state.selectedLinearElement?.pointerDownState) { + invariant( + this.state.selectedLinearElement?.initialState, + "initialState must be set", + ); + if (this.state.selectedLinearElement.initialState) { this.setState({ selectedLinearElement: { ...this.state.selectedLinearElement, + lastCommittedPoint: points[points.length - 1], selectedPointsIndices: [multiElement.points.length - 1], - pointerDownState: { - ...this.state.selectedLinearElement.pointerDownState, + initialState: { + ...this.state.selectedLinearElement.initialState, lastClickedPoint: multiElement.points.length - 1, }, }, @@ -6318,6 +6329,30 @@ class App extends React.Component { }, { informMutation: false, isDragging: false }, ); + this.setState({ + selectedLinearElement: { + ...selectedLinearElement, + selectedPointsIndices: + selectedLinearElement.selectedPointsIndices?.includes( + multiElement.points.length, + ) + ? [ + ...selectedLinearElement.selectedPointsIndices.filter( + (idx) => + idx !== multiElement.points.length && + idx !== multiElement.points.length - 1, + ), + multiElement.points.length - 1, + ] + : selectedLinearElement.selectedPointsIndices, + lastCommittedPoint: + multiElement.points[multiElement.points.length - 1], + initialState: { + ...selectedLinearElement.initialState, + lastClickedPoint: multiElement.points.length - 1, + }, + }, + }); } else { if (isPathALoop(points, this.state.zoom.value)) { setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER); @@ -8171,16 +8206,30 @@ class App extends React.Component { pointerDownState: PointerDownState, ): void => { if (this.state.multiElement) { - const { multiElement } = this.state; + const { multiElement, selectedLinearElement } = this.state; + + invariant( + selectedLinearElement, + "selectedLinearElement is expected to be set", + ); // finalize if completing a loop if ( multiElement.type === "line" && isPathALoop(multiElement.points, this.state.zoom.value) ) { - this.scene.mutateElement(multiElement, { - lastCommittedPoint: - multiElement.points[multiElement.points.length - 1], + flushSync(() => { + this.setState({ + selectedLinearElement: { + ...selectedLinearElement, + lastCommittedPoint: + multiElement.points[multiElement.points.length - 1], + initialState: { + ...selectedLinearElement.initialState, + lastClickedPoint: -1, // Disable dragging + }, + }, + }); }); this.actionManager.executeAction(actionFinalize); return; @@ -8189,10 +8238,6 @@ class App extends React.Component { // Elbow arrows cannot be created by putting down points // only the start and end points can be defined if (isElbowArrow(multiElement) && multiElement.points.length > 1) { - this.scene.mutateElement(multiElement, { - lastCommittedPoint: - multiElement.points[multiElement.points.length - 1], - }); this.actionManager.executeAction(actionFinalize, "ui", { event: event.nativeEvent, sceneCoords: { @@ -8203,7 +8248,9 @@ class App extends React.Component { return; } - const { x: rx, y: ry, lastCommittedPoint } = multiElement; + const { x: rx, y: ry } = multiElement; + const { lastCommittedPoint } = selectedLinearElement; + const hoveredElementForBinding = getHoveredElementForBinding( pointFrom( this.lastPointerMoveCoords?.x ?? @@ -8247,11 +8294,7 @@ class App extends React.Component { prevState, ), })); - // clicking outside commit zone → update reference for last committed - // point - this.scene.mutateElement(multiElement, { - lastCommittedPoint: multiElement.points[multiElement.points.length - 1], - }); + setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER); } else { const [gridX, gridY] = getGridPoint( @@ -8373,27 +8416,24 @@ class App extends React.Component { this.scene.getNonDeletedElementsMap(), ); - if (isBindingElement(element)) { - const endIdx = element.points.length - 1; - linearElementEditor = { - ...linearElementEditor, - selectedPointsIndices: [endIdx], - pointerDownState: { - ...linearElementEditor.pointerDownState, - lastClickedPoint: endIdx, - origin: pointFrom( - pointerDownState.origin.x, - pointerDownState.origin.y, - ), - }, - }; - } + const endIdx = element.points.length - 1; + linearElementEditor = { + ...linearElementEditor, + selectedPointsIndices: [endIdx], + initialState: { + ...linearElementEditor.initialState, + lastClickedPoint: endIdx, + origin: pointFrom( + pointerDownState.origin.x, + pointerDownState.origin.y, + ), + }, + }; } - nextSelectedElementIds = makeNextSelectedElementIds( - { [element.id]: true }, - prevState, - ); + nextSelectedElementIds = !this.state.activeTool.locked + ? makeNextSelectedElementIds({ [element.id]: true }, prevState) + : prevState.selectedElementIds; return { ...prevState, @@ -8607,7 +8647,7 @@ class App extends React.Component { if ( this.state.selectedLinearElement && this.state.selectedLinearElement.elbowed && - this.state.selectedLinearElement.pointerDownState.segmentMidpoint.index + this.state.selectedLinearElement.initialState.segmentMidpoint.index ) { const [gridX, gridY] = getGridPoint( pointerCoords.x, @@ -8616,8 +8656,7 @@ class App extends React.Component { ); let index = - this.state.selectedLinearElement.pointerDownState.segmentMidpoint - .index; + this.state.selectedLinearElement.initialState.segmentMidpoint.index; if (index < 0) { const nextCoords = LinearElementEditor.getSegmentMidpointHitCoords( { @@ -8650,7 +8689,7 @@ class App extends React.Component { selectedLinearElement: { ...this.state.selectedLinearElement, segmentMidPointHoveredCoords: ret.segmentMidPointHoveredCoords, - pointerDownState: ret.pointerDownState, + initialState: ret.initialState, }, }); return; @@ -8740,7 +8779,7 @@ class App extends React.Component { this.setState({ selectedLinearElement: { ...this.state.selectedLinearElement, - pointerDownState: ret.pointerDownState, + initialState: ret.pointerDownState, selectedPointsIndices: ret.selectedPointsIndices, segmentMidPointHoveredCoords: null, }, @@ -8750,11 +8789,11 @@ class App extends React.Component { return; } else if ( - linearElementEditor.pointerDownState.segmentMidpoint.value !== null && - !linearElementEditor.pointerDownState.segmentMidpoint.added + linearElementEditor.initialState.segmentMidpoint.value !== null && + !linearElementEditor.initialState.segmentMidpoint.added ) { return; - } else if (linearElementEditor.pointerDownState.lastClickedPoint > -1) { + } else if (linearElementEditor.initialState.lastClickedPoint > -1) { const element = LinearElementEditor.getElement( linearElementEditor.elementId, elementsMap, @@ -8776,12 +8815,16 @@ class App extends React.Component { if ( event.altKey && - !this.state.selectedLinearElement?.pointerDownState - ?.arrowStartIsInside + !this.state.selectedLinearElement?.initialState?.arrowStartIsInside ) { this.handleSkipBindMode(); } + // Ignore drag requests if the arrow modification already happened + if (linearElementEditor.initialState.lastClickedPoint === -1) { + return; + } + const newState = LinearElementEditor.handlePointDragging( event, this, @@ -8789,6 +8832,7 @@ class App extends React.Component { pointerCoords.y, linearElementEditor, ); + if (newState) { pointerDownState.lastCoords.x = pointerCoords.x; pointerDownState.lastCoords.y = pointerCoords.y; @@ -9277,13 +9321,12 @@ class App extends React.Component { linearElementEditor = { ...linearElementEditor, selectedPointsIndices: [1], - pointerDownState: { - ...linearElementEditor.pointerDownState, + initialState: { + ...linearElementEditor.initialState, lastClickedPoint: 1, }, }; } - this.setState({ newElement, ...LinearElementEditor.handlePointDragging( @@ -9612,6 +9655,23 @@ class App extends React.Component { sceneCoords, }); } + + if ( + this.state.newElement && + this.state.multiElement && + isLinearElement(this.state.newElement) && + this.state.selectedLinearElement + ) { + const { multiElement } = this.state; + + this.setState({ + selectedLinearElement: { + ...this.state.selectedLinearElement, + lastCommittedPoint: + multiElement.points[multiElement.points.length - 1], + }, + }); + } } this.missingPointerEventCleanupEmitter.clear(); @@ -9663,7 +9723,6 @@ class App extends React.Component { this.scene.mutateElement(newElement, { points: [...points, pointFrom(dx, dy)], pressures, - lastCommittedPoint: pointFrom(dx, dy), }); this.actionManager.executeAction(actionFinalize); diff --git a/packages/excalidraw/components/Stats/stats.test.tsx b/packages/excalidraw/components/Stats/stats.test.tsx index 79b6edc071..548a16ffa4 100644 --- a/packages/excalidraw/components/Stats/stats.test.tsx +++ b/packages/excalidraw/components/Stats/stats.test.tsx @@ -114,7 +114,7 @@ describe("binding with linear elements", () => { mouse.up(200, 100); UI.clickTool("arrow"); - mouse.down(5, 0); + mouse.down(-5, 0); mouse.up(300, 50); elementStats = stats?.querySelector("#elementStats"); diff --git a/packages/excalidraw/data/__snapshots__/transform.test.ts.snap b/packages/excalidraw/data/__snapshots__/transform.test.ts.snap index cd95bedf92..afef25eeff 100644 --- a/packages/excalidraw/data/__snapshots__/transform.test.ts.snap +++ b/packages/excalidraw/data/__snapshots__/transform.test.ts.snap @@ -101,7 +101,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s "id": Any, "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -163,7 +162,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s "id": Any, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -359,7 +357,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t "id": Any, "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -467,7 +464,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe "id": Any, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -649,7 +645,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when "id": Any, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -869,7 +864,6 @@ exports[`Test Transform > should transform linear elements 1`] = ` "id": Any, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -917,7 +911,6 @@ exports[`Test Transform > should transform linear elements 2`] = ` "id": Any, "index": "a1", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -964,7 +957,6 @@ exports[`Test Transform > should transform linear elements 3`] = ` "id": Any, "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -1012,7 +1004,6 @@ exports[`Test Transform > should transform linear elements 4`] = ` "id": Any, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -1519,7 +1510,6 @@ exports[`Test Transform > should transform the elements correctly when linear el "id": Any, "index": "a4", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -1588,7 +1578,6 @@ exports[`Test Transform > should transform the elements correctly when linear el "id": Any, "index": "a5", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -1900,7 +1889,6 @@ exports[`Test Transform > should transform to labelled arrows when label provide "id": Any, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -1953,7 +1941,6 @@ exports[`Test Transform > should transform to labelled arrows when label provide "id": Any, "index": "a1", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -2006,7 +1993,6 @@ exports[`Test Transform > should transform to labelled arrows when label provide "id": Any, "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -2059,7 +2045,6 @@ exports[`Test Transform > should transform to labelled arrows when label provide "id": Any, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, diff --git a/packages/excalidraw/data/blob.ts b/packages/excalidraw/data/blob.ts index dc65cf0d3b..1848a845af 100644 --- a/packages/excalidraw/data/blob.ts +++ b/packages/excalidraw/data/blob.ts @@ -7,8 +7,6 @@ import { isPromiseLike, } from "@excalidraw/common"; -import { clearElementsForExport } from "@excalidraw/element"; - import type { ValueOf } from "@excalidraw/common/utility-types"; import type { ExcalidrawElement, FileId } from "@excalidraw/element/types"; @@ -159,7 +157,7 @@ export const loadSceneOrLibraryFromBlob = async ( type: MIME_TYPES.excalidraw, data: restore( { - elements: clearElementsForExport(data.elements || []), + elements: data.elements || [], appState: { theme: localAppState?.theme, fileHandle: fileHandle || blob.handle || null, diff --git a/packages/excalidraw/data/json.ts b/packages/excalidraw/data/json.ts index 52cbf99581..b88aea02c1 100644 --- a/packages/excalidraw/data/json.ts +++ b/packages/excalidraw/data/json.ts @@ -6,11 +6,6 @@ import { VERSIONS, } from "@excalidraw/common"; -import { - clearElementsForDatabase, - clearElementsForExport, -} from "@excalidraw/element"; - import type { ExcalidrawElement } from "@excalidraw/element/types"; import { cleanAppStateForExport, clearAppStateForDatabase } from "../appState"; @@ -57,10 +52,7 @@ export const serializeAsJSON = ( type: EXPORT_DATA_TYPES.excalidraw, version: VERSIONS.excalidraw, source: getExportSource(), - elements: - type === "local" - ? clearElementsForExport(elements) - : clearElementsForDatabase(elements), + elements, appState: type === "local" ? cleanAppStateForExport(appState) diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 7970ba4830..0aa5092dbd 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -292,7 +292,6 @@ export const restoreElement = ( case "freedraw": { return restoreElementWithProperties(element, { points: element.points, - lastCommittedPoint: null, simulatePressure: element.simulatePressure, pressures: element.pressures, }); @@ -328,7 +327,6 @@ export const restoreElement = ( : element.type, startBinding: repairBinding(element, element.startBinding), endBinding: repairBinding(element, element.endBinding), - lastCommittedPoint: null, startArrowhead, endArrowhead, points, @@ -361,7 +359,6 @@ export const restoreElement = ( type: element.type, startBinding: repairBinding(element, element.startBinding), endBinding: repairBinding(element, element.endBinding), - lastCommittedPoint: null, startArrowhead, endArrowhead, points, diff --git a/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap index c25b269f4b..a538500c25 100644 --- a/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap @@ -18,7 +18,6 @@ exports[`Test dragCreate > add element to the scene when pointer dragging long e "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -135,7 +134,6 @@ exports[`Test dragCreate > add element to the scene when pointer dragging long e "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 833c004226..c2eb6eb72a 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -119,7 +119,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -138,7 +143,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 13, "width": 100, "x": -100, "y": -50, @@ -149,7 +154,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -168,7 +173,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 9, "width": 100, "x": 100, "y": -50, @@ -183,17 +188,24 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id15", + "fixedPoint": [ + "0.50000", + 1, + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 0, + "height": "112.78797", "id": "id4", "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -201,8 +213,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 100, - 0, + 94, + "112.78797", ], ], "roughness": 1, @@ -210,24 +222,271 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "inside", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 6, - "width": 100, + "version": 37, + "width": 94, "x": 0, - "y": 10, + "y": "0.01000", } `; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] number of elements 1`] = `3`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] element 3 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 50, + "id": "id15", + "index": "a3", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": null, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 10, + "width": 50, + "x": 100, + "y": 100, +} +`; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] number of renders 1`] = `10`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] number of elements 1`] = `4`; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] redo stack 1`] = `[]`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] number of renders 1`] = `22`; + +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] redo stack 1`] = ` +[ + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "version": 12, + }, + "inserted": { + "version": 11, + }, + }, + "id1": { + "deleted": { + "boundElements": [], + "version": 9, + }, + "inserted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 8, + }, + }, + "id15": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 9, + }, + "inserted": { + "boundElements": [], + "version": 8, + }, + }, + "id4": { + "deleted": { + "endBinding": { + "elementId": "id15", + "fixedPoint": [ + "0.50000", + 1, + ], + "mode": "orbit", + }, + "height": "98.55605", + "points": [ + [ + 0, + 0, + ], + [ + 88, + "98.55605", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.60000", + ], + "mode": "orbit", + }, + "version": 36, + "width": 88, + "y": "16.71973", + }, + "inserted": { + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + 0, + "0.60000", + ], + "mode": "orbit", + }, + "height": "0.00000", + "points": [ + [ + 0, + 0, + ], + [ + 88, + "0.00000", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.60000", + ], + "mode": "orbit", + }, + "version": 33, + "width": 88, + "y": "10.00000", + }, + }, + }, + }, + "id": "id22", + }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "version": 13, + }, + "inserted": { + "version": 12, + }, + }, + "id15": { + "deleted": { + "version": 10, + }, + "inserted": { + "version": 9, + }, + }, + "id4": { + "deleted": { + "height": "112.78797", + "points": [ + [ + 0, + 0, + ], + [ + 94, + "112.78797", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "inside", + }, + "version": 37, + "width": 94, + "x": 0, + "y": "0.01000", + }, + "inserted": { + "height": "98.55605", + "points": [ + [ + 0, + 0, + ], + [ + 88, + "98.55605", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.60000", + ], + "mode": "orbit", + }, + "version": 36, + "width": 88, + "x": 6, + "y": "16.71973", + }, + }, + }, + }, + "id": "id23", + }, +] +`; exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] undo stack 1`] = ` [ @@ -341,10 +600,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 0, + "height": "0.01000", "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -355,7 +613,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl ], [ 100, - 0, + "-0.01000", ], ], "roughness": 1, @@ -363,118 +621,49 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "inside", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, + "version": 6, "width": 100, "x": 0, - "y": 0, + "y": "0.01000", }, "inserted": { "isDeleted": true, + "version": 5, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "version": 3, }, + "inserted": { + "boundElements": [], + "version": 2, + }, }, }, - "updated": {}, }, "id": "id6", }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id4": { - "deleted": { - "height": 10, - "points": [ - [ - 0, - 0, - ], - [ - 100, - -10, - ], - ], - "version": 5, - "y": 10, - }, - "inserted": { - "height": 0, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "version": 4, - "y": 0, - }, - }, - }, - }, - "id": "id9", - }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id4": { - "deleted": { - "height": 0, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "version": 6, - }, - "inserted": { - "height": 10, - "points": [ - [ - 0, - 0, - ], - [ - 100, - -10, - ], - ], - "version": 5, - }, - }, - }, - }, - "id": "id12", - }, ] `; @@ -597,7 +786,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -616,9 +810,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 14, "width": 100, - "x": -100, + "x": 150, "y": -50, } `; @@ -627,7 +821,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -646,9 +840,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 9, "width": 100, - "x": 100, + "x": 150, "y": -50, } `; @@ -665,13 +859,13 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 0, + "height": "0.01000", "id": "id4", "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -679,8 +873,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 100, 0, + "-0.01000", ], ], "roughness": 1, @@ -688,24 +882,206 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "inside", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 6, - "width": 100, - "x": 0, - "y": 10, + "version": 31, + "width": 0, + "x": 250, + "y": "0.01000", } `; exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] number of elements 1`] = `3`; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] number of renders 1`] = `10`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] number of renders 1`] = `24`; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] redo stack 1`] = `[]`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] redo stack 1`] = ` +[ + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "version": 13, + }, + "inserted": { + "version": 12, + }, + }, + "id1": { + "deleted": { + "boundElements": [], + "version": 9, + }, + "inserted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 8, + }, + }, + "id4": { + "deleted": { + "endBinding": null, + "height": "2.93333", + "points": [ + [ + 0, + 0, + ], + [ + -44, + "-2.93333", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.60000", + ], + "mode": "orbit", + }, + "version": 30, + "width": 44, + "y": "2.93333", + }, + "inserted": { + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + 0, + "0.60000", + ], + "mode": "orbit", + }, + "height": 0, + "points": [ + [ + 0, + 0, + ], + [ + 0, + 0, + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.60000", + ], + "mode": "orbit", + }, + "version": 29, + "width": 0, + "y": "9.99999", + }, + }, + }, + }, + "id": "id21", + }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "version": 14, + }, + "inserted": { + "version": 13, + }, + }, + "id4": { + "deleted": { + "height": "0.01000", + "points": [ + [ + 0, + 0, + ], + [ + 0, + "-0.01000", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "inside", + }, + "version": 31, + "width": 0, + "x": 250, + "y": "0.01000", + }, + "inserted": { + "height": "2.93333", + "points": [ + [ + 0, + 0, + ], + [ + -44, + "-2.93333", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.60000", + ], + "mode": "orbit", + }, + "version": 30, + "width": 44, + "x": 144, + "y": "2.93333", + }, + }, + }, + }, + "id": "id22", + }, +] +`; exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] undo stack 1`] = ` [ @@ -819,10 +1195,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 0, + "height": "0.01000", "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -833,7 +1208,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl ], [ 100, - 0, + "-0.01000", ], ], "roughness": 1, @@ -841,118 +1216,49 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "inside", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, + "version": 6, "width": 100, "x": 0, - "y": 0, + "y": "0.01000", }, "inserted": { "isDeleted": true, + "version": 5, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "version": 3, }, + "inserted": { + "boundElements": [], + "version": 2, + }, }, }, - "updated": {}, }, "id": "id6", }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id4": { - "deleted": { - "height": 10, - "points": [ - [ - 0, - 0, - ], - [ - 100, - -10, - ], - ], - "version": 5, - "y": 10, - }, - "inserted": { - "height": 0, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "version": 4, - "y": 0, - }, - }, - }, - }, - "id": "id9", - }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id4": { - "deleted": { - "height": 0, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "version": 6, - }, - "inserted": { - "height": 10, - "points": [ - [ - 0, - 0, - ], - [ - 100, - -10, - ], - ], - "version": 5, - }, - }, - }, - }, - "id": "id12", - }, ] `; @@ -1089,11 +1395,10 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "30.01725", + "height": "29.36414", "id": "id4", "index": "Zz", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "moveMidPointsWithElement": false, @@ -1104,8 +1409,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 90, - "30.01725", + 88, + "29.36414", ], ], "roughness": 1, @@ -1125,9 +1430,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 10, - "width": 90, - "x": 5, - "y": "1.67622", + "width": 88, + "x": 6, + "y": "2.00946", } `; @@ -1449,11 +1754,10 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "15.64048", + "height": "14.91372", "id": "id5", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "moveMidPointsWithElement": false, @@ -1464,8 +1768,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 90, - "-15.64048", + "88.00000", + "-14.91372", ], ], "roughness": 1, @@ -1485,9 +1789,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 11, - "width": 90, - "x": 5, - "y": "37.37707", + "width": "88.00000", + "x": 6, + "y": "37.05219", } `; @@ -1598,10 +1902,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "15.64048", + "height": "14.91372", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -1611,8 +1914,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 90, - "-15.64048", + "88.00000", + "-14.91372", ], ], "roughness": 1, @@ -1631,9 +1934,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "arrow", "version": 11, - "width": 90, - "x": 5, - "y": "37.37707", + "width": "88.00000", + "x": 6, + "y": "37.05219", }, "inserted": { "isDeleted": true, @@ -2025,7 +2328,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "scrollX": 0, "scrollY": 0, "searchMatches": null, - "selectedElementIds": {}, + "selectedElementIds": { + "id4": true, + }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, "selectionElement": null, @@ -2056,7 +2361,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -2075,7 +2385,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 5, "width": 100, "x": -100, "y": -50, @@ -2086,7 +2396,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -2105,10 +2420,10 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 6, "width": 100, - "x": 100, - "y": -50, + "x": 500, + "y": -500, } `; @@ -2120,17 +2435,24 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 0, + "height": "439.13521", "id": "id4", "index": "a2", - "isDeleted": true, - "lastCommittedPoint": null, + "isDeleted": false, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -2138,8 +2460,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 100, - 0, + 488, + "-439.13521", ], ], "roughness": 1, @@ -2147,102 +2469,31 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 5, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": 488, + "x": 6, + "y": "-5.38920", } `; exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] number of elements 1`] = `3`; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] number of renders 1`] = `7`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] number of renders 1`] = `10`; -exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] redo stack 1`] = ` -[ - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": {}, - "selectedLinearElement": null, - }, - "inserted": { - "selectedElementIds": { - "id4": true, - }, - "selectedLinearElement": { - "elementId": "id4", - "isEditing": false, - }, - }, - }, - }, - "elements": { - "added": { - "id4": { - "deleted": { - "isDeleted": true, - "version": 5, - }, - "inserted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": null, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 0, - "index": "a2", - "isDeleted": false, - "lastCommittedPoint": null, - "link": null, - "locked": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "startArrowhead": null, - "startBinding": null, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "version": 4, - "width": 100, - "x": 0, - "y": 0, - }, - }, - }, - "removed": {}, - "updated": {}, - }, - "id": "id7", - }, -] -`; +exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] redo stack 1`] = `[]`; exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] undo stack 1`] = ` [ @@ -2323,6 +2574,125 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "id": "id3", }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id4": true, + }, + "selectedLinearElement": { + "elementId": "id4", + "isEditing": false, + }, + }, + "inserted": { + "selectedElementIds": {}, + "selectedLinearElement": null, + }, + }, + }, + "elements": { + "added": {}, + "removed": { + "id4": { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": "439.13521", + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + 488, + "-439.13521", + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "startArrowhead": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "version": 13, + "width": 488, + "x": 6, + "y": "-5.38920", + }, + "inserted": { + "isDeleted": true, + "version": 10, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 5, + }, + "inserted": { + "boundElements": [], + "version": 4, + }, + }, + "id1": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 6, + }, + "inserted": { + "boundElements": [], + "version": 5, + }, + }, + }, + }, + "id": "id8", + }, ] `; @@ -7063,10 +7433,6 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "id": "id0", "index": "a0", "isDeleted": true, - "lastCommittedPoint": [ - 10, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -7091,7 +7457,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 8, + "version": 7, "width": 10, "x": 0, "y": 0, @@ -7100,7 +7466,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] number of elements 1`] = `1`; -exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] number of renders 1`] = `10`; +exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] number of renders 1`] = `11`; exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] redo stack 1`] = `[]`; @@ -7143,10 +7509,6 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "height": 10, "index": "a0", "isDeleted": true, - "lastCommittedPoint": [ - 10, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -7170,14 +7532,14 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 8, + "version": 7, "width": 10, "x": 0, "y": 0, }, "inserted": { "isDeleted": true, - "version": 7, + "version": 6, }, }, }, @@ -8695,10 +9057,6 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 50, - ], "link": null, "locked": false, "opacity": 100, @@ -8801,10 +9159,6 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "height": 50, "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 50, - ], "link": null, "locked": false, "opacity": 100, @@ -10040,10 +10394,6 @@ exports[`history > multiplayer undo/redo > should override remotely added points "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 30, - 30, - ], "link": null, "locked": false, "opacity": 100, @@ -10080,7 +10430,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 12, + "version": 10, "width": 30, "x": 0, "y": 0, @@ -10089,7 +10439,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] number of elements 1`] = `1`; -exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] number of renders 1`] = `12`; +exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] number of renders 1`] = `13`; exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] redo stack 1`] = `[]`; @@ -10131,10 +10481,6 @@ exports[`history > multiplayer undo/redo > should override remotely added points "height": 10, "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 10, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -10158,14 +10504,14 @@ exports[`history > multiplayer undo/redo > should override remotely added points "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 11, + "version": 9, "width": 10, "x": 0, "y": 0, }, "inserted": { "isDeleted": true, - "version": 10, + "version": 8, }, }, }, @@ -10187,10 +10533,6 @@ exports[`history > multiplayer undo/redo > should override remotely added points "id0": { "deleted": { "height": 30, - "lastCommittedPoint": [ - 30, - 30, - ], "points": [ [ 0, @@ -10213,15 +10555,11 @@ exports[`history > multiplayer undo/redo > should override remotely added points 20, ], ], - "version": 12, + "version": 10, "width": 30, }, "inserted": { "height": 10, - "lastCommittedPoint": [ - 10, - 10, - ], "points": [ [ 0, @@ -10232,7 +10570,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points 10, ], ], - "version": 11, + "version": 9, "width": 10, }, }, @@ -10677,7 +11015,6 @@ exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end o "id": "6Rm4g567UQM4WjLwej2Vc", "index": "a2", "isDeleted": true, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -10762,7 +11099,6 @@ exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end o "height": "236.10000", "index": "a2", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -11804,10 +12140,6 @@ exports[`history > singleplayer undo/redo > should create entry when selecting f "id": "id5", "index": "a1", "isDeleted": true, - "lastCommittedPoint": [ - 50, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -11858,10 +12190,6 @@ exports[`history > singleplayer undo/redo > should create entry when selecting f "id": "id9", "index": "a2", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -12001,10 +12329,6 @@ exports[`history > singleplayer undo/redo > should create entry when selecting f "height": 10, "index": "a2", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -15788,6 +16112,10 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id1", "type": "text", }, + { + "id": "id13", + "type": "arrow", + }, ], "customData": undefined, "fillStyle": "solid", @@ -15807,7 +16135,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 6, "width": 100, "x": -100, "y": -50, @@ -15845,7 +16173,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 4, + "version": 5, "verticalAlign": "middle", "width": 30, "x": -65, @@ -15857,7 +16185,12 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -15876,7 +16209,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 5, "width": 100, "x": 100, "y": -50, @@ -15891,7 +16224,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], @@ -15899,9 +16239,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id13", "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -15909,7 +16249,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -15918,24 +16258,141 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": "88.00000", + "x": 6, + "y": "0.01000", } `; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of renders 1`] = `10`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of renders 1`] = `13`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] redo stack 1`] = `[]`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] redo stack 1`] = ` +[ + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id13": true, + }, + "selectedLinearElement": { + "elementId": "id13", + "isEditing": false, + }, + }, + "inserted": { + "selectedElementIds": {}, + "selectedLinearElement": null, + }, + }, + }, + "elements": { + "added": {}, + "removed": { + "id13": { + "deleted": { + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, + "isDeleted": false, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, + "version": 13, + }, + "inserted": { + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, + "isDeleted": true, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, + "version": 10, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 6, + }, + "inserted": { + "boundElements": [], + "version": 5, + }, + }, + "id1": { + "deleted": { + "version": 5, + }, + "inserted": { + "version": 4, + }, + }, + "id2": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 5, + }, + "inserted": { + "boundElements": [], + "version": 4, + }, + }, + }, + }, + "id": "id18", + }, +] +`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] undo stack 1`] = ` [ @@ -16185,14 +16642,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], "height": 0, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -16202,7 +16665,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + 88, 0, ], ], @@ -16211,23 +16674,61 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 9, + "width": 88, + "x": 6, + "y": "0.00936", }, "inserted": { "isDeleted": true, - "version": 3, + "version": 8, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 4, + }, + "inserted": { + "boundElements": [], + "version": 3, + }, + }, + "id2": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 3, + }, + "inserted": { + "boundElements": [], + "version": 2, }, }, }, - "updated": {}, }, "id": "id15", }, @@ -16358,6 +16859,10 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id1", "type": "text", }, + { + "id": "id13", + "type": "arrow", + }, ], "customData": undefined, "fillStyle": "solid", @@ -16377,7 +16882,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 6, "width": 100, "x": -100, "y": -50, @@ -16415,7 +16920,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 4, + "version": 6, "verticalAlign": "middle", "width": 30, "x": -65, @@ -16427,7 +16932,12 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -16446,7 +16956,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 5, "width": 100, "x": 100, "y": -50, @@ -16461,7 +16971,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], @@ -16469,9 +16986,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id13", "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -16479,7 +16996,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -16488,22 +17005,29 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": "88.00000", + "x": 6, + "y": "0.01000", } `; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of renders 1`] = `10`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of renders 1`] = `13`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] redo stack 1`] = `[]`; @@ -16755,14 +17279,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], "height": 0, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -16772,7 +17302,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -16781,25 +17311,71 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": "88.00000", + "x": 6, + "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 3, + "version": 10, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 6, + }, + "inserted": { + "boundElements": [], + "version": 5, + }, + }, + "id1": { + "deleted": { + "version": 6, + }, + "inserted": { + "version": 5, + }, + }, + "id2": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 5, + }, + "inserted": { + "boundElements": [], + "version": 4, }, }, }, - "updated": {}, }, - "id": "id15", + "id": "id17", }, ] `; @@ -16928,6 +17504,10 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id1", "type": "text", }, + { + "id": "id13", + "type": "arrow", + }, ], "customData": undefined, "fillStyle": "solid", @@ -16947,7 +17527,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 10, "width": 100, "x": -100, "y": -50, @@ -16985,7 +17565,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 4, + "version": 10, "verticalAlign": "middle", "width": 30, "x": -65, @@ -16997,7 +17577,12 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -17016,7 +17601,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 7, "width": 100, "x": 100, "y": -50, @@ -17031,7 +17616,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], @@ -17039,9 +17631,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id13", "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -17049,7 +17641,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -17058,22 +17650,29 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": "88.00000", + "x": 6, + "y": "0.01000", } `; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of renders 1`] = `10`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of renders 1`] = `21`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] redo stack 1`] = `[]`; @@ -17110,14 +17709,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "rectangle", - "version": 2, + "version": 8, "width": 100, "x": -100, "y": -50, }, "inserted": { "isDeleted": true, - "version": 1, + "version": 7, }, }, "id1": { @@ -17149,7 +17748,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "text": "ola", "textAlign": "left", "type": "text", - "version": 2, + "version": 8, "verticalAlign": "top", "width": 100, "x": -200, @@ -17157,7 +17756,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, "inserted": { "isDeleted": true, - "version": 1, + "version": 7, }, }, "id2": { @@ -17181,20 +17780,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "rectangle", - "version": 2, + "version": 6, "width": 100, "x": 100, "y": -50, }, "inserted": { "isDeleted": true, - "version": 1, + "version": 5, }, }, }, "updated": {}, }, - "id": "id4", + "id": "id21", }, { "appState": AppStateDelta { @@ -17214,7 +17813,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "removed": {}, "updated": {}, }, - "id": "id7", + "id": "id22", }, { "appState": AppStateDelta { @@ -17234,7 +17833,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "removed": {}, "updated": {}, }, - "id": "id10", + "id": "id23", }, { "appState": AppStateDelta { @@ -17261,11 +17860,11 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "text", }, ], - "version": 3, + "version": 9, }, "inserted": { "boundElements": [], - "version": 2, + "version": 8, }, }, "id1": { @@ -17273,7 +17872,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "containerId": "id0", "height": 25, "textAlign": "center", - "version": 4, + "version": 9, "verticalAlign": "middle", "width": 30, "x": -65, @@ -17283,7 +17882,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "containerId": null, "height": 100, "textAlign": "left", - "version": 2, + "version": 8, "verticalAlign": "top", "width": 100, "x": -200, @@ -17292,7 +17891,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, }, }, - "id": "id12", + "id": "id24", }, { "appState": AppStateDelta { @@ -17325,14 +17924,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], "height": 0, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -17342,7 +17947,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -17351,25 +17956,71 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": "88.00000", + "x": 6, + "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 3, + "version": 10, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 10, + }, + "inserted": { + "boundElements": [], + "version": 9, + }, + }, + "id1": { + "deleted": { + "version": 10, + }, + "inserted": { + "version": 9, + }, + }, + "id2": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 7, + }, + "inserted": { + "boundElements": [], + "version": 6, }, }, }, - "updated": {}, }, - "id": "id15", + "id": "id25", }, ] `; @@ -17453,15 +18104,13 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, "penDetected": false, "penMode": false, - "previousSelectedElementIds": { - "id0": true, - }, + "previousSelectedElementIds": {}, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": null, "selectedElementIds": { - "id13": true, + "id0": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -17494,6 +18143,10 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "angle": 0, "backgroundColor": "transparent", "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, { "id": "id1", "type": "text", @@ -17517,7 +18170,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 6, "width": 100, "x": -100, "y": -50, @@ -17555,7 +18208,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 4, + "version": 6, "verticalAlign": "middle", "width": 30, "x": -65, @@ -17567,7 +18220,12 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -17586,7 +18244,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 4, "width": 100, "x": 100, "y": -50, @@ -17601,7 +18259,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], @@ -17609,9 +18274,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id13", "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -17619,7 +18284,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -17628,24 +18293,117 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 13, + "width": "88.00000", + "x": 6, + "y": "0.01000", } `; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `10`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `15`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = `[]`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = ` +[ + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id0": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elements": { + "added": {}, + "removed": { + "id0": { + "deleted": { + "isDeleted": false, + "version": 6, + }, + "inserted": { + "isDeleted": true, + "version": 5, + }, + }, + "id1": { + "deleted": { + "isDeleted": false, + "version": 6, + }, + "inserted": { + "isDeleted": true, + "version": 5, + }, + }, + }, + "updated": { + "id13": { + "deleted": { + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, + "version": 13, + }, + "inserted": { + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, + "startBinding": null, + "version": 10, + }, + }, + "id2": { + "deleted": { + "version": 4, + }, + "inserted": { + "version": 3, + }, + }, + }, + }, + "id": "id21", + }, +] +`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] undo stack 1`] = ` [ @@ -17895,14 +18653,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], "height": 0, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -17912,7 +18676,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + 88, 0, ], ], @@ -17921,26 +18685,91 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 9, + "width": 88, + "x": 6, + "y": "0.00936", }, "inserted": { "isDeleted": true, - "version": 3, + "version": 8, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 4, + }, + "inserted": { + "boundElements": [], + "version": 3, + }, + }, + "id2": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 3, + }, + "inserted": { + "boundElements": [], + "version": 2, }, }, }, - "updated": {}, }, "id": "id15", }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id0": true, + }, + "selectedLinearElement": null, + }, + "inserted": { + "selectedElementIds": { + "id13": true, + }, + "selectedLinearElement": { + "elementId": "id13", + "isEditing": false, + }, + }, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": {}, + }, + "id": "id18", + }, ] `; @@ -18031,7 +18860,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "scrollY": 0, "searchMatches": null, "selectedElementIds": { - "id13": true, + "id0": true, + "id2": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -18064,6 +18894,10 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "angle": 0, "backgroundColor": "transparent", "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, { "id": "id1", "type": "text", @@ -18087,7 +18921,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 6, "width": 100, "x": -100, "y": -50, @@ -18125,7 +18959,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 4, + "version": 6, "verticalAlign": "middle", "width": 30, "x": -65, @@ -18137,7 +18971,12 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding { "angle": 0, "backgroundColor": "transparent", - "boundElements": null, + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -18156,7 +18995,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 2, + "version": 5, "width": 100, "x": 100, "y": -50, @@ -18171,7 +19010,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], @@ -18179,9 +19025,9 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "id": "id13", "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, + "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -18189,7 +19035,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + "88.00000", 0, ], ], @@ -18198,24 +19044,113 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 14, + "width": "88.00000", + "x": 6, + "y": "0.01000", } `; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `10`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `16`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = `[]`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = ` +[ + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id0": true, + "id2": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elements": { + "added": {}, + "removed": { + "id0": { + "deleted": { + "isDeleted": false, + "version": 6, + }, + "inserted": { + "isDeleted": true, + "version": 5, + }, + }, + "id1": { + "deleted": { + "isDeleted": false, + "version": 6, + }, + "inserted": { + "isDeleted": true, + "version": 5, + }, + }, + "id2": { + "deleted": { + "isDeleted": false, + "version": 5, + }, + "inserted": { + "isDeleted": true, + "version": 4, + }, + }, + }, + "updated": { + "id13": { + "deleted": { + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, + "version": 14, + }, + "inserted": { + "endBinding": null, + "startBinding": null, + "version": 11, + }, + }, + }, + }, + "id": "id24", + }, +] +`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] undo stack 1`] = ` [ @@ -18465,14 +19400,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id2", + "fixedPoint": [ + 0, + "0.50010", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], "height": 0, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -18482,7 +19423,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - 100, + 88, 0, ], ], @@ -18491,26 +19432,111 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 4, - "width": 100, - "x": 0, - "y": 0, + "version": 9, + "width": 88, + "x": 6, + "y": "0.00936", }, "inserted": { "isDeleted": true, - "version": 3, + "version": 8, + }, + }, + }, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 4, + }, + "inserted": { + "boundElements": [], + "version": 3, + }, + }, + "id2": { + "deleted": { + "boundElements": [ + { + "id": "id13", + "type": "arrow", + }, + ], + "version": 3, + }, + "inserted": { + "boundElements": [], + "version": 2, }, }, }, - "updated": {}, }, "id": "id15", }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id0": true, + }, + "selectedLinearElement": null, + }, + "inserted": { + "selectedElementIds": { + "id13": true, + }, + "selectedLinearElement": { + "elementId": "id13", + "isEditing": false, + }, + }, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": {}, + }, + "id": "id18", + }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id2": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": {}, + }, + "id": "id21", + }, ] `; @@ -20092,10 +21118,6 @@ exports[`history > singleplayer undo/redo > should support linear element creati "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 20, - 0, - ], "link": null, "locked": false, "opacity": 100, @@ -20124,7 +21146,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 14, + "version": 12, "width": 20, "x": 0, "y": 0, @@ -20133,7 +21155,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] number of elements 1`] = `1`; -exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] number of renders 1`] = `23`; +exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] number of renders 1`] = `24`; exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] redo stack 1`] = `[]`; @@ -20175,10 +21197,6 @@ exports[`history > singleplayer undo/redo > should support linear element creati "height": 10, "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 10, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -20202,14 +21220,14 @@ exports[`history > singleplayer undo/redo > should support linear element creati "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 12, + "version": 10, "width": 10, "x": 0, "y": 0, }, "inserted": { "isDeleted": true, - "version": 11, + "version": 9, }, }, }, @@ -20230,10 +21248,6 @@ exports[`history > singleplayer undo/redo > should support linear element creati "updated": { "id0": { "deleted": { - "lastCommittedPoint": [ - 20, - 0, - ], "points": [ [ 0, @@ -20248,14 +21262,10 @@ exports[`history > singleplayer undo/redo > should support linear element creati 0, ], ], - "version": 13, + "version": 11, "width": 20, }, "inserted": { - "lastCommittedPoint": [ - 10, - 10, - ], "points": [ [ 0, @@ -20266,7 +21276,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati 10, ], ], - "version": 12, + "version": 10, "width": 10, }, }, @@ -20326,7 +21336,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati 20, ], ], - "version": 14, + "version": 12, }, "inserted": { "height": 10, @@ -20344,7 +21354,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati 0, ], ], - "version": 13, + "version": 11, }, }, }, diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 556a41c35b..2431240933 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -95,3 +95,141 @@ exports[`move element > rectangle 5`] = ` "y": 40, } `; + +exports[`move element > rectangles with binding arrow 5`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id6", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "id": "id0", + "index": "a0", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": null, + "seed": 1278240551, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 4, + "versionNonce": 640725609, + "width": 100, + "x": 0, + "y": 0, +} +`; + +exports[`move element > rectangles with binding arrow 6`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id6", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 300, + "id": "id3", + "index": "a1", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": null, + "seed": 1116226695, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 7, + "versionNonce": 1051383431, + "width": 300, + "x": 201, + "y": 2, +} +`; + +exports[`move element > rectangles with binding arrow 7`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id3", + "fixedPoint": [ + "-0.03333", + "0.43333", + ], + "mode": "orbit", + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": "90.03375", + "id": "id6", + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "moveMidPointsWithElement": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + 89, + "90.03375", + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "seed": 23633383, + "startArrowhead": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.10000", + "0.50010", + ], + "mode": "orbit", + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "updated": 1, + "version": 9, + "versionNonce": 1996028265, + "width": 89, + "x": 106, + "y": "46.01049", +} +`; diff --git a/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap index 821f1f6be3..03bec27275 100644 --- a/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap @@ -16,10 +16,6 @@ exports[`multi point mode in linear elements > arrow 3`] = ` "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 70, - 110, - ], "link": null, "locked": false, "opacity": 100, @@ -49,8 +45,8 @@ exports[`multi point mode in linear elements > arrow 3`] = ` "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 7, - "versionNonce": 400692809, + "version": 5, + "versionNonce": 1014066025, "width": 70, "x": 30, "y": 30, @@ -72,10 +68,6 @@ exports[`multi point mode in linear elements > line 3`] = ` "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 70, - 110, - ], "link": null, "locked": false, "opacity": 100, @@ -104,8 +96,8 @@ exports[`multi point mode in linear elements > line 3`] = ` "strokeWidth": 2, "type": "line", "updated": 1, - "version": 7, - "versionNonce": 400692809, + "version": 5, + "versionNonce": 1014066025, "width": 70, "x": 30, "y": 30, diff --git a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap index b560c4c914..1ebcf05750 100644 --- a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap @@ -6242,7 +6242,7 @@ exports[`regression tests > draw every type of shape > [end of test] appState 1` exports[`regression tests > draw every type of shape > [end of test] number of elements 1`] = `0`; -exports[`regression tests > draw every type of shape > [end of test] number of renders 1`] = `31`; +exports[`regression tests > draw every type of shape > [end of test] number of renders 1`] = `35`; exports[`regression tests > draw every type of shape > [end of test] redo stack 1`] = `[]`; @@ -6446,7 +6446,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "height": 10, "index": "a3", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -6525,7 +6524,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "height": 10, "index": "a4", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -6604,10 +6602,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "height": 10, "index": "a5", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -6631,14 +6625,14 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 5, + "version": 4, "width": 50, "x": 310, "y": -10, }, "inserted": { "isDeleted": true, - "version": 4, + "version": 3, }, }, }, @@ -6660,10 +6654,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "id15": { "deleted": { "height": 20, - "lastCommittedPoint": [ - 80, - 20, - ], "points": [ [ 0, @@ -6678,15 +6668,11 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack 20, ], ], - "version": 7, + "version": 5, "width": 80, }, "inserted": { "height": 10, - "lastCommittedPoint": [ - 50, - 10, - ], "points": [ [ 0, @@ -6697,7 +6683,7 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack 10, ], ], - "version": 5, + "version": 4, "width": 50, }, }, @@ -6712,7 +6698,10 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "selectedElementIds": { "id20": true, }, - "selectedLinearElement": null, + "selectedLinearElement": { + "elementId": "id20", + "isEditing": false, + }, }, "inserted": { "selectedElementIds": { @@ -6742,10 +6731,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "height": 10, "index": "a6", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -6768,14 +6753,14 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "strokeStyle": "solid", "strokeWidth": 2, "type": "line", - "version": 5, + "version": 4, "width": 50, "x": 430, "y": -10, }, "inserted": { "isDeleted": true, - "version": 4, + "version": 3, }, }, }, @@ -6797,10 +6782,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "id20": { "deleted": { "height": 20, - "lastCommittedPoint": [ - 80, - 20, - ], "points": [ [ 0, @@ -6815,15 +6796,11 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack 20, ], ], - "version": 7, + "version": 5, "width": 80, }, "inserted": { "height": 10, - "lastCommittedPoint": [ - 50, - 10, - ], "points": [ [ 0, @@ -6834,7 +6811,7 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack 10, ], ], - "version": 5, + "version": 4, "width": 50, }, }, @@ -6842,27 +6819,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack }, "id": "id24", }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedLinearElement": { - "elementId": "id20", - "isEditing": false, - }, - }, - "inserted": { - "selectedLinearElement": null, - }, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": {}, - }, - "id": "id26", - }, { "appState": AppStateDelta { "delta": Delta { @@ -6881,7 +6837,7 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "removed": {}, "updated": {}, }, - "id": "id28", + "id": "id26", }, { "appState": AppStateDelta { @@ -6900,7 +6856,7 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "elements": { "added": {}, "removed": { - "id29": { + "id27": { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -6912,10 +6868,6 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "height": 10, "index": "a7", "isDeleted": false, - "lastCommittedPoint": [ - 50, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -6958,7 +6910,7 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack }, "updated": {}, }, - "id": "id31", + "id": "id29", }, ] `; @@ -8680,12 +8632,8 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1` "elbowed": false, "elementId": "id0", "hoverPointIndex": -1, - "isDragging": false, - "isEditing": false, - "lastUncommittedPoint": null, - "pointerDownState": { + "initialState": { "arrowStartIsInside": false, - "lastClickedIsEndPoint": false, "lastClickedPoint": -1, "origin": null, "prevSelectedPointsIndices": null, @@ -8695,6 +8643,11 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1` "value": null, }, }, + "isDragging": false, + "isEditing": false, + "lastCommittedPoint": null, + "lastUncommittedPoint": null, + "pointerDownState": undefined, "pointerOffset": { "x": 0, "y": 0, @@ -8728,7 +8681,7 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1` exports[`regression tests > key 5 selects arrow tool > [end of test] number of elements 1`] = `0`; -exports[`regression tests > key 5 selects arrow tool > [end of test] number of renders 1`] = `6`; +exports[`regression tests > key 5 selects arrow tool > [end of test] number of renders 1`] = `7`; exports[`regression tests > key 5 selects arrow tool > [end of test] redo stack 1`] = `[]`; @@ -8770,7 +8723,6 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] undo stack "height": 30, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -8908,12 +8860,8 @@ exports[`regression tests > key 6 selects line tool > [end of test] appState 1`] "elbowed": false, "elementId": "id0", "hoverPointIndex": -1, - "isDragging": false, - "isEditing": false, - "lastUncommittedPoint": null, - "pointerDownState": { + "initialState": { "arrowStartIsInside": false, - "lastClickedIsEndPoint": false, "lastClickedPoint": -1, "origin": null, "prevSelectedPointsIndices": null, @@ -8923,6 +8871,11 @@ exports[`regression tests > key 6 selects line tool > [end of test] appState 1`] "value": null, }, }, + "isDragging": false, + "isEditing": false, + "lastCommittedPoint": null, + "lastUncommittedPoint": null, + "pointerDownState": undefined, "pointerOffset": { "x": 0, "y": 0, @@ -8956,7 +8909,7 @@ exports[`regression tests > key 6 selects line tool > [end of test] appState 1`] exports[`regression tests > key 6 selects line tool > [end of test] number of elements 1`] = `0`; -exports[`regression tests > key 6 selects line tool > [end of test] number of renders 1`] = `6`; +exports[`regression tests > key 6 selects line tool > [end of test] number of renders 1`] = `7`; exports[`regression tests > key 6 selects line tool > [end of test] redo stack 1`] = `[]`; @@ -8997,7 +8950,6 @@ exports[`regression tests > key 6 selects line tool > [end of test] undo stack 1 "height": 30, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -9182,10 +9134,6 @@ exports[`regression tests > key 7 selects freedraw tool > [end of test] undo sta "height": 30, "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 30, - 30, - ], "link": null, "locked": false, "opacity": 100, @@ -9329,12 +9277,8 @@ exports[`regression tests > key a selects arrow tool > [end of test] appState 1` "elbowed": false, "elementId": "id0", "hoverPointIndex": -1, - "isDragging": false, - "isEditing": false, - "lastUncommittedPoint": null, - "pointerDownState": { + "initialState": { "arrowStartIsInside": false, - "lastClickedIsEndPoint": false, "lastClickedPoint": -1, "origin": null, "prevSelectedPointsIndices": null, @@ -9344,6 +9288,11 @@ exports[`regression tests > key a selects arrow tool > [end of test] appState 1` "value": null, }, }, + "isDragging": false, + "isEditing": false, + "lastCommittedPoint": null, + "lastUncommittedPoint": null, + "pointerDownState": undefined, "pointerOffset": { "x": 0, "y": 0, @@ -9377,7 +9326,7 @@ exports[`regression tests > key a selects arrow tool > [end of test] appState 1` exports[`regression tests > key a selects arrow tool > [end of test] number of elements 1`] = `0`; -exports[`regression tests > key a selects arrow tool > [end of test] number of renders 1`] = `6`; +exports[`regression tests > key a selects arrow tool > [end of test] number of renders 1`] = `7`; exports[`regression tests > key a selects arrow tool > [end of test] redo stack 1`] = `[]`; @@ -9419,7 +9368,6 @@ exports[`regression tests > key a selects arrow tool > [end of test] undo stack "height": 30, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -9736,12 +9684,8 @@ exports[`regression tests > key l selects line tool > [end of test] appState 1`] "elbowed": false, "elementId": "id0", "hoverPointIndex": -1, - "isDragging": false, - "isEditing": false, - "lastUncommittedPoint": null, - "pointerDownState": { + "initialState": { "arrowStartIsInside": false, - "lastClickedIsEndPoint": false, "lastClickedPoint": -1, "origin": null, "prevSelectedPointsIndices": null, @@ -9751,6 +9695,11 @@ exports[`regression tests > key l selects line tool > [end of test] appState 1`] "value": null, }, }, + "isDragging": false, + "isEditing": false, + "lastCommittedPoint": null, + "lastUncommittedPoint": null, + "pointerDownState": undefined, "pointerOffset": { "x": 0, "y": 0, @@ -9784,7 +9733,7 @@ exports[`regression tests > key l selects line tool > [end of test] appState 1`] exports[`regression tests > key l selects line tool > [end of test] number of elements 1`] = `0`; -exports[`regression tests > key l selects line tool > [end of test] number of renders 1`] = `6`; +exports[`regression tests > key l selects line tool > [end of test] number of renders 1`] = `7`; exports[`regression tests > key l selects line tool > [end of test] redo stack 1`] = `[]`; @@ -9825,7 +9774,6 @@ exports[`regression tests > key l selects line tool > [end of test] undo stack 1 "height": 30, "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -10189,10 +10137,6 @@ exports[`regression tests > key p selects freedraw tool > [end of test] undo sta "height": 30, "index": "a0", "isDeleted": false, - "lastCommittedPoint": [ - 30, - 30, - ], "link": null, "locked": false, "opacity": 100, @@ -14530,7 +14474,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] appStat exports[`regression tests > undo/redo drawing an element > [end of test] number of elements 1`] = `0`; -exports[`regression tests > undo/redo drawing an element > [end of test] number of renders 1`] = `18`; +exports[`regression tests > undo/redo drawing an element > [end of test] number of renders 1`] = `19`; exports[`regression tests > undo/redo drawing an element > [end of test] redo stack 1`] = ` [ @@ -14548,10 +14492,6 @@ exports[`regression tests > undo/redo drawing an element > [end of test] redo st "id6": { "deleted": { "height": 10, - "lastCommittedPoint": [ - 60, - 10, - ], "points": [ [ 0, @@ -14562,15 +14502,11 @@ exports[`regression tests > undo/redo drawing an element > [end of test] redo st 10, ], ], - "version": 8, + "version": 6, "width": 60, }, "inserted": { "height": 20, - "lastCommittedPoint": [ - 100, - 20, - ], "points": [ [ 0, @@ -14585,7 +14521,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] redo st 20, ], ], - "version": 7, + "version": 5, "width": 100, }, }, @@ -14618,7 +14554,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] redo st "id6": { "deleted": { "isDeleted": true, - "version": 9, + "version": 7, }, "inserted": { "angle": 0, @@ -14634,10 +14570,6 @@ exports[`regression tests > undo/redo drawing an element > [end of test] redo st "height": 10, "index": "a2", "isDeleted": false, - "lastCommittedPoint": [ - 60, - 10, - ], "link": null, "locked": false, "opacity": 100, @@ -14661,7 +14593,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] redo st "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 8, + "version": 6, "width": 60, "x": 130, "y": 10, diff --git a/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap index f47b89813f..5d5c701f0a 100644 --- a/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap @@ -16,7 +16,6 @@ exports[`select single element on the scene > arrow 1`] = ` "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -65,7 +64,6 @@ exports[`select single element on the scene > arrow escape 1`] = ` "id": "id0", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, diff --git a/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap b/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap index d59a829a0f..95826081f4 100644 --- a/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap +++ b/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap @@ -16,7 +16,6 @@ exports[`restoreElements > should restore arrow element correctly 1`] = ` "id": "id-arrow01", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -175,7 +174,6 @@ exports[`restoreElements > should restore freedraw element correctly 1`] = ` "id": "id-freedraw01", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -222,7 +220,6 @@ exports[`restoreElements > should restore line and draw elements correctly 1`] = "id": "id-line01", "index": "a0", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, @@ -270,7 +267,6 @@ exports[`restoreElements > should restore line and draw elements correctly 2`] = "id": "id-draw01", "index": "a1", "isDeleted": false, - "lastCommittedPoint": null, "link": null, "locked": false, "opacity": 100, diff --git a/packages/excalidraw/tests/dragCreate.test.tsx b/packages/excalidraw/tests/dragCreate.test.tsx index 566c839050..e943bce431 100644 --- a/packages/excalidraw/tests/dragCreate.test.tsx +++ b/packages/excalidraw/tests/dragCreate.test.tsx @@ -157,9 +157,9 @@ describe("Test dragCreate", () => { fireEvent.pointerUp(canvas); expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( - `5`, + `6`, ); - expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`); + expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); expect(h.state.selectionElement).toBeNull(); expect(h.elements.length).toEqual(1); @@ -195,9 +195,9 @@ describe("Test dragCreate", () => { fireEvent.pointerUp(canvas); expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( - `5`, + `6`, ); - expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`); + expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); expect(h.state.selectionElement).toBeNull(); expect(h.elements.length).toEqual(1); diff --git a/packages/excalidraw/tests/lasso.test.tsx b/packages/excalidraw/tests/lasso.test.tsx index d84ce1ffb9..f9a9d12d27 100644 --- a/packages/excalidraw/tests/lasso.test.tsx +++ b/packages/excalidraw/tests/lasso.test.tsx @@ -210,7 +210,6 @@ describe("Basic lasso selection tests", () => { [0, 0], [168.4765625, -153.38671875], ], - lastCommittedPoint: null, startBinding: null, endBinding: null, startArrowhead: null, @@ -250,7 +249,6 @@ describe("Basic lasso selection tests", () => { [0, 0], [206.12890625, 35.4140625], ], - lastCommittedPoint: null, startBinding: null, endBinding: null, startArrowhead: null, @@ -354,7 +352,6 @@ describe("Basic lasso selection tests", () => { ], pressures: [], simulatePressure: true, - lastCommittedPoint: null, }, ].map( (e) => @@ -1229,7 +1226,6 @@ describe("Special cases", () => { locked: false, startBinding: null, endBinding: null, - lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, points: [ @@ -1271,7 +1267,6 @@ describe("Special cases", () => { locked: false, startBinding: null, endBinding: null, - lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, points: [ @@ -1312,7 +1307,6 @@ describe("Special cases", () => { locked: false, startBinding: null, endBinding: null, - lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, points: [ @@ -1353,7 +1347,6 @@ describe("Special cases", () => { locked: false, startBinding: null, endBinding: null, - lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, points: [ @@ -1692,7 +1685,6 @@ describe("Special cases", () => { locked: false, startBinding: null, endBinding: null, - lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, points: [ @@ -1744,7 +1736,6 @@ describe("Special cases", () => { locked: false, startBinding: null, endBinding: null, - lastCommittedPoint: null, startArrowhead: null, endArrowhead: null, points: [ diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index 0417090bc0..dc7b92b007 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -102,16 +102,16 @@ describe("move element", () => { new Pointer("mouse").clickOn(rectB); expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( - `15`, + `16`, ); - expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`13`); + expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`14`); expect(h.state.selectionElement).toBeNull(); expect(h.elements.length).toEqual(3); expect(h.state.selectedElementIds[rectB.id]).toBeTruthy(); expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectB.x, rectB.y]).toEqual([200, 0]); - expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[105, 45]], 0); - expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[90, 90]], 0); + expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[110, 50]], 0); + expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[80, 80]], 0); renderInteractiveScene.mockClear(); renderStaticScene.mockClear(); @@ -129,8 +129,11 @@ describe("move element", () => { expect(h.state.selectedElementIds[rectB.id]).toBeTruthy(); expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectB.x, rectB.y]).toEqual([201, 2]); - expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[105, 45]], 0); - expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[91, 91]], 0); + expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[106, 46]], 0); + expect([[arrow.width, arrow.height]]).toCloselyEqualPoints( + [[89, 90.033]], + 0, + ); h.elements.forEach((element) => expect(element).toMatchSnapshot()); }); diff --git a/packages/excalidraw/tests/multiPointCreate.test.tsx b/packages/excalidraw/tests/multiPointCreate.test.tsx index 926c8d47f3..73aae8b24b 100644 --- a/packages/excalidraw/tests/multiPointCreate.test.tsx +++ b/packages/excalidraw/tests/multiPointCreate.test.tsx @@ -118,8 +118,8 @@ describe("multi point mode in linear elements", () => { key: KEYS.ENTER, }); - expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(`7`); - expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); + expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(`11`); + expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`); expect(h.elements.length).toEqual(1); const element = h.elements[0] as ExcalidrawLinearElement; @@ -161,8 +161,8 @@ describe("multi point mode in linear elements", () => { fireEvent.keyDown(document, { key: KEYS.ENTER, }); - expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(`7`); - expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); + expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(`11`); + expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`); expect(h.elements.length).toEqual(1); const element = h.elements[0] as ExcalidrawLinearElement; diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index dfd20767f0..03b5f615ec 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -24,7 +24,7 @@ test("unselected bound arrow updates when rotating its target element", async () const arrow = UI.createElement("arrow", { x: -80, y: 50, - width: 70, + width: 85, height: 0, }); @@ -35,8 +35,8 @@ test("unselected bound arrow updates when rotating its target element", async () expect(arrow.endBinding?.elementId).toEqual(rectangle.id); expect(arrow.x).toBeCloseTo(-80); expect(arrow.y).toBeCloseTo(50); - expect(arrow.width).toBeCloseTo(81.75, 1); - expect(arrow.height).toBeCloseTo(62.3, 1); + expect(arrow.width).toBeCloseTo(84.9, 1); + expect(arrow.height).toBeCloseTo(52.717, 1); }); test("unselected bound arrows update when rotating their target elements", async () => { @@ -48,9 +48,10 @@ test("unselected bound arrows update when rotating their target elements", async height: 120, }); const ellipseArrow = UI.createElement("arrow", { - position: 0, - width: 40, - height: 80, + x: -10, + y: 80, + width: 50, + height: 60, }); const text = UI.createElement("text", { position: 220, @@ -59,8 +60,8 @@ test("unselected bound arrows update when rotating their target elements", async const textArrow = UI.createElement("arrow", { x: 360, y: 300, - width: -100, - height: -40, + width: -140, + height: -60, }); expect(ellipseArrow.endBinding?.elementId).toEqual(ellipse.id); @@ -69,16 +70,16 @@ test("unselected bound arrows update when rotating their target elements", async UI.rotate([ellipse, text], [-82, 23], { shift: true }); expect(ellipseArrow.endBinding?.elementId).toEqual(ellipse.id); - expect(ellipseArrow.x).toEqual(0); - expect(ellipseArrow.y).toEqual(0); + expect(ellipseArrow.x).toEqual(-10); + expect(ellipseArrow.y).toEqual(80); expect(ellipseArrow.points[0]).toEqual([0, 0]); - expect(ellipseArrow.points[1][0]).toBeCloseTo(16.52, 1); - expect(ellipseArrow.points[1][1]).toBeCloseTo(216.57, 1); + expect(ellipseArrow.points[1][0]).toBeCloseTo(42.318, 1); + expect(ellipseArrow.points[1][1]).toBeCloseTo(92.133, 1); expect(textArrow.endBinding?.elementId).toEqual(text.id); expect(textArrow.x).toEqual(360); expect(textArrow.y).toEqual(300); expect(textArrow.points[0]).toEqual([0, 0]); - expect(textArrow.points[1][0]).toBeCloseTo(-63, 0); - expect(textArrow.points[1][1]).toBeCloseTo(-146, 0); + expect(textArrow.points[1][0]).toBeCloseTo(-98.86, 0); + expect(textArrow.points[1][1]).toBeCloseTo(-123.65, 0); }); diff --git a/packages/excalidraw/tests/selection.test.tsx b/packages/excalidraw/tests/selection.test.tsx index 19e3b9a485..dde3c96e48 100644 --- a/packages/excalidraw/tests/selection.test.tsx +++ b/packages/excalidraw/tests/selection.test.tsx @@ -425,8 +425,8 @@ describe("select single element on the scene", () => { fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 }); fireEvent.pointerUp(canvas); - expect(renderInteractiveScene).toHaveBeenCalledTimes(8); - expect(renderStaticScene).toHaveBeenCalledTimes(6); + expect(renderInteractiveScene).toHaveBeenCalledTimes(9); + expect(renderStaticScene).toHaveBeenCalledTimes(7); expect(h.state.selectionElement).toBeNull(); expect(h.elements.length).toEqual(1); expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy(); @@ -469,8 +469,8 @@ describe("select single element on the scene", () => { fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 }); fireEvent.pointerUp(canvas); - expect(renderInteractiveScene).toHaveBeenCalledTimes(8); - expect(renderStaticScene).toHaveBeenCalledTimes(6); + expect(renderInteractiveScene).toHaveBeenCalledTimes(9); + expect(renderStaticScene).toHaveBeenCalledTimes(7); expect(h.state.selectionElement).toBeNull(); expect(h.elements.length).toEqual(1); expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();