From e3ad1f593570b588558af959c62c5528f5216d86 Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Sat, 2 Aug 2025 10:24:28 +0200 Subject: [PATCH] Fix inconsistent arrow start jump out --- packages/excalidraw/components/App.tsx | 78 +++++++++++++++++--------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 057d72218c..f4e8b06333 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -4717,9 +4717,8 @@ class App extends React.Component { this.setState({ bindMode: "inside", }); - } else { - this.bindModeHandler = null; } + this.bindModeHandler = null; }, BIND_MODE_TIMEOUT); } } @@ -6163,11 +6162,21 @@ class App extends React.Component { flushSync(() => { this.setState({ bindMode: "inside", + selectedLinearElement: this.state.selectedLinearElement + ? { + ...this.state.selectedLinearElement, + pointerDownState: { + ...this.state.selectedLinearElement + .pointerDownState, + arrowStartIsInside: true, + }, + } + : null, }); }); - } else { - this.bindModeHandler = null; } + + this.bindModeHandler = null; }, BIND_MODE_TIMEOUT); } } else if (!hoveredElement) { @@ -6893,8 +6902,9 @@ class App extends React.Component { if (this.state.bindMode === "inside" || this.state.bindMode === "skip") { if (this.bindModeHandler) { clearTimeout(this.bindModeHandler); + this.bindModeHandler = null; } - this.bindModeHandler = null; + // We need this iteration to complete binding and change // back to orbit mode after that setTimeout(() => @@ -7009,8 +7019,9 @@ class App extends React.Component { private maybeCleanupAfterMissingPointerUp = (event: PointerEvent | null) => { if (this.bindModeHandler) { clearTimeout(this.bindModeHandler); + this.bindModeHandler = null; } - this.bindModeHandler = null; + this.setState({ bindMode: "orbit", }); @@ -8095,19 +8106,6 @@ class App extends React.Component { this.state.zoom, ); - if (isSimpleArrow(element)) { - this.setState((prevState) => { - const nextSelectedElementIds = makeNextSelectedElementIds( - { [element.id]: true }, - prevState, - ); - - return { - selectedElementIds: nextSelectedElementIds, - }; - }); - } - this.scene.mutateElement(element, { points: [pointFrom(0, 0), pointFrom(0, 0)], }); @@ -8132,6 +8130,29 @@ class App extends React.Component { { newArrow: true }, ); } + + if (isSimpleArrow(element)) { + if (this.bindModeHandler) { + clearTimeout(this.bindModeHandler); + this.bindModeHandler = null; + } + + this.bindModeHandler = setTimeout(() => { + this.setState({ + bindMode: "inside", + selectedLinearElement: this.state.selectedLinearElement + ? { + ...this.state.selectedLinearElement, + pointerDownState: { + ...this.state.selectedLinearElement?.pointerDownState, + arrowStartIsInside: !!boundElement, + }, + } + : null, + }); + }, BIND_MODE_TIMEOUT); + } + this.setState((prevState) => { let linearElementEditor = null; let nextSelectedElementIds = prevState.selectedElementIds; @@ -8156,11 +8177,6 @@ class App extends React.Component { ); } - if (this.bindModeHandler) { - clearTimeout(this.bindModeHandler); - } - this.bindModeHandler = null; - return { ...prevState, bindMode: "orbit", @@ -8547,6 +8563,16 @@ class App extends React.Component { flushSync(() => { this.setState({ bindMode: "inside", + selectedLinearElement: this.state.selectedLinearElement + ? { + ...this.state.selectedLinearElement, + pointerDownState: { + ...this.state.selectedLinearElement + .pointerDownState, + arrowStartIsInside: true, + }, + } + : null, }); }); @@ -8587,9 +8613,9 @@ class App extends React.Component { this.setState(newState); } - } else { - this.bindModeHandler = null; } + + this.bindModeHandler = null; }, BIND_MODE_TIMEOUT); } } else if (!hoveredElement) {