From 99d8bff1751b0bcfaacd1b0f32689df63ab42f86 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:05:42 +0100 Subject: [PATCH] fix: elements offset incorrectly when action-duplicated during drag (#9275) * fix: elements offset incorrectly when action-duplicated during drag * prevent duplicate action during drag altogether --- .../actions/actionDuplicateSelection.tsx | 4 ++++ packages/excalidraw/element/dragElements.ts | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index ce225a1d6..0125f0288 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -52,6 +52,10 @@ export const actionDuplicateSelection = register({ icon: DuplicateIcon, trackEvent: { category: "element" }, perform: (elements, appState, formData, app) => { + if (appState.selectedElementsAreBeingDragged) { + return false; + } + // duplicate selected point(s) if editing a line if (appState.editingLinearElement) { // TODO: Invariants should be checked here instead of duplicateSelectedPoints() diff --git a/packages/excalidraw/element/dragElements.ts b/packages/excalidraw/element/dragElements.ts index 4cc408b21..e3a6a48b3 100644 --- a/packages/excalidraw/element/dragElements.ts +++ b/packages/excalidraw/element/dragElements.ts @@ -17,7 +17,7 @@ import { } from "./typeChecks"; import type { Bounds } from "./bounds"; -import type { NonDeletedExcalidrawElement } from "./types"; +import type { ExcalidrawElement, NonDeletedExcalidrawElement } from "./types"; import type Scene from "../scene/Scene"; import type { AppState, @@ -78,13 +78,20 @@ export const dragSelectedElements = ( } } - const commonBounds = getCommonBounds( - Array.from(elementsToUpdate).map( - (el) => pointerDownState.originalElements.get(el.id) ?? el, - ), - ); + const origElements: ExcalidrawElement[] = []; + + for (const element of elementsToUpdate) { + const origElement = pointerDownState.originalElements.get(element.id); + // if original element is not set (e.g. when you duplicate during a drag + // operation), exit to avoid undefined behavior + if (!origElement) { + return; + } + origElements.push(origElement); + } + const adjustedOffset = calculateOffset( - commonBounds, + getCommonBounds(origElements), offset, snapOffset, gridSize,