diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index c3b67bd3e..8ea4cfbf4 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -386,35 +386,58 @@ export class LinearElementEditor { } if (selectedPointsIndices && draggingPoint) { - const isDraggingPointBound = - (lastClickedPoint === 0 && element.startBinding) || - (lastClickedPoint === element.points.length - 1 && - element.endBinding); - - if (!isDraggingPointBound) { - const oppositePointIndex = - lastClickedPoint === 0 ? element.points.length - 1 : 0; - if (oppositePointIndex === 0 && element.startBinding) { - const startBindingElement = elementsMap.get( - element.startBinding.elementId, - ); - updateBoundElements(startBindingElement!, elementsMap, { - simultaneouslyUpdated: [startBindingElement!], - }); - } else if ( - oppositePointIndex === element.points.length - 1 && - element.endBinding - ) { - const endBindingElement = elementsMap.get( - element.endBinding.elementId, - ); - updateBoundElements(endBindingElement!, elementsMap, { - simultaneouslyUpdated: [endBindingElement!], - }); + // Temporarily remove the binding from the dragging point to avoid the element being pulled by the binding + let originalBinding: ExcalidrawBindableElement | "keep" | null = null; + if (lastClickedPoint === 0) { + originalBinding = element.startBinding as + | ExcalidrawBindableElement + | "keep" + | null; + bindOrUnbindLinearElement(element, null, "keep", elementsMap, scene); + } else if (lastClickedPoint === element.points.length - 1) { + originalBinding = element.endBinding as + | ExcalidrawBindableElement + | "keep" + | null; + bindOrUnbindLinearElement(element, "keep", null, elementsMap, scene); + } + + // Run updateBoundElements for the opposite point + if (element.startBinding) { + const startBindingElement = elementsMap.get( + element.startBinding.elementId, + ); + if (startBindingElement) { + updateBoundElements(startBindingElement, elementsMap); + } + } else if (element.endBinding) { + const endBindingElement = elementsMap.get( + element.endBinding.elementId, + ); + if (endBindingElement) { + updateBoundElements(endBindingElement, elementsMap); } } - } + // Restore the original binding + if (lastClickedPoint === 0) { + bindOrUnbindLinearElement( + element, + originalBinding, + "keep", + elementsMap, + scene, + ); + } else if (lastClickedPoint === element.points.length - 1) { + bindOrUnbindLinearElement( + element, + "keep", + originalBinding, + elementsMap, + scene, + ); + } + } return true; } diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 299b9f98f..3bf640ddc 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -167,7 +167,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 19, + "version": 21, "width": 100, "x": 100, "y": -50, @@ -223,7 +223,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 40, + "version": 43, "width": "98.20800", "x": 1, "y": 0, @@ -312,15 +312,18 @@ History { "focus": "0.02970", "gap": 1, }, + "width": 98, + "x": 1, + "y": "0.99000", }, "inserted": { "endBinding": { "elementId": "id165", "fixedPoint": null, - "focus": "-0.02000", + "focus": "-0.01668", "gap": 1, }, - "height": "0.00000", + "height": "0.32013", "points": [ [ 0, @@ -328,15 +331,18 @@ History { ], [ 98, - "0.00000", + "-0.32013", ], ], "startBinding": { "elementId": "id164", "fixedPoint": null, - "focus": "0.02000", + "focus": "0.02970", "gap": 1, }, + "width": 98, + "x": 1, + "y": "1.32340", }, }, }, @@ -428,7 +434,7 @@ History { "focus": "0.02970", "gap": 1, }, - "y": "0.99101", + "y": "0.99000", }, }, "id169" => Delta { @@ -769,7 +775,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 9, + "version": 11, "width": 100, "x": 150, "y": -50, @@ -817,7 +823,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 30, + "version": 36, "width": 0, "x": 200, "y": 0, @@ -856,6 +862,8 @@ History { 0, ], ], + "width": 0, + "x": 200, }, "inserted": { "points": [ @@ -864,10 +872,12 @@ History { 0, ], [ - 100, + 99, 0, ], ], + "width": 99, + "x": 1, }, }, },