From 019ce4c52cc82fe654d7e92c2672843c8ff57c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Wed, 26 Nov 2025 12:00:33 +0100 Subject: [PATCH] fix: Corner jumping & hints (#10403) * fix: Corner jumping Signed-off-by: Mark Tolmacs * fix: Hints Signed-off-by: Mark Tolmacs * fix: No corner avoidance for simple arrows Signed-off-by: Mark Tolmacs * show alt/cmd hint when creating/moving arrow point any time --------- Signed-off-by: Mark Tolmacs Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- packages/element/src/binding.ts | 25 +++++++++++-------- packages/excalidraw/components/HintViewer.tsx | 16 ++++++++++-- packages/excalidraw/components/LayerUI.tsx | 10 ++------ packages/excalidraw/locales/en.json | 2 +- .../tests/__snapshots__/move.test.tsx.snap | 4 +-- packages/excalidraw/types.ts | 6 +---- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index 473b2ec7be..c3fcf2767b 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -1202,23 +1202,26 @@ export const bindPointToSnapToElementOutline = ( customIntersector?: LineSegment, ): GlobalPoint => { const elbowed = isElbowArrow(arrowElement); - const point = - customIntersector && !elbowed - ? customIntersector[0] - : LinearElementEditor.getPointAtIndexGlobalCoordinates( - arrowElement, - startOrEnd === "start" ? 0 : -1, - elementsMap, - ); + const point = LinearElementEditor.getPointAtIndexGlobalCoordinates( + arrowElement, + startOrEnd === "start" ? 0 : -1, + elementsMap, + ); if (arrowElement.points.length < 2) { // New arrow creation, so no snapping return point; } - const edgePoint = isRectanguloidElement(bindableElement) - ? avoidRectangularCorner(arrowElement, bindableElement, elementsMap, point) - : point; + const edgePoint = + isRectanguloidElement(bindableElement) && elbowed + ? avoidRectangularCorner( + arrowElement, + bindableElement, + elementsMap, + point, + ) + : point; const adjacentPoint = customIntersector && !elbowed ? customIntersector[1] diff --git a/packages/excalidraw/components/HintViewer.tsx b/packages/excalidraw/components/HintViewer.tsx index 1fd255c8fe..875ad4b73d 100644 --- a/packages/excalidraw/components/HintViewer.tsx +++ b/packages/excalidraw/components/HintViewer.tsx @@ -62,6 +62,20 @@ const getHints = ({ shortcut: getTaggedShortcutKey("Alt"), }); } + + const selectedElements = app.scene.getSelectedElements(appState); + + // creating or dragging arrow point + if ( + appState.selectedLinearElement?.isDragging && + selectedElements[0]?.type === "arrow" + ) { + return t("hints.arrowBindModifiers", { + shortcut_1: getTaggedShortcutKey("Ctrl"), + shortcut_2: getTaggedShortcutKey("Alt"), + }); + } + if (activeTool.type === "arrow" || activeTool.type === "line") { if (multiMode) { return t("hints.linearElementMulti", { @@ -89,8 +103,6 @@ const getHints = ({ return t("hints.embeddable"); } - const selectedElements = app.scene.getSelectedElements(appState); - if ( isResizing && lastPointerDownWith === "mouse" && diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index 457069e7d5..17dffdfd9d 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -646,14 +646,8 @@ const LayerUI = ({ }; const stripIrrelevantAppStateProps = (appState: AppState): UIAppState => { - const { - suggestedBinding, - startBoundElement, - cursorButton, - scrollX, - scrollY, - ...ret - } = appState; + const { startBoundElement, cursorButton, scrollX, scrollY, ...ret } = + appState; return ret; }; diff --git a/packages/excalidraw/locales/en.json b/packages/excalidraw/locales/en.json index d6fd2654bf..233dcfa7a6 100644 --- a/packages/excalidraw/locales/en.json +++ b/packages/excalidraw/locales/en.json @@ -341,7 +341,7 @@ "canvasPanning": "To move canvas, hold {{shortcut_1}} or {{shortcut_2}} while dragging, or use the hand tool", "linearElement": "Click to start multiple points, drag for single line", "arrowTool": "Click to start multiple points, drag for single line. Press {{shortcut}} again to change arrow type.", - "arrowBindModifiers": "Hold {{shortcut_1}} to bind inside, or {{shortcut_2}} to disable binding", + "arrowBindModifiers": "Hold {{shortcut_1}} to disable binding, or {{shortcut_2}} to bind at a fixed point", "freeDraw": "Click and drag, release when you're finished", "text": "Tip: you can also add text by double-clicking anywhere with the selection tool", "embeddable": "Click-drag to create a website embed", diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 8be177988e..fceb5f14a7 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -203,7 +203,7 @@ exports[`move element > rectangles with binding arrow 7`] = ` 0, ], [ - 79, + "79.00000", "124.16785", ], ], @@ -228,7 +228,7 @@ exports[`move element > rectangles with binding arrow 7`] = ` "updated": 1, "version": 12, "versionNonce": 2066753033, - "width": 79, + "width": "79.00000", "x": 111, "y": "6.14995", } diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index 66110700cb..ad7c46a6db 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -474,11 +474,7 @@ export type SearchMatch = { export type UIAppState = Omit< AppState, - | "suggestedBinding" - | "startBoundElement" - | "cursorButton" - | "scrollX" - | "scrollY" + "startBoundElement" | "cursorButton" | "scrollX" | "scrollY" >; export type NormalizedZoomValue = number & { _brand: "normalizedZoom" };