Merge pull request #4105 from xyflow/refactor/internal-nodes
React Flow 12: separate user nodes and internal nodes
This commit is contained in:
@@ -56,18 +56,19 @@ const initialEdges: Edge[] = [
|
||||
const defaultEdgeOptions = {};
|
||||
|
||||
const BasicFlow = () => {
|
||||
const { setNodes, getNodes, setEdges, getEdges, deleteElements, updateNodeData, toObject, setViewport } =
|
||||
const { addNodes, setNodes, getNodes, setEdges, getEdges, deleteElements, updateNodeData, toObject, setViewport } =
|
||||
useReactFlow();
|
||||
|
||||
const updatePos = () => {
|
||||
setNodes((nodes) =>
|
||||
nodes.map((node) => {
|
||||
node.position = {
|
||||
x: Math.random() * 400,
|
||||
y: Math.random() * 400,
|
||||
return {
|
||||
...node,
|
||||
position: {
|
||||
x: Math.random() * 400,
|
||||
y: Math.random() * 400,
|
||||
},
|
||||
};
|
||||
|
||||
return node;
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -78,9 +79,10 @@ const BasicFlow = () => {
|
||||
const toggleClassnames = () => {
|
||||
setNodes((nodes) =>
|
||||
nodes.map((node) => {
|
||||
node.className = node.className === 'light' ? 'dark' : 'light';
|
||||
|
||||
return node;
|
||||
return {
|
||||
...node,
|
||||
className: node.className === 'light' ? 'dark' : 'light',
|
||||
};
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -108,6 +110,14 @@ const BasicFlow = () => {
|
||||
updateNodeData('1', { label: 'update' });
|
||||
updateNodeData('2', { label: 'update' });
|
||||
};
|
||||
const addNode = () => {
|
||||
addNodes({
|
||||
id: `${Math.random()}`,
|
||||
data: { label: 'Node' },
|
||||
position: { x: Math.random() * 300, y: Math.random() * 300 },
|
||||
className: 'light',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
@@ -144,6 +154,7 @@ const BasicFlow = () => {
|
||||
<button onClick={deleteSomeElements}>deleteSomeElements</button>
|
||||
<button onClick={onSetNodes}>setNodes</button>
|
||||
<button onClick={onUpdateNode}>updateNode</button>
|
||||
<button onClick={addNode}>addNode</button>
|
||||
</Panel>
|
||||
</ReactFlow>
|
||||
);
|
||||
|
||||
@@ -9,8 +9,8 @@ function getNodeIntersection(intersectionNode: Node, targetNode: Node) {
|
||||
width: intersectionNodeWidth,
|
||||
height: intersectionNodeHeight,
|
||||
positionAbsolute: intersectionNodePosition,
|
||||
} = intersectionNode.computed || {};
|
||||
const targetPosition = targetNode.computed?.positionAbsolute!;
|
||||
} = intersectionNode.measured || {};
|
||||
const targetPosition = targetNode.measured?.positionAbsolute!;
|
||||
|
||||
const w = intersectionNodeWidth! / 2;
|
||||
const h = intersectionNodeHeight! / 2;
|
||||
@@ -33,7 +33,7 @@ function getNodeIntersection(intersectionNode: Node, targetNode: Node) {
|
||||
|
||||
// returns the position (top,right,bottom or right) passed node compared to the intersection point
|
||||
function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
|
||||
const n = { ...node.computed?.positionAbsolute, ...node };
|
||||
const n = { ...node.measured?.positionAbsolute, ...node };
|
||||
const nx = Math.round(n.x!);
|
||||
const ny = Math.round(n.y!);
|
||||
const px = Math.round(intersectionPoint.x);
|
||||
@@ -42,13 +42,13 @@ function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
|
||||
if (px <= nx + 1) {
|
||||
return Position.Left;
|
||||
}
|
||||
if (px >= nx + n.computed?.width! - 1) {
|
||||
if (px >= nx + n.measured?.width! - 1) {
|
||||
return Position.Right;
|
||||
}
|
||||
if (py <= ny + 1) {
|
||||
return Position.Top;
|
||||
}
|
||||
if (py >= n.y! + n.computed?.height! - 1) {
|
||||
if (py >= n.y! + n.measured?.height! - 1) {
|
||||
return Position.Bottom;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import { getEdgeParams } from './utils';
|
||||
|
||||
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, style }) => {
|
||||
const { sourceNode, targetNode } = useStore((s) => {
|
||||
const sourceNode = s.nodes.find((n) => n.id === source);
|
||||
const targetNode = s.nodes.find((n) => n.id === target);
|
||||
const sourceNode = s.nodeLookup.get(source);
|
||||
const targetNode = s.nodeLookup.get(target);
|
||||
|
||||
return { sourceNode, targetNode };
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Position, XYPosition, Node, Edge } from '@xyflow/react';
|
||||
import { Position, XYPosition, Node, Edge, InternalNode } from '@xyflow/react';
|
||||
|
||||
// this helper function returns the intersection point
|
||||
// of the line between the center of the intersectionNode and the target node
|
||||
@@ -6,7 +6,7 @@ function getNodeIntersection(intersectionNode: Node, targetNode: Node): XYPositi
|
||||
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a
|
||||
|
||||
const { position: intersectionNodePosition } = intersectionNode;
|
||||
const { width: intersectionNodeWidth, height: intersectionNodeHeight } = intersectionNode.computed ?? {
|
||||
const { width: intersectionNodeWidth, height: intersectionNodeHeight } = intersectionNode.measured ?? {
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
@@ -42,13 +42,13 @@ function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
|
||||
if (px <= nx + 1) {
|
||||
return Position.Left;
|
||||
}
|
||||
if (px >= nx + (n.computed?.width ?? 0) - 1) {
|
||||
if (px >= nx + (n.measured?.width ?? 0) - 1) {
|
||||
return Position.Right;
|
||||
}
|
||||
if (py <= ny + 1) {
|
||||
return Position.Top;
|
||||
}
|
||||
if (py >= n.y + (n.computed?.height ?? 0) - 1) {
|
||||
if (py >= n.y + (n.measured?.height ?? 0) - 1) {
|
||||
return Position.Bottom;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
|
||||
}
|
||||
|
||||
// returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge
|
||||
export function getEdgeParams(source: Node, target: Node) {
|
||||
export function getEdgeParams(source: InternalNode, target: InternalNode) {
|
||||
const sourceIntersectionPoint = getNodeIntersection(source, target);
|
||||
const targetIntersectionPoint = getNodeIntersection(target, source);
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ const initialNodes: Node[] = [
|
||||
label: 'Child with extent: parent',
|
||||
},
|
||||
position: { x: 50, y: 50 },
|
||||
parentNode: '5',
|
||||
parentId: '5',
|
||||
extent: 'parent',
|
||||
width: 50,
|
||||
height: 100,
|
||||
@@ -148,7 +148,7 @@ const initialNodes: Node[] = [
|
||||
type: 'defaultResizer',
|
||||
data: { label: 'Child with expandParent' },
|
||||
position: { x: 150, y: 100 },
|
||||
parentNode: '5',
|
||||
parentId: '5',
|
||||
expandParent: true,
|
||||
style: { ...nodeStyle },
|
||||
},
|
||||
@@ -157,7 +157,7 @@ const initialNodes: Node[] = [
|
||||
type: 'defaultResizer',
|
||||
data: { label: 'Child with expandParent & keepAspectRatio', keepAspectRatio: true },
|
||||
position: { x: 25, y: 200 },
|
||||
parentNode: '5',
|
||||
parentId: '5',
|
||||
expandParent: true,
|
||||
style: { ...nodeStyle },
|
||||
},
|
||||
|
||||
@@ -50,7 +50,7 @@ const initialNodes: Node[] = [
|
||||
data: { label: 'Node 4a' },
|
||||
position: { x: 15, y: 15 },
|
||||
className: 'light',
|
||||
parentNode: '4',
|
||||
parentId: '4',
|
||||
origin: [0.5, 0.5],
|
||||
|
||||
extent: [
|
||||
@@ -68,21 +68,21 @@ const initialNodes: Node[] = [
|
||||
height: 200,
|
||||
width: 300,
|
||||
},
|
||||
parentNode: '4',
|
||||
parentId: '4',
|
||||
},
|
||||
{
|
||||
id: '4b1',
|
||||
data: { label: 'Node 4b1' },
|
||||
position: { x: 40, y: 20 },
|
||||
className: 'light',
|
||||
parentNode: '4b',
|
||||
parentId: '4b',
|
||||
},
|
||||
{
|
||||
id: '4b2',
|
||||
data: { label: 'Node 4b2' },
|
||||
position: { x: 20, y: 100 },
|
||||
className: 'light',
|
||||
parentNode: '4b',
|
||||
parentId: '4b',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
@@ -98,7 +98,7 @@ const initialNodes: Node[] = [
|
||||
data: { label: 'Node 5a' },
|
||||
position: { x: 0, y: 0 },
|
||||
className: 'light',
|
||||
parentNode: '5',
|
||||
parentId: '5',
|
||||
extent: 'parent',
|
||||
},
|
||||
{
|
||||
@@ -106,7 +106,7 @@ const initialNodes: Node[] = [
|
||||
data: { label: 'Node 5b' },
|
||||
position: { x: 225, y: 50 },
|
||||
className: 'light',
|
||||
parentNode: '5',
|
||||
parentId: '5',
|
||||
expandParent: true,
|
||||
},
|
||||
{
|
||||
@@ -160,7 +160,7 @@ const Subflow = () => {
|
||||
const updatePos = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
if (!n.parentNode) {
|
||||
if (!n.parentId) {
|
||||
return {
|
||||
...n,
|
||||
position: {
|
||||
@@ -194,7 +194,7 @@ const Subflow = () => {
|
||||
return nds.map((n) => {
|
||||
return {
|
||||
...n,
|
||||
hidden: !!n.parentNode && !n.hidden,
|
||||
hidden: !!n.parentId && !n.hidden,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user