@@ -7,18 +7,25 @@ export type CssClassesGetter = (
7
7
data ?: Readonly < Record < string , unknown > > | undefined ,
8
8
) => string [ ]
9
9
10
+ export type NodeShapeGetter = (
11
+ data ?: Readonly < Record < string , unknown > > | undefined ,
12
+ ) => { type : 'circle' | 'rect' }
13
+
10
14
export interface BeautifulTreeProps {
11
15
readonly id : string
12
16
readonly svgProps : {
13
17
readonly width : number
14
18
readonly height : number
15
19
readonly sizeUnit ?: '%' | 'em' | 'px' | 'rem'
16
20
}
21
+ readonly nodeShape ?: 'circle' | 'rect'
22
+ readonly hCoef ?: number
17
23
readonly tree : Tree
18
24
readonly computeLayout : (
19
25
tree : Readonly < Tree > ,
20
26
) => Readonly < WrappedTreeWithLayout >
21
27
readonly getNodeClass ?: CssClassesGetter | undefined
28
+ readonly getNodeShape ?: NodeShapeGetter | undefined
22
29
readonly getEdgeClass ?: CssClassesGetter | undefined
23
30
}
24
31
@@ -33,19 +40,24 @@ function runClassesGetter(
33
40
export function BeautifulTree ( {
34
41
id,
35
42
svgProps,
43
+ nodeShape,
44
+ hCoef = 1 ,
36
45
tree,
37
46
computeLayout,
38
- getNodeClass : nodeClassesInferrer ,
39
- getEdgeClass : edgeClassesInferrer ,
47
+ getNodeClass,
48
+ getNodeShape,
49
+ getEdgeClass,
40
50
} : Readonly < BeautifulTreeProps > ) : JSX . Element {
41
51
const { tree : treeWithLayout , mX, mY } = computeLayout ( tree )
42
52
const { width, height, sizeUnit = 'px' } = svgProps
43
53
44
54
const xCoef = width / ( mX + 2 )
45
55
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
49
61
50
62
return (
51
63
< svg
@@ -58,13 +70,15 @@ export function BeautifulTree({
58
70
} }
59
71
className = { 'beautiful-tree-react' }
60
72
>
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 >
62
76
{ Array . from ( edgesIterator ( treeWithLayout ) , ( edge , idx ) => {
63
77
return (
64
78
< line
65
79
key = { `${ id } -edge-${ idx } ` }
66
80
className = { `beautiful-tree-edge${ runClassesGetter (
67
- edgeClassesInferrer ,
81
+ getEdgeClass ,
68
82
edge . eData ,
69
83
) } `}
70
84
x1 = { ( edge . start . x + 1 ) * xCoef }
@@ -76,13 +90,30 @@ export function BeautifulTree({
76
90
} ) }
77
91
{ Array . from ( postOrderIterator ( treeWithLayout ) , ( node , idx ) => {
78
92
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
+ ) : (
80
111
< circle
81
112
key = { `${ id } -node-${ idx } ` }
82
113
className = { `beautiful-tree-node${
83
114
nm . isRoot ? ' beautiful-tree-root' : ''
84
115
} ${ nm . isLeaf ? ' beautiful-tree-leaf' : '' } ${ runClassesGetter (
85
- nodeClassesInferrer ,
116
+ getNodeClass ,
86
117
node . data ,
87
118
) } `}
88
119
cx = { ( nm . pos . x + 1 ) * xCoef }
0 commit comments