Поправил логику проверки удаления узлов

This commit is contained in:
NikitaKalitov
2026-07-20 13:49:44 +03:00
parent 179be1f63b
commit d823b3df47
+20 -11
View File
@@ -259,17 +259,25 @@ function DiagramCanvas({ initialValue, onChange }: DiagramEditorProps) {
setSelectedEdgeId(null);
}, []);
const onNodesChange = useCallback(
(changes: NodeChange[]) => {
const withChildren = new Set(nodes.filter((n) => n.parentId).map((n) => n.parentId!));
const filteredChanges = changes.filter((change) => {
if (change.type !== 'remove' || !withChildren.has(change.id)) return true;
// Runs before React Flow computes any removal changes at all (for both
// nodes and their connected edges), so blocking here — unlike filtering
// inside onNodesChange — stops the connected edges from being deleted too.
const onBeforeDelete = useCallback(
async ({ nodes: nodesToDelete }: { nodes: Node[]; edges: Edge[] }) => {
const hasContainerNode = nodesToDelete.some((node) => nodes.some((n) => n.parentId === node.id));
if (hasContainerNode) {
window.alert('Сначала удалите вложенные узлы — у этого узла есть под-процесс.');
return false;
});
}
return true;
},
[nodes],
);
const positionChanges = filteredChanges.filter((c) => c.type === 'position' && c.position);
let adjustedChanges = filteredChanges;
const onNodesChange = useCallback(
(changes: NodeChange[]) => {
const positionChanges = changes.filter((c) => c.type === 'position' && c.position);
let adjustedChanges = changes;
if (positionChanges.length === 1) {
const change = positionChanges[0];
const draggedNode = change.type === 'position' ? nodes.find((n) => n.id === change.id) : undefined;
@@ -286,7 +294,7 @@ function DiagramCanvas({ initialValue, onChange }: DiagramEditorProps) {
};
const snapped = computeSnapAndGuides(dragged, others);
setAlignmentGuides(change.dragging === false ? [] : snapped.guides);
adjustedChanges = filteredChanges.map((c) =>
adjustedChanges = changes.map((c) =>
c === change ? { ...c, position: { x: snapped.x, y: snapped.y } } : c,
);
}
@@ -294,7 +302,7 @@ function DiagramCanvas({ initialValue, onChange }: DiagramEditorProps) {
setAlignmentGuides([]);
}
const isHistoryWorthy = filteredChanges.some(
const isHistoryWorthy = changes.some(
(change) =>
change.type === 'remove' ||
(change.type === 'position' && change.dragging === false) ||
@@ -308,7 +316,7 @@ function DiagramCanvas({ initialValue, onChange }: DiagramEditorProps) {
// emitChange — filtering edges here too (redundantly with onEdgesChange)
// guarantees a removed node never leaves a dangling edge behind.
const removedIds = new Set(
filteredChanges.filter((change) => change.type === 'remove').map((change) => change.id),
changes.filter((change) => change.type === 'remove').map((change) => change.id),
);
const nextEdges = removedIds.size
? edges.filter((edge) => !removedIds.has(edge.source) && !removedIds.has(edge.target))
@@ -574,6 +582,7 @@ function DiagramCanvas({ initialValue, onChange }: DiagramEditorProps) {
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onReconnect={onReconnect}
onBeforeDelete={onBeforeDelete}
edgesReconnectable={mode === 'edit'}
onNodeClick={onNodeClick}
onEdgeClick={onEdgeClick}