diff --git a/src/components/Actions.tsx b/src/components/Actions.tsx index 2bd78cb6..827989d5 100644 --- a/src/components/Actions.tsx +++ b/src/components/Actions.tsx @@ -6,8 +6,7 @@ import { hasBackground, hasStroke, hasText, getTargetElement } from "../scene"; import { t } from "../i18n"; import { SHAPES } from "../shapes"; import { ToolButton } from "./ToolButton"; -import { capitalizeString, getShortcutKey } from "../utils"; -import { CURSOR_TYPE } from "../constants"; +import { capitalizeString, getShortcutKey, setCursorForShape } from "../utils"; import Stack from "./Stack"; import useIsMobile from "../is-mobile"; @@ -115,8 +114,7 @@ export function ShapesSwitcher({ multiElement: null, selectedElementIds: {}, }); - document.documentElement.style.cursor = - value === "text" ? CURSOR_TYPE.TEXT : CURSOR_TYPE.CROSSHAIR; + setCursorForShape(value); setAppState({}); }} > diff --git a/src/components/App.tsx b/src/components/App.tsx index 3ffb6c80..36f77b84 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -67,6 +67,7 @@ import { resetCursor, viewportCoordsToSceneCoords, sceneCoordsToViewportCoords, + setCursorForShape, } from "../utils"; import { KEYS, isArrowKey } from "../keys"; @@ -146,15 +147,6 @@ const gesture: Gesture = { initialScale: null, }; -function setCursorForShape(shape: string) { - if (shape === "selection") { - resetCursor(); - } else { - document.documentElement.style.cursor = - shape === "text" ? CURSOR_TYPE.TEXT : CURSOR_TYPE.CROSSHAIR; - } -} - export class App extends React.Component { canvas: HTMLCanvasElement | null = null; rc: RoughCanvas | null = null; @@ -1110,10 +1102,7 @@ export class App extends React.Component { if (this.state.elementType === "selection") { resetCursor(); } else { - document.documentElement.style.cursor = - this.state.elementType === "text" - ? CURSOR_TYPE.TEXT - : CURSOR_TYPE.CROSSHAIR; + setCursorForShape(this.state.elementType); this.setState({ selectedElementIds: {} }); } isHoldingSpace = false; @@ -1483,7 +1472,11 @@ export class App extends React.Component { } const hasDeselectedButton = Boolean(event.buttons); - if (hasDeselectedButton || this.state.elementType !== "selection") { + if ( + hasDeselectedButton || + (this.state.elementType !== "selection" && + this.state.elementType !== "text") + ) { return; } @@ -1513,8 +1506,14 @@ export class App extends React.Component { y, this.state.zoom, ); - document.documentElement.style.cursor = - hitElement && !isOverScrollBar ? "move" : ""; + if (this.state.elementType === "text") { + document.documentElement.style.cursor = isTextElement(hitElement) + ? CURSOR_TYPE.TEXT + : CURSOR_TYPE.CROSSHAIR; + } else { + document.documentElement.style.cursor = + hitElement && !isOverScrollBar ? "move" : ""; + } }; private handleCanvasPointerDown = ( @@ -1790,48 +1789,26 @@ export class App extends React.Component { return; } - const snappedToCenterPosition = event.altKey - ? null - : this.getTextWysiwygSnappedToCenterPosition( - x, - y, - this.state, - this.canvas, - window.devicePixelRatio, - ); + const { x, y } = viewportCoordsToSceneCoords( + event, + this.state, + this.canvas, + window.devicePixelRatio, + ); - const element = newTextElement({ - x: snappedToCenterPosition?.elementCenterX ?? x, - y: snappedToCenterPosition?.elementCenterY ?? y, - strokeColor: this.state.currentItemStrokeColor, - backgroundColor: this.state.currentItemBackgroundColor, - fillStyle: this.state.currentItemFillStyle, - strokeWidth: this.state.currentItemStrokeWidth, - roughness: this.state.currentItemRoughness, - opacity: this.state.currentItemOpacity, - text: "", - font: this.state.currentItemFont, + this.startTextEditing({ + x: x, + y: y, + clientX: event.clientX, + clientY: event.clientY, + centerIfPossible: !event.altKey, }); - globalSceneState.replaceAllElements([ - ...globalSceneState.getAllElements(), - element, - ]); - - this.handleTextWysiwyg(element, { - x: snappedToCenterPosition?.wysiwygX ?? event.clientX, - y: snappedToCenterPosition?.wysiwygY ?? event.clientY, - }); resetCursor(); if (!this.state.elementLocked) { this.setState({ - editingElement: element, elementType: "selection", }); - } else { - this.setState({ - editingElement: element, - }); } return; } else if ( diff --git a/src/element/typeChecks.ts b/src/element/typeChecks.ts index 4be91297..3809849a 100644 --- a/src/element/typeChecks.ts +++ b/src/element/typeChecks.ts @@ -5,9 +5,9 @@ import { } from "./types"; export function isTextElement( - element: ExcalidrawElement, + element: ExcalidrawElement | null, ): element is ExcalidrawTextElement { - return element.type === "text"; + return element != null && element.type === "text"; } export function isLinearElement( diff --git a/src/utils.ts b/src/utils.ts index 965e30ec..eee06798 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,6 @@ import { FlooredNumber } from "./types"; import { getZoomOrigin } from "./scene"; +import { CURSOR_TYPE } from "./constants"; export const SVG_NS = "http://www.w3.org/2000/svg"; @@ -144,6 +145,14 @@ export function resetCursor() { document.documentElement.style.cursor = ""; } +export function setCursorForShape(shape: string) { + if (shape === "selection") { + resetCursor(); + } else { + document.documentElement.style.cursor = CURSOR_TYPE.CROSSHAIR; + } +} + export const isFullScreen = () => document.fullscreenElement?.nodeName === "HTML";