Skip to Content

2024-06-11

Layouting example for Entitree Flex

Hayleigh Thompson
Software Engineer

We add a new layouting algorithm to our example lineup with the addition of Entitree Flex. This algorithm is similar to d3-hierarchy but allows for sibling nodes as well as nodes with different dimensions.

This example was very kindly contributed by GitHub user @kaustubhxd , thanks Kaustubh! Check it out below.

import { Position } from '@xyflow/react'; import { layoutFromMap } from 'entitree-flex'; const nodeWidth = 150; const nodeHeight = 36; const Orientation = { Vertical: 'vertical', Horizontal: 'horizontal', }; const entitreeSettings = { clone: true, // returns a copy of the input, if your application does not allow editing the original object enableFlex: true, // has slightly better performance if turned off (node.width, node.height will not be read) firstDegreeSpacing: 100, // spacing in px between nodes belonging to the same source, e.g. children with same parent nextAfterAccessor: 'spouses', // the side node prop used to go sideways, AFTER the current node nextAfterSpacing: 100, // the spacing of the "side" nodes AFTER the current node nextBeforeAccessor: 'siblings', // the side node prop used to go sideways, BEFORE the current node nextBeforeSpacing: 100, // the spacing of the "side" nodes BEFORE the current node nodeHeight, // default node height in px nodeWidth, // default node width in px orientation: Orientation.Vertical, // "vertical" to see parents top and children bottom, "horizontal" to see parents left and rootX: 0, // set root position if other than 0 rootY: 0, // set root position if other than 0 secondDegreeSpacing: 100, // spacing in px between nodes not belonging to same parent eg "cousin" nodes sourcesAccessor: 'parents', // the prop used as the array of ancestors ids sourceTargetSpacing: 100, // the "vertical" spacing between nodes in vertical orientation, horizontal otherwise targetsAccessor: 'children', // the prop used as the array of children ids }; const { Top, Bottom, Left, Right } = Position; export const layoutElements = (tree, rootId, direction = 'TB') => { const isTreeHorizontal = direction === 'LR'; const { nodes: entitreeNodes, rels: entitreeEdges } = layoutFromMap( rootId, tree, { ...entitreeSettings, orientation: isTreeHorizontal ? Orientation.Horizontal : Orientation.Vertical, }, ); const nodes = [], edges = []; entitreeEdges.forEach((edge) => { const sourceNode = edge.source.id; const targetNode = edge.target.id; const newEdge = {}; newEdge.id = 'e' + sourceNode + targetNode; newEdge.source = sourceNode; newEdge.target = targetNode; newEdge.type = 'smoothstep'; newEdge.animated = 'true'; // Check if target node is spouse or sibling const isTargetSpouse = !!edge.target.isSpouse; const isTargetSibling = !!edge.target.isSibling; if (isTargetSpouse) { newEdge.sourceHandle = isTreeHorizontal ? Bottom : Right; newEdge.targetHandle = isTreeHorizontal ? Top : Left; } else if (isTargetSibling) { newEdge.sourceHandle = isTreeHorizontal ? Top : Left; newEdge.targetHandle = isTreeHorizontal ? Bottom : Right; } else { newEdge.sourceHandle = isTreeHorizontal ? Right : Bottom; newEdge.targetHandle = isTreeHorizontal ? Left : Top; } edges.push(newEdge); }); entitreeNodes.forEach((node) => { const newNode = {}; const isSpouse = !!node?.isSpouse; const isSibling = !!node?.isSibling; const isRoot = node?.id === rootId; if (isSpouse) { newNode.sourcePosition = isTreeHorizontal ? Bottom : Right; newNode.targetPosition = isTreeHorizontal ? Top : Left; } else if (isSibling) { newNode.sourcePosition = isTreeHorizontal ? Top : Left; newNode.targetPosition = isTreeHorizontal ? Bottom : Right; } else { newNode.sourcePosition = isTreeHorizontal ? Right : Bottom; newNode.targetPosition = isTreeHorizontal ? Left : Top; } newNode.data = { label: node.name, direction, isRoot, ...node }; newNode.id = node.id; newNode.type = 'custom'; newNode.width = nodeWidth; newNode.height = nodeHeight; newNode.position = { x: node.x, y: node.y, }; nodes.push(newNode); }); return { nodes, edges }; };

Get Pro examples, prioritized bug reports, 1:1 support from the maintainers, and more with React Flow Pro

Last updated on