From 5fabc57277e38997aef8005100fca3ea585792c6 Mon Sep 17 00:00:00 2001 From: connorhanafee Date: Fri, 9 Jul 2021 18:00:13 -0400 Subject: [PATCH] fix: view mode cursor adjustments (#3809) --- src/components/App.tsx | 14 +++++++-- src/constants.ts | 1 + src/tests/viewMode.test.tsx | 58 +++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 src/tests/viewMode.test.tsx diff --git a/src/components/App.tsx b/src/components/App.tsx index 8f0b2688..b188aa95 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -343,7 +343,7 @@ class App extends React.Component { style={{ width: canvasDOMWidth, height: canvasDOMHeight, - cursor: "grabbing", + cursor: CURSOR_TYPE.GRAB, }} width={canvasWidth} height={canvasHeight} @@ -1610,7 +1610,9 @@ class App extends React.Component { private onKeyUp = withBatchedUpdates((event: KeyboardEvent) => { if (event.key === KEYS.SPACE) { - if (this.state.elementType === "selection") { + if (this.state.viewModeEnabled) { + setCursor(this.canvas, CURSOR_TYPE.GRAB); + } else if (this.state.elementType === "selection") { resetCursor(this.canvas); } else { setCursorForShape(this.canvas, this.state.elementType); @@ -2235,6 +2237,8 @@ class App extends React.Component { this.canvas, isTextElement(hitElement) ? CURSOR_TYPE.TEXT : CURSOR_TYPE.CROSSHAIR, ); + } else if (this.state.viewModeEnabled) { + setCursor(this.canvas, CURSOR_TYPE.GRAB); } else if (isOverScrollBar) { setCursor(this.canvas, CURSOR_TYPE.AUTO); } else if ( @@ -2472,7 +2476,11 @@ class App extends React.Component { lastPointerUp = null; isPanning = false; if (!isHoldingSpace) { - setCursorForShape(this.canvas, this.state.elementType); + if (this.state.viewModeEnabled) { + setCursor(this.canvas, CURSOR_TYPE.GRAB); + } else { + setCursorForShape(this.canvas, this.state.elementType); + } } this.setState({ cursorButton: "up", diff --git a/src/constants.ts b/src/constants.ts index 89582a55..46c2548f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -14,6 +14,7 @@ export const CURSOR_TYPE = { TEXT: "text", CROSSHAIR: "crosshair", GRABBING: "grabbing", + GRAB: "grab", POINTER: "pointer", MOVE: "move", AUTO: "", diff --git a/src/tests/viewMode.test.tsx b/src/tests/viewMode.test.tsx new file mode 100644 index 00000000..18dfe29e --- /dev/null +++ b/src/tests/viewMode.test.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { render, GlobalTestState } from "./test-utils"; +import ExcalidrawApp from "../excalidraw-app"; +import { KEYS } from "../keys"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; +import { CURSOR_TYPE } from "../constants"; + +const { h } = window; +const mouse = new Pointer("mouse"); +const touch = new Pointer("touch"); +const pen = new Pointer("pen"); +const pointerTypes = [mouse, touch, pen]; + +describe("view mode", () => { + beforeEach(async () => { + await render(); + }); + + it("after switching to view mode – cursor type should be pointer", async () => { + h.setState({ viewModeEnabled: true }); + expect(GlobalTestState.canvas.style.cursor).toBe(CURSOR_TYPE.GRAB); + }); + + it("after switching to view mode, moving, clicking, and pressing space key – cursor type should be pointer", async () => { + h.setState({ viewModeEnabled: true }); + + pointerTypes.forEach((pointerType) => { + const pointer = pointerType; + pointer.reset(); + pointer.move(100, 100); + pointer.click(); + Keyboard.keyPress(KEYS.SPACE); + expect(GlobalTestState.canvas.style.cursor).toBe(CURSOR_TYPE.GRAB); + }); + }); + + it("cursor should stay as grabbing type when hovering over canvas elements", async () => { + // create a rectangle, then hover over it – cursor should be + // move type for mouse and grab for touch & pen + // then switch to view-mode and cursor should be grabbing type + UI.createElement("rectangle", { size: 100 }); + + pointerTypes.forEach((pointerType) => { + const pointer = pointerType; + + pointer.moveTo(50, 50); + // eslint-disable-next-line dot-notation + if (pointerType["pointerType"] === "mouse") { + expect(GlobalTestState.canvas.style.cursor).toBe(CURSOR_TYPE.MOVE); + } else { + expect(GlobalTestState.canvas.style.cursor).toBe(CURSOR_TYPE.GRAB); + } + + h.setState({ viewModeEnabled: true }); + expect(GlobalTestState.canvas.style.cursor).toBe(CURSOR_TYPE.GRAB); + }); + }); +});