From 7e737f233ce8861e97ded97ddfcf82cd81149007 Mon Sep 17 00:00:00 2001 From: Ryan Di Date: Fri, 21 Mar 2025 00:54:48 +1100 Subject: [PATCH] shift for additive selection --- packages/excalidraw/components/App.tsx | 15 ++++++++++++--- packages/excalidraw/lasso/index.ts | 23 +++++++++++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 8e21f2075..dbeb5b3a3 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -6562,6 +6562,7 @@ class App extends React.Component { this.lassoTrail.startPath( pointerDownState.origin.x, pointerDownState.origin.y, + event.shiftKey, ); } else if (this.state.activeTool.type === "text") { this.handleTextOnPointerDown(event, pointerDownState); @@ -7020,7 +7021,10 @@ class App extends React.Component { } private clearSelectionIfNotUsingSelection = (): void => { - if (this.state.activeTool.type !== "selection") { + if ( + this.state.activeTool.type !== "selection" && + this.state.activeTool.type !== "lasso" + ) { this.setState({ selectedElementIds: makeNextSelectedElementIds({}, this.state), selectedGroupIds: {}, @@ -8261,7 +8265,8 @@ class App extends React.Component { selectedElements.length > 0 && !pointerDownState.withCmdOrCtrl && !this.state.editingTextElement && - this.state.activeEmbeddable?.state !== "active" + this.state.activeEmbeddable?.state !== "active" && + this.state.activeTool.type !== "lasso" ) { const dragOffset = { x: pointerCoords.x - pointerDownState.origin.x, @@ -8611,7 +8616,11 @@ class App extends React.Component { this.lassoTrail.endPath(); selectionSwitch = false; } else { - this.lassoTrail.addPointToPath(pointerCoords.x, pointerCoords.y); + this.lassoTrail.addPointToPath( + pointerCoords.x, + pointerCoords.y, + event.shiftKey, + ); } } else { // It is very important to read this.state within each move event, diff --git a/packages/excalidraw/lasso/index.ts b/packages/excalidraw/lasso/index.ts index 6bb4a9838..df7df8ebb 100644 --- a/packages/excalidraw/lasso/index.ts +++ b/packages/excalidraw/lasso/index.ts @@ -26,6 +26,7 @@ export class LassoTrail extends AnimatedTrail { private worker: Worker | null = null; private elementsSegments: Map[]> | null = null; + private keepPreviousSelection: boolean = false; constructor(animationFrameHandler: AnimationFrameHandler, app: App) { super(animationFrameHandler, app, { @@ -49,7 +50,7 @@ export class LassoTrail extends AnimatedTrail { }); } - startPath(x: number, y: number) { + startPath(x: number, y: number, keepPreviousSelection = false) { // clear any existing trails just in case this.endPath(); @@ -57,6 +58,16 @@ export class LassoTrail extends AnimatedTrail { this.intersectedElements.clear(); this.enclosedElements.clear(); + this.keepPreviousSelection = keepPreviousSelection; + + if (!this.keepPreviousSelection) { + this.app.setState({ + selectedElementIds: {}, + selectedGroupIds: {}, + selectedLinearElement: null, + }); + } + try { this.worker = new LassoWorker(); @@ -80,6 +91,12 @@ export class LassoTrail extends AnimatedTrail { return acc; }, {} as Record); + if (this.keepPreviousSelection) { + for (const id of Object.keys(prevState.selectedElementIds)) { + nextSelectedElementIds[id] = true; + } + } + for (const [id] of Object.entries(nextSelectedElementIds)) { const element = this.app.scene.getNonDeletedElement(id); if (element && isFrameLikeElement(element)) { @@ -123,9 +140,11 @@ export class LassoTrail extends AnimatedTrail { }); }; - addPointToPath = (x: number, y: number) => { + addPointToPath = (x: number, y: number, keepPreviousSelection = false) => { super.addPointToPath(x, y); + this.keepPreviousSelection = keepPreviousSelection; + this.app.setState({ lassoSelection: { points: