fix: Move a frame along with its children

This commit is contained in:
Hazem Krimi 2025-04-25 00:38:22 +01:00
parent 7343285694
commit 820a8540b1
3 changed files with 67 additions and 35 deletions

View file

@ -58,17 +58,13 @@ const MultiPosition = ({
}), }),
[atomicUnits, elementsMap, property], [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"; const value = new Set(positions).size === 1 ? positions[0] : "Mixed";
return ( return (
<StatsDragInput <StatsDragInput
label={property === "x" ? "X" : "Y"} label={property === "x" ? "X" : "Y"}
elements={elementsWithFramesChildren} elements={elements}
dragInputCallback={handlePositionChange} dragInputCallback={handlePositionChange}
value={value} value={value}
property={property} property={property}

View file

@ -35,8 +35,6 @@ const Position = ({
pointFrom(element.x + element.width / 2, element.y + element.height / 2), pointFrom(element.x + element.width / 2, element.y + element.height / 2),
element.angle, element.angle,
); );
const children = isFrameLikeElement(element) ? getFrameChildren(elementsMap, element.id) : [];
const elements = children.length > 0 ? [element, ...children] : [element];
let value = round(property === "x" ? topLeftX : topLeftY, 2); let value = round(property === "x" ? topLeftX : topLeftY, 2);
if ( if (
@ -57,7 +55,7 @@ const Position = ({
return ( return (
<StatsDragInput <StatsDragInput
label={property === "x" ? "X" : "Y"} label={property === "x" ? "X" : "Y"}
elements={elements} elements={[element]}
dragInputCallback={handlePositionChange} dragInputCallback={handlePositionChange}
scene={scene} scene={scene}
value={value} value={value}

View file

@ -30,6 +30,7 @@ import type {
import type Scene from "@excalidraw/element/Scene"; import type Scene from "@excalidraw/element/Scene";
import type { AppState } from "../../types"; import type { AppState } from "../../types";
import { getFrameChildren } from "@excalidraw/element/frame";
export type StatsInputProperty = export type StatsInputProperty =
| "x" | "x"
@ -191,6 +192,60 @@ export const moveElement = (
{ informMutation: shouldInformMutation, isDragging: false }, { informMutation: shouldInformMutation, isDragging: false },
); );
} }
if (isFrameLikeElement(originalElement)) {
getFrameChildren(originalElementsMap, originalElement.id).forEach(child => {
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 = ( export const moveElements = (
@ -371,22 +426,6 @@ export const handlePositionChange: DragInputCallbackType<
origElement.angle, origElement.angle,
); );
if (isFrameChildElement(origElement)) {
const childNewTopLeftX = property === "x" ? nextValue + Math.abs(topLeftX) : topLeftX;
const childNewTopLeftY = property === "y" ? nextValue + Math.abs(topLeftY) : topLeftY;
moveElement(
childNewTopLeftX,
childNewTopLeftY,
origElement,
scene,
originalElementsMap,
false,
);
scene.triggerUpdate();
return;
} else {
const newTopLeftX = property === "x" ? nextValue : topLeftX; const newTopLeftX = property === "x" ? nextValue : topLeftX;
const newTopLeftY = property === "y" ? nextValue : topLeftY; const newTopLeftY = property === "y" ? nextValue : topLeftY;
@ -401,7 +440,6 @@ export const handlePositionChange: DragInputCallbackType<
} }
} }
} }
}
scene.triggerUpdate(); scene.triggerUpdate();
return; return;