Make internal nodes immutable

This commit is contained in:
peterkogo
2025-01-21 15:45:08 +01:00
parent 7b3d9eae5b
commit 7cb9a8686d
+60 -45
View File
@@ -87,6 +87,7 @@ export function adoptUserNodes<NodeType extends NodeBase>(
options?: UpdateNodesOptions<NodeType> options?: UpdateNodesOptions<NodeType>
) { ) {
const _options = mergeObjects(adoptUserNodesDefaultOptions, options); const _options = mergeObjects(adoptUserNodesDefaultOptions, options);
const tmpLookup = new Map(nodeLookup); const tmpLookup = new Map(nodeLookup);
const selectedNodeZ: number = _options?.elevateNodesOnSelect ? 1000 : 0; const selectedNodeZ: number = _options?.elevateNodesOnSelect ? 1000 : 0;
@@ -173,11 +174,15 @@ function updateChildNode<NodeType extends NodeBase>(
const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y; const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
if (positionChanged || z !== node.internals.z) { if (positionChanged || z !== node.internals.z) {
node.internals = { // we create a new object to mark the node as updated
...node.internals, nodeLookup.set(node.id, {
positionAbsolute: positionChanged ? { x, y } : positionAbsolute, ...node,
z, internals: {
}; ...node.internals,
positionAbsolute: positionChanged ? { x, y } : positionAbsolute,
z,
},
});
} }
} }
@@ -333,60 +338,70 @@ export function updateNodeInternals<NodeType extends InternalNodeBase>(
} }
if (node.hidden) { if (node.hidden) {
node.internals = { nodeLookup.set(node.id, {
...node.internals, ...node,
handleBounds: undefined, internals: {
}; ...node.internals,
handleBounds: undefined,
},
});
updatedInternals = true; updatedInternals = true;
} else { continue;
const dimensions = getDimensions(update.nodeElement); }
const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
const doUpdate = !!(
dimensions.width &&
dimensions.height &&
(dimensionChanged || !node.internals.handleBounds || update.force)
);
if (doUpdate) { const dimensions = getDimensions(update.nodeElement);
const nodeBounds = update.nodeElement.getBoundingClientRect(); const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
const extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent; const doUpdate = !!(
let { positionAbsolute } = node.internals; dimensions.width &&
dimensions.height &&
(dimensionChanged || !node.internals.handleBounds || update.force)
);
if (node.parentId && node.extent === 'parent') { if (doUpdate) {
positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId)!); const nodeBounds = update.nodeElement.getBoundingClientRect();
} else if (extent) { const extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent;
positionAbsolute = clampPosition(positionAbsolute, extent, dimensions); let { positionAbsolute } = node.internals;
}
node.measured = dimensions; if (node.parentId && node.extent === 'parent') {
node.internals = { positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId)!);
} else if (extent) {
positionAbsolute = clampPosition(positionAbsolute, extent, dimensions);
}
const newNode = {
...node,
measured: dimensions,
internals: {
...node.internals, ...node.internals,
positionAbsolute, positionAbsolute,
handleBounds: { handleBounds: {
source: getHandleBounds('source', update.nodeElement, nodeBounds, zoom, node.id), source: getHandleBounds('source', update.nodeElement, nodeBounds, zoom, node.id),
target: getHandleBounds('target', update.nodeElement, nodeBounds, zoom, node.id), target: getHandleBounds('target', update.nodeElement, nodeBounds, zoom, node.id),
}, },
}; },
if (node.parentId) { };
updateChildNode(node, nodeLookup, parentLookup, { nodeOrigin });
}
updatedInternals = true; nodeLookup.set(node.id, newNode);
if (dimensionChanged) { if (node.parentId) {
changes.push({ updateChildNode(newNode, nodeLookup, parentLookup, { nodeOrigin });
}
updatedInternals = true;
if (dimensionChanged) {
changes.push({
id: node.id,
type: 'dimensions',
dimensions,
});
if (node.expandParent && node.parentId) {
parentExpandChildren.push({
id: node.id, id: node.id,
type: 'dimensions', parentId: node.parentId,
dimensions, rect: nodeToRect(newNode, nodeOrigin),
}); });
if (node.expandParent && node.parentId) {
parentExpandChildren.push({
id: node.id,
parentId: node.parentId,
rect: nodeToRect(node, nodeOrigin),
});
}
} }
} }
} }