Merge branch 'master' into mrazator/scene-static-methods-removal

This commit is contained in:
Marcel Mraz 2025-04-23 13:16:53 +02:00
commit d438cdf83a
No known key found for this signature in database
GPG key ID: 4EBD6E62DC830CD2
29 changed files with 741 additions and 644 deletions

View file

@ -7,26 +7,17 @@ import {
import { getNonDeletedElements } from "@excalidraw/element";
import {
isBoundToContainer,
isLinearElement,
} from "@excalidraw/element/typeChecks";
import { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
import { selectGroupsForSelectedElements } from "@excalidraw/element/groups";
import {
excludeElementsInFramesFromSelection,
getSelectedElements,
getSelectionStateForElements,
} from "@excalidraw/element/selection";
import { syncMovedIndices } from "@excalidraw/element/fractionalIndex";
import { duplicateElements } from "@excalidraw/element/duplicate";
import type { ElementsMap, ExcalidrawElement } from "@excalidraw/element/types";
import { ToolButton } from "../components/ToolButton";
import { DuplicateIcon } from "../components/icons";
@ -65,57 +56,49 @@ export const actionDuplicateSelection = register({
}
}
let { newElements: duplicatedElements, elementsWithClones: nextElements } =
duplicateElements({
type: "in-place",
elements,
idsOfElementsToDuplicate: arrayToMap(
getSelectedElements(elements, appState, {
includeBoundTextElement: true,
includeElementsInFrames: true,
}),
),
appState,
randomizeSeed: true,
overrides: (element) => ({
x: element.x + DEFAULT_GRID_SIZE / 2,
y: element.y + DEFAULT_GRID_SIZE / 2,
let { duplicatedElements, elementsWithDuplicates } = duplicateElements({
type: "in-place",
elements,
idsOfElementsToDuplicate: arrayToMap(
getSelectedElements(elements, appState, {
includeBoundTextElement: true,
includeElementsInFrames: true,
}),
reverseOrder: false,
});
),
appState,
randomizeSeed: true,
overrides: ({ origElement, origIdToDuplicateId }) => {
const duplicateFrameId =
origElement.frameId && origIdToDuplicateId.get(origElement.frameId);
return {
x: origElement.x + DEFAULT_GRID_SIZE / 2,
y: origElement.y + DEFAULT_GRID_SIZE / 2,
frameId: duplicateFrameId ?? origElement.frameId,
};
},
});
if (app.props.onDuplicate && nextElements) {
const mappedElements = app.props.onDuplicate(nextElements, elements);
if (app.props.onDuplicate && elementsWithDuplicates) {
const mappedElements = app.props.onDuplicate(
elementsWithDuplicates,
elements,
);
if (mappedElements) {
nextElements = mappedElements;
elementsWithDuplicates = mappedElements;
}
}
syncMovedIndices(nextElements, arrayToMap(duplicatedElements));
return {
elements: nextElements,
elements: syncMovedIndices(
elementsWithDuplicates,
arrayToMap(duplicatedElements),
),
appState: {
...appState,
...updateLinearElementEditors(
...getSelectionStateForElements(
duplicatedElements,
arrayToMap(nextElements),
),
...selectGroupsForSelectedElements(
{
editingGroupId: appState.editingGroupId,
selectedElementIds: excludeElementsInFramesFromSelection(
duplicatedElements,
).reduce((acc: Record<ExcalidrawElement["id"], true>, element) => {
if (!isBoundToContainer(element)) {
acc[element.id] = true;
}
return acc;
}, {}),
},
getNonDeletedElements(nextElements),
getNonDeletedElements(elementsWithDuplicates),
appState,
null,
),
},
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
@ -135,27 +118,3 @@ export const actionDuplicateSelection = register({
/>
),
});
const updateLinearElementEditors = (
clonedElements: ExcalidrawElement[],
elementsMap: ElementsMap,
) => {
const linears = clonedElements.filter(isLinearElement);
if (linears.length === 1) {
const linear = linears[0];
const boundElements = linear.boundElements?.map((def) => def.id) ?? [];
const onlySingleLinearSelected = clonedElements.every(
(el) => el.id === linear.id || boundElements.includes(el.id),
);
if (onlySingleLinearSelected) {
return {
selectedLinearElement: new LinearElementEditor(linear, elementsMap),
};
}
}
return {
selectedLinearElement: null,
};
};