11import { useMemo } from 'react'
22import { partition as d3Partition , hierarchy as d3Hierarchy } from 'd3-hierarchy'
3+ import { scaleRadial as d3ScaleRadial } from 'd3-scale'
34import cloneDeep from 'lodash/cloneDeep'
45import sortBy from 'lodash/sortBy'
56import { usePropertyAccessor , useTheme , useValueFormatter } from '@nivo/core'
@@ -21,6 +22,8 @@ export const useSunburst = <RawDatum>({
2122 valueFormat,
2223 radius,
2324 cornerRadius = defaultProps . cornerRadius ,
25+ innerRadius = defaultProps . innerRadius ,
26+ renderRootNode = defaultProps . renderRootNode ,
2427 colors = defaultProps . colors ,
2528 colorBy = defaultProps . colorBy ,
2629 inheritColorFromParent = defaultProps . inheritColorFromParent ,
@@ -32,6 +35,8 @@ export const useSunburst = <RawDatum>({
3235 valueFormat ?: DataProps < RawDatum > [ 'valueFormat' ]
3336 radius : number
3437 cornerRadius ?: SunburstCommonProps < RawDatum > [ 'cornerRadius' ]
38+ innerRadius ?: SunburstCommonProps < RawDatum > [ 'innerRadius' ]
39+ renderRootNode ?: SunburstCommonProps < RawDatum > [ 'renderRootNode' ]
3540 colors ?: SunburstCommonProps < RawDatum > [ 'colors' ]
3641 colorBy ?: SunburstCommonProps < RawDatum > [ 'colorBy' ]
3742 inheritColorFromParent ?: SunburstCommonProps < RawDatum > [ 'inheritColorFromParent' ]
@@ -57,8 +62,10 @@ export const useSunburst = <RawDatum>({
5762 const hierarchy = d3Hierarchy ( clonedData ) . sum ( getValue )
5863
5964 const partition = d3Partition < RawDatum > ( ) . size ( [ 2 * Math . PI , radius * radius ] )
60- // exclude root node
61- const descendants = partition ( hierarchy ) . descendants ( ) . slice ( 1 )
65+ // exclude root node if renderRootNode is false
66+ const descendants = renderRootNode
67+ ? partition ( hierarchy ) . descendants ( )
68+ : partition ( hierarchy ) . descendants ( ) . slice ( 1 )
6269
6370 const total = hierarchy . value ?? 0
6471
@@ -68,6 +75,12 @@ export const useSunburst = <RawDatum>({
6875 // are going to be computed first
6976 const sortedNodes = sortBy ( descendants , 'depth' )
7077
78+ const innerRadiusOffset = radius * Math . min ( innerRadius , 1 )
79+
80+ const maxDepth = Math . max ( ...sortedNodes . map ( n => n . depth ) )
81+
82+ const radiusScale = d3ScaleRadial ( ) . domain ( [ 0 , maxDepth ] ) . range ( [ innerRadiusOffset , radius ] )
83+
7184 return sortedNodes . reduce < ComputedDatum < RawDatum > [ ] > ( ( acc , descendant ) => {
7285 const id = getId ( descendant . data )
7386 // d3 hierarchy node value is optional by default as it depends on
@@ -78,12 +91,13 @@ export const useSunburst = <RawDatum>({
7891 const value = descendant . value !
7992 const percentage = ( 100 * value ) / total
8093 const path = descendant . ancestors ( ) . map ( ancestor => getId ( ancestor . data ) )
94+ const isRootNode = renderRootNode && descendant . depth === 0
8195
8296 const arc : Arc = {
8397 startAngle : descendant . x0 ,
8498 endAngle : descendant . x1 ,
85- innerRadius : Math . sqrt ( descendant . y0 ) ,
86- outerRadius : Math . sqrt ( descendant . y1 ) ,
99+ innerRadius : isRootNode ? 0 : radiusScale ( descendant . depth - 1 ) ,
100+ outerRadius : isRootNode ? innerRadiusOffset : radiusScale ( descendant . depth ) ,
87101 }
88102
89103 let parent : ComputedDatum < RawDatum > | undefined
@@ -118,6 +132,8 @@ export const useSunburst = <RawDatum>({
118132 } , [
119133 data ,
120134 radius ,
135+ innerRadius ,
136+ renderRootNode ,
121137 getValue ,
122138 getId ,
123139 valueFormat ,
0 commit comments