From 820a8540b1c62c313a5de700c516f3db2b2b2e7d Mon Sep 17 00:00:00 2001 From: Hazem Krimi Date: Fri, 25 Apr 2025 00:38:22 +0100 Subject: [PATCH] fix: Move a frame along with its children --- .../components/Stats/MultiPosition.tsx | 6 +- .../excalidraw/components/Stats/Position.tsx | 4 +- packages/excalidraw/components/Stats/utils.ts | 92 +++++++++++++------ 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/packages/excalidraw/components/Stats/MultiPosition.tsx b/packages/excalidraw/components/Stats/MultiPosition.tsx index 025d79058..10b6bd277 100644 --- a/packages/excalidraw/components/Stats/MultiPosition.tsx +++ b/packages/excalidraw/components/Stats/MultiPosition.tsx @@ -58,17 +58,13 @@ const MultiPosition = ({ }), [atomicUnits, elementsMap, property], ); - const elementsWithFramesChildren = elements.reduce((accumulator: ExcalidrawElement[], element: ExcalidrawElement) => { - if (!isFrameLikeElement(element)) return [...accumulator, element]; - return [...accumulator, element, ...getFrameChildren(elementsMap, element.id)]; - }, []); const value = new Set(positions).size === 1 ? positions[0] : "Mixed"; return ( 0 ? [element, ...children] : [element]; let value = round(property === "x" ? topLeftX : topLeftY, 2); if ( @@ -57,7 +55,7 @@ const Position = ({ return ( { + const latestChildElement = elementsMap.get(child.id); + + if (!latestChildElement) return; + + const [childCX, childCY] = [ + child.x + child.width / 2, + child.y + child.height / 2, + ]; + const [childTopLeftX, childTopLeftY] = pointRotateRads( + pointFrom(child.x, child.y), + pointFrom(childCX, childCY), + child.angle, + ); + + const childNewTopLeftX = Math.round(childTopLeftX + changeInX); + const childNewTopLeftY = Math.round(childTopLeftY + changeInY); + + const [childX, childY] = pointRotateRads( + pointFrom(childNewTopLeftX, childNewTopLeftY), + pointFrom(childCX + changeInX, childCY + changeInY), + -child.angle as Radians, + ); + + scene.mutateElement( + latestChildElement, + { + x: childX, + y: childY, + }, + { informMutation: shouldInformMutation, isDragging: false }, + ); + updateBindings(latestChildElement, scene); + + const boundTextElement = getBoundTextElement( + latestChildElement, + originalElementsMap, + ); + if (boundTextElement) { + const latestBoundTextElement = elementsMap.get(boundTextElement.id); + latestBoundTextElement && + scene.mutateElement( + latestBoundTextElement, + { + x: boundTextElement.x + changeInX, + y: boundTextElement.y + changeInY, + }, + { informMutation: shouldInformMutation, isDragging: false }, + ); + } + }) + } }; export const moveElements = ( @@ -371,34 +426,17 @@ export const handlePositionChange: DragInputCallbackType< origElement.angle, ); - if (isFrameChildElement(origElement)) { - const childNewTopLeftX = property === "x" ? nextValue + Math.abs(topLeftX) : topLeftX; - const childNewTopLeftY = property === "y" ? nextValue + Math.abs(topLeftY) : topLeftY; + const newTopLeftX = property === "x" ? nextValue : topLeftX; + const newTopLeftY = property === "y" ? nextValue : topLeftY; - moveElement( - childNewTopLeftX, - childNewTopLeftY, - origElement, - scene, - originalElementsMap, - false, - ); - - scene.triggerUpdate(); - return; - } else { - const newTopLeftX = property === "x" ? nextValue : topLeftX; - const newTopLeftY = property === "y" ? nextValue : topLeftY; - - moveElement( - newTopLeftX, - newTopLeftY, - origElement, - scene, - originalElementsMap, - false, - ); - } + moveElement( + newTopLeftX, + newTopLeftY, + origElement, + scene, + originalElementsMap, + false, + ); } } }