89 lines
2.4 KiB
TypeScript
89 lines
2.4 KiB
TypeScript
import { ElementId, Node, NodeInternals, NodeInternalsItem, XYPosition } from '../types';
|
|
|
|
type XYZPosition = XYPosition & { z: number };
|
|
type ParentNodes = Record<ElementId, boolean>;
|
|
|
|
function calculateXYZPosition(
|
|
node: NodeInternalsItem,
|
|
nodeInternals: NodeInternals,
|
|
parentNodes: ParentNodes,
|
|
result: XYZPosition
|
|
): XYZPosition {
|
|
if (!node.parentNode) {
|
|
return result;
|
|
}
|
|
const parentNode = nodeInternals.get(node.parentNode)!;
|
|
|
|
// +1 for each recursion level
|
|
let zAddition = 1;
|
|
|
|
// +2 if it's a parent node, so that groups/parents are always on top
|
|
if (parentNodes[node.parentNode!]) {
|
|
zAddition = 2;
|
|
}
|
|
|
|
if (parentNode.z) {
|
|
zAddition += parentNode.z;
|
|
}
|
|
|
|
return calculateXYZPosition(parentNode, nodeInternals, parentNodes, {
|
|
x: (result.x ?? 0) + (parentNode.position?.x ?? 0),
|
|
y: (result.y ?? 0) + (parentNode.position?.y ?? 0),
|
|
z: (result.z ?? 0) + zAddition,
|
|
});
|
|
}
|
|
export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals): NodeInternals {
|
|
const nextNodeInternals = new Map<ElementId, NodeInternalsItem>();
|
|
const parentNodes: ParentNodes = {};
|
|
|
|
nodes.forEach((node) => {
|
|
const internals: NodeInternalsItem = {
|
|
...nodeInternals.get(node.id),
|
|
id: node.id,
|
|
width: node.width || null,
|
|
height: node.height || null,
|
|
position: node.position,
|
|
positionAbsolute: node.position,
|
|
z: node.dragging || node.selected ? 1000 : node.zIndex || 0,
|
|
};
|
|
if (node.parentNode) {
|
|
internals.parentNode = node.parentNode;
|
|
parentNodes[node.parentNode] = true;
|
|
}
|
|
nextNodeInternals.set(node.id, internals);
|
|
});
|
|
|
|
nodes.forEach((node) => {
|
|
const updatedInternals: NodeInternalsItem = nextNodeInternals.get(node.id)!;
|
|
|
|
if (node.parentNode || parentNodes[node.id]) {
|
|
let startingZ = updatedInternals.z || 0;
|
|
|
|
if (!startingZ) {
|
|
if (parentNodes[node.id] && node.parentNode) {
|
|
startingZ = 2;
|
|
} else if (node.parentNode) {
|
|
startingZ = 1;
|
|
}
|
|
}
|
|
|
|
const { x, y, z } = calculateXYZPosition(node, nextNodeInternals, parentNodes, {
|
|
...node.position,
|
|
z: startingZ,
|
|
});
|
|
|
|
updatedInternals.positionAbsolute = {
|
|
x,
|
|
y,
|
|
};
|
|
updatedInternals.z = z;
|
|
|
|
if (parentNodes[node.id]) {
|
|
updatedInternals.isParent = true;
|
|
}
|
|
}
|
|
});
|
|
|
|
return nextNodeInternals;
|
|
}
|