diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts index c3c348cebc..c797c6e8c2 100644 --- a/packages/common/src/constants.ts +++ b/packages/common/src/constants.ts @@ -36,6 +36,7 @@ export const APP_NAME = "Excalidraw"; // (happens a lot with fast clicks with the text tool) export const TEXT_AUTOWRAP_THRESHOLD = 36; // px export const DRAGGING_THRESHOLD = 10; // px +export const MINIMUM_ARROW_SIZE = 20; // px export const LINE_CONFIRM_THRESHOLD = 8; // px export const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5; export const ELEMENT_TRANSLATE_AMOUNT = 1; diff --git a/packages/element/src/renderElement.ts b/packages/element/src/renderElement.ts index e870d977fb..008d6afc4a 100644 --- a/packages/element/src/renderElement.ts +++ b/packages/element/src/renderElement.ts @@ -106,6 +106,11 @@ const getCanvasPadding = (element: ExcalidrawElement) => { return element.strokeWidth * 12; case "text": return element.fontSize / 2; + case "arrow": + if (element.endArrowhead || element.endArrowhead) { + return 40; + } + return 20; default: return 20; } diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index 7a4511e051..b699e9ea64 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -154,11 +154,7 @@ export const actionFinalize = register({ if (element) { // pen and mouse have hover - if ( - appState.multiElement && - element.type !== "freedraw" && - appState.lastPointerDownWith !== "touch" - ) { + if (appState.multiElement && element.type !== "freedraw") { const { points, lastCommittedPoint } = element; if ( !lastCommittedPoint || diff --git a/packages/excalidraw/components/Actions.tsx b/packages/excalidraw/components/Actions.tsx index 919e9c688d..1b42e9f402 100644 --- a/packages/excalidraw/components/Actions.tsx +++ b/packages/excalidraw/components/Actions.tsx @@ -505,15 +505,3 @@ export const ExitZenModeAction = ({ {t("buttons.exitZenMode")} ); - -export const FinalizeAction = ({ - renderAction, - className, -}: { - renderAction: ActionManager["renderAction"]; - className?: string; -}) => ( -
- {renderAction("finalize", { size: "small" })} -
-); diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 1397a8b7c2..dcb9f9838f 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -100,6 +100,7 @@ import { randomInteger, CLASSES, Emitter, + MINIMUM_ARROW_SIZE, } from "@excalidraw/common"; import { @@ -8162,7 +8163,9 @@ class App extends React.Component { pointDistance( pointFrom(pointerCoords.x, pointerCoords.y), pointFrom(pointerDownState.origin.x, pointerDownState.origin.y), - ) < DRAGGING_THRESHOLD + ) * + this.state.zoom.value < + MINIMUM_ARROW_SIZE ) { return; } @@ -9113,25 +9116,54 @@ class App extends React.Component { this.state, ); - if (!pointerDownState.drag.hasOccurred && newElement && !multiElement) { - this.scene.mutateElement( - newElement, - { - points: [ - ...newElement.points, - pointFrom( - pointerCoords.x - newElement.x, - pointerCoords.y - newElement.y, - ), - ], - }, - { informMutation: false, isDragging: false }, - ); + const dragDistance = + pointDistance( + pointFrom(pointerCoords.x, pointerCoords.y), + pointFrom(pointerDownState.origin.x, pointerDownState.origin.y), + ) * this.state.zoom.value; - this.setState({ - multiElement: newElement, - newElement, - }); + if ( + (!pointerDownState.drag.hasOccurred || + dragDistance < MINIMUM_ARROW_SIZE) && + newElement && + !multiElement + ) { + if (this.device.isTouchScreen) { + const FIXED_DELTA_X = Math.min( + (this.state.width * 0.7) / this.state.zoom.value, + 100, + ); + + this.scene.mutateElement( + newElement, + { + x: newElement.x - FIXED_DELTA_X / 2, + points: [ + pointFrom(0, 0), + pointFrom(FIXED_DELTA_X, 0), + ], + }, + { informMutation: false, isDragging: false }, + ); + + this.actionManager.executeAction(actionFinalize); + } else { + const dx = pointerCoords.x - newElement.x; + const dy = pointerCoords.y - newElement.y; + + this.scene.mutateElement( + newElement, + { + points: [...newElement.points, pointFrom(dx, dy)], + }, + { informMutation: false, isDragging: false }, + ); + + this.setState({ + multiElement: newElement, + newElement, + }); + } } else if (pointerDownState.drag.hasOccurred && !multiElement) { if ( isBindingEnabled(this.state) && diff --git a/packages/excalidraw/components/footer/Footer.tsx b/packages/excalidraw/components/footer/Footer.tsx index 427628e7c9..3b213d796a 100644 --- a/packages/excalidraw/components/footer/Footer.tsx +++ b/packages/excalidraw/components/footer/Footer.tsx @@ -2,13 +2,7 @@ import clsx from "clsx"; import { actionShortcuts } from "../../actions"; import { useTunnels } from "../../context/tunnels"; -import { - ExitZenModeAction, - FinalizeAction, - UndoRedoActions, - ZoomActions, -} from "../Actions"; -import { useDevice } from "../App"; +import { ExitZenModeAction, UndoRedoActions, ZoomActions } from "../Actions"; import { HelpButton } from "../HelpButton"; import { Section } from "../Section"; import Stack from "../Stack"; @@ -29,10 +23,6 @@ const Footer = ({ }) => { const { FooterCenterTunnel, WelcomeScreenHelpHintTunnel } = useTunnels(); - const device = useDevice(); - const showFinalize = - !appState.viewModeEnabled && appState.multiElement && device.isTouchScreen; - return (