diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index db9d309db0..78b23c5985 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -8472,7 +8472,7 @@ class App extends React.Component { this, ) : unbindLinearElements( - this.scene.getNonDeletedElements(), + this.scene.getSelectedElements(this.state), elementsMap, ); } diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index ba1258f379..6a1da1e7b7 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -293,7 +293,16 @@ export const unbindLinearElements = ( ): void => { elements.forEach((element) => { if (isBindingElement(element)) { - bindOrUnbindLinearElement(element, null, null, elementsMap); + if (element.startBinding !== null && element.endBinding !== null) { + bindOrUnbindLinearElement(element, null, null, elementsMap); + } else { + bindOrUnbindLinearElement( + element, + element.startBinding ? "keep" : null, + element.endBinding ? "keep" : null, + elementsMap, + ); + } } }); }; diff --git a/packages/excalidraw/tests/binding.test.tsx b/packages/excalidraw/tests/binding.test.tsx index 9e074c2e51..5223f6b0dc 100644 --- a/packages/excalidraw/tests/binding.test.tsx +++ b/packages/excalidraw/tests/binding.test.tsx @@ -369,4 +369,44 @@ describe("element binding", () => { expect(arrow2.startBinding?.elementId).toBe(container.id); expect(arrow2.endBinding?.elementId).toBe(rectangle1.id); }); + + // #6459 + it("should unbind arrow only from the latest element", () => { + const rectLeft = UI.createElement("rectangle", { + x: 0, + width: 200, + height: 500, + }); + const rectRight = UI.createElement("rectangle", { + x: 400, + width: 200, + height: 500, + }); + const arrow = UI.createElement("arrow", { + x: 210, + y: 250, + width: 180, + height: 1, + }); + expect(arrow.startBinding?.elementId).toBe(rectLeft.id); + expect(arrow.endBinding?.elementId).toBe(rectRight.id); + + // Drag arrow off of bound rectangle range + const handles = getTransformHandles( + arrow, + h.state.zoom, + arrayToMap(h.elements), + "mouse", + ).se!; + + Keyboard.keyDown(KEYS.CTRL_OR_CMD); + const elX = handles[0] + handles[2] / 2; + const elY = handles[1] + handles[3] / 2; + mouse.downAt(elX, elY); + mouse.moveTo(300, 400); + mouse.up(); + + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).toBe(null); + }); });