Skip to content

Commit ad5dac7

Browse files
committed
feat: allow using rect for nodes
Signed-off-by: Andres Correa Casablanca <castarco@coderspirit.xyz>
1 parent cf505fc commit ad5dac7

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/BeautifulTree.tsx

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,25 @@ export type CssClassesGetter = (
77
data?: Readonly<Record<string, unknown>> | undefined,
88
) => string[]
99

10+
export type NodeShapeGetter = (
11+
data?: Readonly<Record<string, unknown>> | undefined,
12+
) => { type: 'circle' | 'rect' }
13+
1014
export interface BeautifulTreeProps {
1115
readonly id: string
1216
readonly svgProps: {
1317
readonly width: number
1418
readonly height: number
1519
readonly sizeUnit?: '%' | 'em' | 'px' | 'rem'
1620
}
21+
readonly nodeShape?: 'circle' | 'rect'
22+
readonly hCoef?: number
1723
readonly tree: Tree
1824
readonly computeLayout: (
1925
tree: Readonly<Tree>,
2026
) => Readonly<WrappedTreeWithLayout>
2127
readonly getNodeClass?: CssClassesGetter | undefined
28+
readonly getNodeShape?: NodeShapeGetter | undefined
2229
readonly getEdgeClass?: CssClassesGetter | undefined
2330
}
2431

@@ -33,19 +40,24 @@ function runClassesGetter(
3340
export function BeautifulTree({
3441
id,
3542
svgProps,
43+
nodeShape,
44+
hCoef = 1,
3645
tree,
3746
computeLayout,
38-
getNodeClass: nodeClassesInferrer,
39-
getEdgeClass: edgeClassesInferrer,
47+
getNodeClass,
48+
getNodeShape,
49+
getEdgeClass,
4050
}: Readonly<BeautifulTreeProps>): JSX.Element {
4151
const { tree: treeWithLayout, mX, mY } = computeLayout(tree)
4252
const { width, height, sizeUnit = 'px' } = svgProps
4353

4454
const xCoef = width / (mX + 2)
4555
const yCoef = height / (mY + 2)
46-
const maxNodeWidth = xCoef * 0.25
47-
const maxNodeHeight = yCoef * 0.25
48-
const maxNodeRadius = Math.min(maxNodeWidth, maxNodeHeight)
56+
const maxNodeWidth = xCoef * 0.5
57+
const maxNodeHeight = Math.min(yCoef * 0.5, maxNodeWidth * hCoef)
58+
const widthCenterShift = maxNodeWidth * 0.5
59+
const heightCenterShift = maxNodeHeight * 0.5
60+
const maxNodeRadius = maxNodeHeight * 0.5
4961

5062
return (
5163
<svg
@@ -58,13 +70,15 @@ export function BeautifulTree({
5870
}}
5971
className={'beautiful-tree-react'}
6072
>
61-
<style>{'line{stroke:black;}circle{stroke:black;fill:white;}'}</style>
73+
<style>
74+
{'line{stroke:black;}circle,rect{stroke:black;fill:white;}'}
75+
</style>
6276
{Array.from(edgesIterator(treeWithLayout), (edge, idx) => {
6377
return (
6478
<line
6579
key={`${id}-edge-${idx}`}
6680
className={`beautiful-tree-edge${runClassesGetter(
67-
edgeClassesInferrer,
81+
getEdgeClass,
6882
edge.eData,
6983
)}`}
7084
x1={(edge.start.x + 1) * xCoef}
@@ -76,13 +90,30 @@ export function BeautifulTree({
7690
})}
7791
{Array.from(postOrderIterator(treeWithLayout), (node, idx) => {
7892
const nm = node.meta
79-
return (
93+
94+
const _nodeShape = getNodeShape?.(node.data) ?? nodeShape ?? 'circle'
95+
96+
return _nodeShape === 'rect' ? (
97+
<rect
98+
key={`${id}-node-${idx}`}
99+
className={`beautiful-tree-node${
100+
nm.isRoot ? ' beautiful-tree-root' : ''
101+
}${nm.isLeaf ? ' beautiful-tree-leaf' : ''}${runClassesGetter(
102+
getNodeClass,
103+
node.data,
104+
)}`}
105+
x={(nm.pos.x + 1) * xCoef - widthCenterShift}
106+
y={(nm.pos.y + 1) * yCoef - heightCenterShift}
107+
width={maxNodeWidth}
108+
height={maxNodeHeight}
109+
/>
110+
) : (
80111
<circle
81112
key={`${id}-node-${idx}`}
82113
className={`beautiful-tree-node${
83114
nm.isRoot ? ' beautiful-tree-root' : ''
84115
}${nm.isLeaf ? ' beautiful-tree-leaf' : ''}${runClassesGetter(
85-
nodeClassesInferrer,
116+
getNodeClass,
86117
node.data,
87118
)}`}
88119
cx={(nm.pos.x + 1) * xCoef}

0 commit comments

Comments
 (0)