mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: do not delete frame children on frame delete (#9011)
This commit is contained in:
parent
46f42ef8d7
commit
ae6bee3403
3 changed files with 103 additions and 40 deletions
|
@ -7,7 +7,7 @@ import { getNonDeletedElements } from "../element";
|
||||||
import type { ExcalidrawElement } from "../element/types";
|
import type { ExcalidrawElement } from "../element/types";
|
||||||
import type { AppClassProperties, AppState } from "../types";
|
import type { AppClassProperties, AppState } from "../types";
|
||||||
import { mutateElement, newElementWith } from "../element/mutateElement";
|
import { mutateElement, newElementWith } from "../element/mutateElement";
|
||||||
import { getElementsInGroup } from "../groups";
|
import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups";
|
||||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||||
import { fixBindingsAfterDeletion } from "../element/binding";
|
import { fixBindingsAfterDeletion } from "../element/binding";
|
||||||
import {
|
import {
|
||||||
|
@ -33,14 +33,15 @@ const deleteSelectedElements = (
|
||||||
).map((el) => el.id),
|
).map((el) => el.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
const selectedElementIds: Record<ExcalidrawElement["id"], true> = {};
|
||||||
elements: elements.map((el) => {
|
|
||||||
|
let shouldSelectEditingGroup = true;
|
||||||
|
|
||||||
|
const nextElements = elements.map((el) => {
|
||||||
if (appState.selectedElementIds[el.id]) {
|
if (appState.selectedElementIds[el.id]) {
|
||||||
if (el.boundElements) {
|
if (el.boundElements) {
|
||||||
el.boundElements.forEach((candidate) => {
|
el.boundElements.forEach((candidate) => {
|
||||||
const bound = app.scene
|
const bound = app.scene.getNonDeletedElementsMap().get(candidate.id);
|
||||||
.getNonDeletedElementsMap()
|
|
||||||
.get(candidate.id);
|
|
||||||
if (bound && isElbowArrow(bound)) {
|
if (bound && isElbowArrow(bound)) {
|
||||||
mutateElement(bound, {
|
mutateElement(bound, {
|
||||||
startBinding:
|
startBinding:
|
||||||
|
@ -48,9 +49,7 @@ const deleteSelectedElements = (
|
||||||
? null
|
? null
|
||||||
: bound.startBinding,
|
: bound.startBinding,
|
||||||
endBinding:
|
endBinding:
|
||||||
el.id === bound.endBinding?.elementId
|
el.id === bound.endBinding?.elementId ? null : bound.endBinding,
|
||||||
? null
|
|
||||||
: bound.endBinding,
|
|
||||||
});
|
});
|
||||||
mutateElbowArrow(bound, elementsMap, bound.points);
|
mutateElbowArrow(bound, elementsMap, bound.points);
|
||||||
}
|
}
|
||||||
|
@ -59,22 +58,74 @@ const deleteSelectedElements = (
|
||||||
return newElementWith(el, { isDeleted: true });
|
return newElementWith(el, { isDeleted: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if deleting a frame, remove the children from it and select them
|
||||||
if (el.frameId && framesToBeDeleted.has(el.frameId)) {
|
if (el.frameId && framesToBeDeleted.has(el.frameId)) {
|
||||||
return newElementWith(el, { isDeleted: true });
|
shouldSelectEditingGroup = false;
|
||||||
|
selectedElementIds[el.id] = true;
|
||||||
|
return newElementWith(el, { frameId: null });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (isBoundToContainer(el) && appState.selectedElementIds[el.containerId]) {
|
||||||
isBoundToContainer(el) &&
|
|
||||||
appState.selectedElementIds[el.containerId]
|
|
||||||
) {
|
|
||||||
return newElementWith(el, { isDeleted: true });
|
return newElementWith(el, { isDeleted: true });
|
||||||
}
|
}
|
||||||
return el;
|
return el;
|
||||||
}),
|
});
|
||||||
|
|
||||||
|
let nextEditingGroupId = appState.editingGroupId;
|
||||||
|
|
||||||
|
// select next eligible element in currently editing group or supergroup
|
||||||
|
if (shouldSelectEditingGroup && appState.editingGroupId) {
|
||||||
|
const elems = getElementsInGroup(
|
||||||
|
nextElements,
|
||||||
|
appState.editingGroupId,
|
||||||
|
).filter((el) => !el.isDeleted);
|
||||||
|
if (elems.length > 1) {
|
||||||
|
if (elems[0]) {
|
||||||
|
selectedElementIds[elems[0].id] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextEditingGroupId = null;
|
||||||
|
if (elems[0]) {
|
||||||
|
selectedElementIds[elems[0].id] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastElementInGroup = elems[0];
|
||||||
|
if (lastElementInGroup) {
|
||||||
|
const editingGroupIdx = lastElementInGroup.groupIds.findIndex(
|
||||||
|
(groupId) => {
|
||||||
|
return groupId === appState.editingGroupId;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const superGroupId = lastElementInGroup.groupIds[editingGroupIdx + 1];
|
||||||
|
if (superGroupId) {
|
||||||
|
const elems = getElementsInGroup(nextElements, superGroupId).filter(
|
||||||
|
(el) => !el.isDeleted,
|
||||||
|
);
|
||||||
|
if (elems.length > 1) {
|
||||||
|
nextEditingGroupId = superGroupId;
|
||||||
|
|
||||||
|
elems.forEach((el) => {
|
||||||
|
selectedElementIds[el.id] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
elements: nextElements,
|
||||||
appState: {
|
appState: {
|
||||||
...appState,
|
...appState,
|
||||||
selectedElementIds: {},
|
...selectGroupsForSelectedElements(
|
||||||
selectedGroupIds: {},
|
{
|
||||||
|
selectedElementIds,
|
||||||
|
editingGroupId: nextEditingGroupId,
|
||||||
|
},
|
||||||
|
nextElements,
|
||||||
|
appState,
|
||||||
|
null,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -105,6 +105,10 @@ export const selectGroupsForSelectedElements = (function () {
|
||||||
const groupElementsIndex: Record<GroupId, string[]> = {};
|
const groupElementsIndex: Record<GroupId, string[]> = {};
|
||||||
const selectedElementIdsInGroups = elements.reduce(
|
const selectedElementIdsInGroups = elements.reduce(
|
||||||
(acc: Record<string, true>, element) => {
|
(acc: Record<string, true>, element) => {
|
||||||
|
if (element.isDeleted) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
const groupId = element.groupIds.find((id) => selectedGroupIds[id]);
|
const groupId = element.groupIds.find((id) => selectedGroupIds[id]);
|
||||||
|
|
||||||
if (groupId) {
|
if (groupId) {
|
||||||
|
|
|
@ -4307,14 +4307,20 @@ History {
|
||||||
"appStateChange": AppStateChange {
|
"appStateChange": AppStateChange {
|
||||||
"delta": Delta {
|
"delta": Delta {
|
||||||
"deleted": {
|
"deleted": {
|
||||||
|
"editingGroupId": null,
|
||||||
"selectedElementIds": {
|
"selectedElementIds": {
|
||||||
"id1": true,
|
"id1": true,
|
||||||
},
|
},
|
||||||
|
"selectedGroupIds": {
|
||||||
|
"id4": false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"inserted": {
|
"inserted": {
|
||||||
|
"editingGroupId": "id4",
|
||||||
"selectedElementIds": {
|
"selectedElementIds": {
|
||||||
"id0": true,
|
"id0": true,
|
||||||
},
|
},
|
||||||
|
"selectedGroupIds": {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -4337,14 +4343,16 @@ History {
|
||||||
"appStateChange": AppStateChange {
|
"appStateChange": AppStateChange {
|
||||||
"delta": Delta {
|
"delta": Delta {
|
||||||
"deleted": {
|
"deleted": {
|
||||||
"editingGroupId": null,
|
|
||||||
"selectedElementIds": {},
|
"selectedElementIds": {},
|
||||||
|
"selectedGroupIds": {},
|
||||||
},
|
},
|
||||||
"inserted": {
|
"inserted": {
|
||||||
"editingGroupId": "id4",
|
|
||||||
"selectedElementIds": {
|
"selectedElementIds": {
|
||||||
"id1": true,
|
"id1": true,
|
||||||
},
|
},
|
||||||
|
"selectedGroupIds": {
|
||||||
|
"id4": false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue