From 7e38c3169c66c514dcab7e2179bb5e032629e857 Mon Sep 17 00:00:00 2001 From: dwelle <5153846+dwelle@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:02:30 +0100 Subject: [PATCH] reset selectionLinearElement on tool change --- packages/common/src/utils.ts | 4 +++ packages/excalidraw/components/App.tsx | 25 ++++++------- .../regressionTests.test.tsx.snap | 35 ++++--------------- 3 files changed, 20 insertions(+), 44 deletions(-) diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index f2bb2c47c6..356f951521 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -378,6 +378,10 @@ export const removeSelection = () => { export const distance = (x: number, y: number) => Math.abs(x - y); +export const isSelectionLikeTool = (type: ToolType | "custom") => { + return type === "selection" || type === "lasso"; +}; + export const updateActiveTool = ( appState: Pick, data: (( diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 4f0c850196..79371ccf11 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -108,6 +108,7 @@ import { type StylesPanelMode, loadDesktopUIModePreference, setDesktopUIMode, + isSelectionLikeTool, } from "@excalidraw/common"; import { @@ -5001,10 +5002,7 @@ class App extends React.Component { this.state.openDialog?.name === "elementLinkSelector" ) { setCursor(this.interactiveCanvas, CURSOR_TYPE.GRAB); - } else if ( - this.state.activeTool.type === "selection" || - this.state.activeTool.type === "lasso" - ) { + } else if (isSelectionLikeTool(this.state.activeTool.type)) { resetCursor(this.interactiveCanvas); } else { setCursorForShape(this.interactiveCanvas, this.state); @@ -5215,6 +5213,9 @@ class App extends React.Component { snapLines: prevState.snapLines.length ? [] : prevState.snapLines, originSnapOffset: null, activeEmbeddable: null, + selectedLinearElement: isSelectionLikeTool(nextActiveTool.type) + ? prevState.selectedLinearElement + : null, } as const; if (nextActiveTool.type === "freedraw") { @@ -5224,6 +5225,7 @@ class App extends React.Component { if (nextActiveTool.type === "lasso") { return { ...prevState, + ...commonResets, activeTool: nextActiveTool, ...(keepSelection ? {} @@ -5233,23 +5235,22 @@ class App extends React.Component { editingGroupId: null, multiElement: null, }), - ...commonResets, }; } else if (nextActiveTool.type !== "selection") { return { ...prevState, + ...commonResets, activeTool: nextActiveTool, selectedElementIds: makeNextSelectedElementIds({}, prevState), selectedGroupIds: makeNextSelectedElementIds({}, prevState), editingGroupId: null, multiElement: null, - ...commonResets, }; } return { ...prevState, - activeTool: nextActiveTool, ...commonResets, + activeTool: nextActiveTool, }; }); }; @@ -7713,10 +7714,7 @@ class App extends React.Component { } private clearSelectionIfNotUsingSelection = (): void => { - if ( - this.state.activeTool.type !== "selection" && - this.state.activeTool.type !== "lasso" - ) { + if (!isSelectionLikeTool(this.state.activeTool.type)) { this.setState({ selectedElementIds: makeNextSelectedElementIds({}, this.state), selectedGroupIds: {}, @@ -7733,10 +7731,7 @@ class App extends React.Component { event: React.PointerEvent, pointerDownState: PointerDownState, ): boolean => { - if ( - this.state.activeTool.type === "selection" || - this.state.activeTool.type === "lasso" - ) { + if (isSelectionLikeTool(this.state.activeTool.type)) { const elements = this.scene.getNonDeletedElements(); const elementsMap = this.scene.getNonDeletedElementsMap(); const selectedElements = this.scene.getSelectedElements(this.state); diff --git a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap index 9eef51ae91..ecea596167 100644 --- a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap @@ -6299,35 +6299,7 @@ exports[`regression tests > draw every type of shape > [end of test] appState 1` "selectedElementIds": {}, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, - "selectedLinearElement": { - "customLineAngle": null, - "elbowed": false, - "elementId": "id20", - "hoverPointIndex": -1, - "initialState": { - "altFocusPoint": null, - "arrowStartIsInside": false, - "lastClickedPoint": -1, - "origin": null, - "prevSelectedPointsIndices": null, - "segmentMidpoint": { - "added": false, - "index": null, - "value": null, - }, - }, - "isDragging": false, - "isEditing": false, - "lastCommittedPoint": null, - "lastUncommittedPoint": null, - "pointerDownState": undefined, - "pointerOffset": { - "x": 0, - "y": 0, - }, - "segmentMidPointHoveredCoords": null, - "selectedPointsIndices": null, - }, + "selectedLinearElement": null, "selectionElement": null, "shouldCacheIgnoreZoom": false, "showHyperlinkPopup": false, @@ -6936,11 +6908,16 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack "delta": Delta { "deleted": { "selectedElementIds": {}, + "selectedLinearElement": null, }, "inserted": { "selectedElementIds": { "id20": true, }, + "selectedLinearElement": { + "elementId": "id20", + "isEditing": false, + }, }, }, },