From b0cdf1c2964f6a312c3065d3c72f91c9ea180193 Mon Sep 17 00:00:00 2001 From: Ryan Di Date: Wed, 26 Feb 2025 20:10:05 +1100 Subject: [PATCH] improve ux --- packages/excalidraw/actions/actionCanvas.tsx | 34 +++++++++++ packages/excalidraw/actions/types.ts | 3 +- packages/excalidraw/components/Actions.tsx | 23 +++++--- packages/excalidraw/components/App.tsx | 56 ++++++++++-------- .../CommandPalette/CommandPalette.tsx | 1 + packages/excalidraw/components/HintViewer.tsx | 2 +- packages/excalidraw/lasso/index.ts | 3 + packages/excalidraw/locales/en.json | 1 - .../__snapshots__/contextmenu.test.tsx.snap | 17 ++++++ .../tests/__snapshots__/history.test.tsx.snap | 58 +++++++++++++++++++ .../regressionTests.test.tsx.snap | 52 +++++++++++++++++ .../utils/__snapshots__/export.test.ts.snap | 1 + 12 files changed, 215 insertions(+), 36 deletions(-) diff --git a/packages/excalidraw/actions/actionCanvas.tsx b/packages/excalidraw/actions/actionCanvas.tsx index 3b3a12b98..56645ad30 100644 --- a/packages/excalidraw/actions/actionCanvas.tsx +++ b/packages/excalidraw/actions/actionCanvas.tsx @@ -1,6 +1,7 @@ import { ColorPicker } from "../components/ColorPicker/ColorPicker"; import { handIcon, + LassoIcon, MoonIcon, SunIcon, TrashIcon, @@ -516,6 +517,39 @@ export const actionToggleEraserTool = register({ keyTest: (event) => event.key === KEYS.E, }); +export const actionToggleLassoTool = register({ + name: "toggleLassoTool", + label: "toolBar.lasso", + icon: LassoIcon, + paletteName: "Toggle lasso selection tool", + trackEvent: { category: "toolbar" }, + perform: (elements, appState, _, app) => { + let activeTool: AppState["activeTool"]; + + if (appState.activeTool.type !== "lasso") { + activeTool = updateActiveTool(appState, { + type: "lasso", + }); + setCursor(app.interactiveCanvas, CURSOR_TYPE.CROSSHAIR); + } else { + activeTool = updateActiveTool(appState, { + type: "selection", + }); + } + + return { + appState: { + ...appState, + selectedElementIds: {}, + selectedGroupIds: {}, + activeEmbeddable: null, + activeTool, + }, + storeAction: StoreAction.CAPTURE, + }; + }, +}); + export const actionToggleHandTool = register({ name: "toggleHandTool", label: "toolBar.hand", diff --git a/packages/excalidraw/actions/types.ts b/packages/excalidraw/actions/types.ts index 1627b2fca..49c4508ec 100644 --- a/packages/excalidraw/actions/types.ts +++ b/packages/excalidraw/actions/types.ts @@ -138,7 +138,8 @@ export type ActionName = | "copyElementLink" | "linkToElement" | "cropEditor" - | "wrapSelectionInFrame"; + | "wrapSelectionInFrame" + | "toggleLassoTool"; export type PanelComponentProps = { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/Actions.tsx b/packages/excalidraw/components/Actions.tsx index 319aef7ce..cb948ec55 100644 --- a/packages/excalidraw/components/Actions.tsx +++ b/packages/excalidraw/components/Actions.tsx @@ -281,12 +281,12 @@ export const ShapesSwitcher = ({ const frameToolSelected = activeTool.type === "frame"; const laserToolSelected = activeTool.type === "laser"; + const lassoToolSelected = activeTool.type === "lasso"; + const embeddableToolSelected = activeTool.type === "embeddable"; const { TTDDialogTriggerTunnel } = useTunnels(); - const lasso = appState.activeTool.type === "lasso"; - return ( <> {SHAPES.map(({ value, icon, key, numericKey, fillable }, index) => { @@ -305,17 +305,13 @@ export const ShapesSwitcher = ({ ? `${letter} ${t("helpDialog.or")} ${numericKey}` : `${numericKey}`; - const _icon = value === "selection" && lasso ? LassoIcon : icon; - const _fillable = value === "selection" && lasso ? false : fillable; return ( {t("toolBar.laser")} + app.setActiveTool({ type: "lasso" })} + icon={LassoIcon} + data-testid="toolbar-lasso" + selected={lassoToolSelected} + > + {t("toolBar.lasso")} +
Generate
diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index c66fbf902..88fbdfa1f 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -554,6 +554,7 @@ let IS_PLAIN_PASTE_TIMER = 0; let PLAIN_PASTE_TOAST_SHOWN = false; let lastPointerUp: (() => void) | null = null; +let selectionSwitch = false; const gesture: Gesture = { pointers: new Map(), lastCenter: null, @@ -4534,14 +4535,6 @@ class App extends React.Component { return; } - if (event.key === KEYS[1] && !event.altKey && !event[KEYS.CTRL_OR_CMD]) { - if (this.state.activeTool.type === "selection") { - this.setActiveTool({ type: "lasso" }); - } else { - this.setActiveTool({ type: "selection" }); - } - } - if ( event[KEYS.CTRL_OR_CMD] && (event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE) @@ -4572,7 +4565,10 @@ class App extends React.Component { this.state.openDialog?.name === "elementLinkSelector" ) { setCursor(this.interactiveCanvas, CURSOR_TYPE.GRAB); - } else if (this.state.activeTool.type === "selection") { + } else if ( + this.state.activeTool.type === "selection" || + this.state.activeTool.type === "lasso" + ) { resetCursor(this.interactiveCanvas); } else { setCursorForShape(this.interactiveCanvas, this.state); @@ -6607,18 +6603,10 @@ class App extends React.Component { this.state.activeTool.type !== "eraser" && this.state.activeTool.type !== "hand" ) { - if (this.state.activeTool.type === "selection" && event.altKey) { - this.setActiveTool({ type: "lasso" }); - this.lassoTrail.startPath( - pointerDownState.origin.x, - pointerDownState.origin.y, - ); - } else { - this.createGenericElementOnPointerDown( - this.state.activeTool.type, - pointerDownState, - ); - } + this.createGenericElementOnPointerDown( + this.state.activeTool.type, + pointerDownState, + ); } this.props?.onPointerDown?.(this.state.activeTool, pointerDownState); @@ -8522,9 +8510,28 @@ class App extends React.Component { if (this.state.selectionElement) { pointerDownState.lastCoords.x = pointerCoords.x; pointerDownState.lastCoords.y = pointerCoords.y; - this.maybeDragNewGenericElement(pointerDownState, event); + if (event.altKey) { + this.setActiveTool({ type: "lasso" }); + this.lassoTrail.startPath(pointerCoords.x, pointerCoords.y); + this.setAppState({ + selectionElement: null, + }); + selectionSwitch = true; + } else { + this.maybeDragNewGenericElement(pointerDownState, event); + } } else if (this.state.activeTool.type === "lasso") { - this.lassoTrail.addPointToPath(pointerCoords.x, pointerCoords.y); + if (!event.altKey && selectionSwitch) { + this.setActiveTool({ type: "selection" }); + this.createGenericElementOnPointerDown("selection", pointerDownState); + pointerDownState.lastCoords.x = pointerCoords.x; + pointerDownState.lastCoords.y = pointerCoords.y; + this.maybeDragNewGenericElement(pointerDownState, event); + this.lassoTrail.endPath(); + selectionSwitch = false; + } else { + this.lassoTrail.addPointToPath(pointerCoords.x, pointerCoords.y); + } } else { // It is very important to read this.state within each move event, // otherwise we would read a stale one! @@ -8781,6 +8788,7 @@ class App extends React.Component { // just in case, tool changes mid drag, always clean up this.lassoTrail.endPath(); + selectionSwitch = false; this.lastPointerMoveCoords = null; SnapCache.setReferenceSnapPoints(null); @@ -10450,7 +10458,7 @@ class App extends React.Component { width: distance(pointerDownState.origin.x, pointerCoords.x), height: distance(pointerDownState.origin.y, pointerCoords.y), shouldMaintainAspectRatio: shouldMaintainAspectRatio(event), - shouldResizeFromCenter: shouldResizeFromCenter(event), + shouldResizeFromCenter: false, zoom: this.state.zoom.value, informMutation, }); diff --git a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx index cc3c782c4..567916ed1 100644 --- a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx +++ b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx @@ -308,6 +308,7 @@ function CommandPaletteInner({ const toolCommands: CommandPaletteItem[] = [ actionManager.actions.toggleHandTool, actionManager.actions.setFrameAsActiveTool, + actionManager.actions.toggleLassoTool, ].map((action) => actionToCommand(action, DEFAULT_CATEGORIES.tools)); const editorCommands: CommandPaletteItem[] = [ diff --git a/packages/excalidraw/components/HintViewer.tsx b/packages/excalidraw/components/HintViewer.tsx index aa0e28d09..ef43a0591 100644 --- a/packages/excalidraw/components/HintViewer.tsx +++ b/packages/excalidraw/components/HintViewer.tsx @@ -123,7 +123,7 @@ const getHints = ({ } if (!selectedElements.length && !isMobile) { - return [t("hints.canvasPanning"), t("hints.lassoSelect")]; + return [t("hints.canvasPanning")]; } if (selectedElements.length === 1) { diff --git a/packages/excalidraw/lasso/index.ts b/packages/excalidraw/lasso/index.ts index 9e165a9c5..a64598891 100644 --- a/packages/excalidraw/lasso/index.ts +++ b/packages/excalidraw/lasso/index.ts @@ -42,6 +42,9 @@ export class LassoTrail extends AnimatedTrail { } startPath(x: number, y: number) { + // clear any existing trails just in case + this.endPath(); + super.startPath(x, y); this.intersectedElements.clear(); this.enclosedElements.clear(); diff --git a/packages/excalidraw/locales/en.json b/packages/excalidraw/locales/en.json index 14c70355c..1f166290d 100644 --- a/packages/excalidraw/locales/en.json +++ b/packages/excalidraw/locales/en.json @@ -342,7 +342,6 @@ "bindTextToElement": "Press enter to add text", "createFlowchart": "Hold CtrlOrCmd and Arrow key to create a flowchart", "deepBoxSelect": "Hold CtrlOrCmd to deep select, and to prevent dragging", - "lassoSelect": "Hold Alt, or click on the selection again, to lasso select", "eraserRevert": "Hold Alt to revert the elements marked for deletion", "firefox_clipboard_write": "This feature can likely be enabled by setting the \"dom.events.asyncClipboard.clipboardItem\" flag to \"true\". To change the browser flags in Firefox, visit the \"about:config\" page.", "disableSnapping": "Hold CtrlOrCmd to disable snapping", diff --git a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap index f77eb8ddb..3f79731ea 100644 --- a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap @@ -933,6 +933,7 @@ exports[`contextMenu element > right-clicking on a group should select whole gro "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -1142,6 +1143,7 @@ exports[`contextMenu element > selecting 'Add to library' in context menu adds e "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -1361,6 +1363,7 @@ exports[`contextMenu element > selecting 'Bring forward' in context menu brings "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -1695,6 +1698,7 @@ exports[`contextMenu element > selecting 'Bring to front' in context menu brings "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2029,6 +2033,7 @@ exports[`contextMenu element > selecting 'Copy styles' in context menu copies st "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2248,6 +2253,7 @@ exports[`contextMenu element > selecting 'Delete' in context menu deletes elemen "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2491,6 +2497,7 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2795,6 +2802,7 @@ exports[`contextMenu element > selecting 'Group selection' in context menu group "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -3167,6 +3175,7 @@ exports[`contextMenu element > selecting 'Paste styles' in context menu pastes s "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -3645,6 +3654,7 @@ exports[`contextMenu element > selecting 'Send backward' in context menu sends e "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -3971,6 +3981,7 @@ exports[`contextMenu element > selecting 'Send to back' in context menu sends el "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -4297,6 +4308,7 @@ exports[`contextMenu element > selecting 'Ungroup selection' in context menu ung "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -5577,6 +5589,7 @@ exports[`contextMenu element > shows 'Group selection' in context menu for multi "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -6798,6 +6811,7 @@ exports[`contextMenu element > shows 'Ungroup selection' in context menu for gro "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -7736,6 +7750,7 @@ exports[`contextMenu element > shows context menu for canvas > [end of test] app "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -8742,6 +8757,7 @@ exports[`contextMenu element > shows context menu for element > [end of test] ap "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -9730,6 +9746,7 @@ exports[`contextMenu element > shows context menu for element > [end of test] ap "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index d8cf4ec2d..ec5e37208 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -59,6 +59,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -658,6 +659,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -1165,6 +1167,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -1536,6 +1539,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -1908,6 +1912,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -2178,6 +2183,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -2617,6 +2623,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -2919,6 +2926,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -3206,6 +3214,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -3503,6 +3512,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -3792,6 +3802,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -4030,6 +4041,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -4292,6 +4304,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -4568,6 +4581,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -4802,6 +4816,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -5036,6 +5051,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -5268,6 +5284,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -5500,6 +5517,7 @@ exports[`history > multiplayer undo/redo > conflicts in frames and their childre "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -5762,6 +5780,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -6096,6 +6115,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -6524,6 +6544,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -6905,6 +6926,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -7227,6 +7249,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -7528,6 +7551,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -7760,6 +7784,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -8118,6 +8143,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -8476,6 +8502,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -8883,6 +8910,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -9173,6 +9201,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -9441,6 +9470,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -9708,6 +9738,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -9942,6 +9973,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -10246,6 +10278,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -10589,6 +10622,7 @@ exports[`history > multiplayer undo/redo > should redistribute deltas when eleme "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -10827,6 +10861,7 @@ exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end o "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -11279,6 +11314,7 @@ exports[`history > multiplayer undo/redo > should update history entries after r "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -11536,6 +11572,7 @@ exports[`history > singleplayer undo/redo > remounting undo/redo buttons should "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -11778,6 +11815,7 @@ exports[`history > singleplayer undo/redo > should clear the redo stack on eleme "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -12022,6 +12060,7 @@ exports[`history > singleplayer undo/redo > should create entry when selecting f "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -12426,6 +12465,7 @@ exports[`history > singleplayer undo/redo > should create new history entry on s "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -12676,6 +12716,7 @@ exports[`history > singleplayer undo/redo > should disable undo/redo buttons whe "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -12920,6 +12961,7 @@ exports[`history > singleplayer undo/redo > should end up with no history entry "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -13164,6 +13206,7 @@ exports[`history > singleplayer undo/redo > should iterate through the history w "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -13414,6 +13457,7 @@ exports[`history > singleplayer undo/redo > should not clear the redo stack on s "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -13749,6 +13793,7 @@ exports[`history > singleplayer undo/redo > should not collapse when applying co "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -13924,6 +13969,7 @@ exports[`history > singleplayer undo/redo > should not end up with history entry "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -14215,6 +14261,7 @@ exports[`history > singleplayer undo/redo > should not end up with history entry "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -14485,6 +14532,7 @@ exports[`history > singleplayer undo/redo > should not override appstate changes "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -14763,6 +14811,7 @@ exports[`history > singleplayer undo/redo > should support appstate name or view "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -14927,6 +14976,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -15622,6 +15672,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -16241,6 +16292,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -16860,6 +16912,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -17570,6 +17623,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -18317,6 +18371,7 @@ exports[`history > singleplayer undo/redo > should support changes in elements' "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -18794,6 +18849,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -19319,6 +19375,7 @@ exports[`history > singleplayer undo/redo > should support element creation, del "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, @@ -19778,6 +19835,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "newElement": null, diff --git a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap index 5d48ead6c..26eb30ca6 100644 --- a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap @@ -59,6 +59,7 @@ exports[`given element A and group of elements B and given both are selected whe "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -474,6 +475,7 @@ exports[`given element A and group of elements B and given both are selected whe "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -880,6 +882,7 @@ exports[`regression tests > Cmd/Ctrl-click exclusively select element under poin "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -1425,6 +1428,7 @@ exports[`regression tests > Drags selected element when hitting only bounding bo "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -1629,6 +1633,7 @@ exports[`regression tests > adjusts z order when grouping > [end of test] appSta "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2004,6 +2009,7 @@ exports[`regression tests > alt-drag duplicates an element > [end of test] appSt "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2244,6 +2250,7 @@ exports[`regression tests > arrow keys > [end of test] appState 1`] = ` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2424,6 +2431,7 @@ exports[`regression tests > can drag element that covers another element, while "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2744,6 +2752,7 @@ exports[`regression tests > change the properties of a shape > [end of test] app "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -2990,6 +2999,7 @@ exports[`regression tests > click on an element and drag it > [dragged] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -3233,6 +3243,7 @@ exports[`regression tests > click on an element and drag it > [end of test] appS "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -3463,6 +3474,7 @@ exports[`regression tests > click to select a shape > [end of test] appState 1`] "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -3719,6 +3731,7 @@ exports[`regression tests > click-drag to select a group > [end of test] appStat "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -4030,6 +4043,7 @@ exports[`regression tests > deleting last but one element in editing group shoul "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -4452,6 +4466,7 @@ exports[`regression tests > deselects group of selected elements on pointer down "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -4735,6 +4750,7 @@ exports[`regression tests > deselects group of selected elements on pointer up w "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -4988,6 +5004,7 @@ exports[`regression tests > deselects selected element on pointer down when poin "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -5198,6 +5215,7 @@ exports[`regression tests > deselects selected element, on pointer up, when clic "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -5397,6 +5415,7 @@ exports[`regression tests > double click to edit a group > [end of test] appStat "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -5779,6 +5798,7 @@ exports[`regression tests > drags selected elements from point inside common bou "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -6069,6 +6089,7 @@ exports[`regression tests > draw every type of shape > [end of test] appState 1` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -6877,6 +6898,7 @@ exports[`regression tests > given a group of selected elements with an element t "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -7207,6 +7229,7 @@ exports[`regression tests > given a selected element A and a not selected elemen "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -7483,6 +7506,7 @@ exports[`regression tests > given selected element A with lower z-index than uns "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -7717,6 +7741,7 @@ exports[`regression tests > given selected element A with lower z-index than uns "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -7954,6 +7979,7 @@ exports[`regression tests > key 2 selects rectangle tool > [end of test] appStat "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -8134,6 +8160,7 @@ exports[`regression tests > key 3 selects diamond tool > [end of test] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -8314,6 +8341,7 @@ exports[`regression tests > key 4 selects ellipse tool > [end of test] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -8494,6 +8522,7 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -8717,6 +8746,7 @@ exports[`regression tests > key 6 selects line tool > [end of test] appState 1`] "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -8939,6 +8969,7 @@ exports[`regression tests > key 7 selects freedraw tool > [end of test] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -9133,6 +9164,7 @@ exports[`regression tests > key a selects arrow tool > [end of test] appState 1` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -9356,6 +9388,7 @@ exports[`regression tests > key d selects diamond tool > [end of test] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -9536,6 +9569,7 @@ exports[`regression tests > key l selects line tool > [end of test] appState 1`] "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -9758,6 +9792,7 @@ exports[`regression tests > key o selects ellipse tool > [end of test] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -9938,6 +9973,7 @@ exports[`regression tests > key p selects freedraw tool > [end of test] appState "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -10132,6 +10168,7 @@ exports[`regression tests > key r selects rectangle tool > [end of test] appStat "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -10312,6 +10349,7 @@ exports[`regression tests > make a group and duplicate it > [end of test] appSta "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -10826,6 +10864,7 @@ exports[`regression tests > noop interaction after undo shouldn't create history "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -11103,6 +11142,7 @@ exports[`regression tests > pinch-to-zoom works > [end of test] appState 1`] = ` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "touch", "multiElement": null, "name": "Untitled-201933152653", @@ -11229,6 +11269,7 @@ exports[`regression tests > shift click on selected element should deselect it o "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -11428,6 +11469,7 @@ exports[`regression tests > shift-click to multiselect, then drag > [end of test "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -11739,6 +11781,7 @@ exports[`regression tests > should group elements and ungroup them > [end of tes "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -12151,6 +12194,7 @@ exports[`regression tests > single-clicking on a subgroup of a selected group sh "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -12764,6 +12808,7 @@ exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] a "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -12893,6 +12938,7 @@ exports[`regression tests > supports nested groups > [end of test] appState 1`] "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -13477,6 +13523,7 @@ exports[`regression tests > switches from group of selected elements to another "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -13815,6 +13862,7 @@ exports[`regression tests > switches selected element on pointer down > [end of "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -14080,6 +14128,7 @@ exports[`regression tests > two-finger scroll works > [end of test] appState 1`] "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "touch", "multiElement": null, "name": "Untitled-201933152653", @@ -14206,6 +14255,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] appStat "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -14585,6 +14635,7 @@ exports[`regression tests > updates fontSize & fontFamily appState > [end of tes "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", @@ -14711,6 +14762,7 @@ exports[`regression tests > zoom hotkeys > [end of test] appState 1`] = ` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "Untitled-201933152653", diff --git a/packages/utils/__snapshots__/export.test.ts.snap b/packages/utils/__snapshots__/export.test.ts.snap index 54d4af4bc..19e1608f6 100644 --- a/packages/utils/__snapshots__/export.test.ts.snap +++ b/packages/utils/__snapshots__/export.test.ts.snap @@ -59,6 +59,7 @@ exports[`exportToSvg > with default arguments 1`] = ` "isLoading": false, "isResizing": false, "isRotating": false, + "lassoSelection": null, "lastPointerDownWith": "mouse", "multiElement": null, "name": "name",