Skip to content

Commit

Permalink
feat(sunburst): add innerRadius and renderRootNode props
Browse files Browse the repository at this point in the history
  • Loading branch information
0x706b committed Nov 27, 2024
1 parent cdf60f7 commit 9cf33f7
Show file tree
Hide file tree
Showing 10 changed files with 25,957 additions and 34,357 deletions.
7 changes: 6 additions & 1 deletion packages/arcs/src/centers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export const useArcCentersTransition = <Datum extends DatumWithArc, ExtraProps =
mode: ArcTransitionMode = 'innerRadius',
extra?: TransitionExtra<Datum, ExtraProps>
) => {
// center root node label
const dataWithCenteredRoot = data.map(d =>
d.arc.innerRadius === 0 ? { ...d, arc: { ...d.arc, outerRadius: 0 } } : d
)

const { animate, config: springConfig } = useMotionConfig()

const phases = useArcTransitionMode<Datum, ExtraProps>(mode, extra)
Expand All @@ -60,7 +65,7 @@ export const useArcCentersTransition = <Datum extends DatumWithArc, ExtraProps =
innerRadius: number
outerRadius: number
} & ExtraProps
>(data, {
>(dataWithCenteredRoot, {
keys: datum => datum.id,
initial: phases.update,
from: phases.enter,
Expand Down
4 changes: 4 additions & 0 deletions packages/sunburst/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@
"@nivo/tooltip": "workspace:*",
"@types/d3-hierarchy": "^1.1.8",
"d3-hierarchy": "^1.1.8",
"d3-scale": "^4.0.2",
"lodash": "^4.17.21"
},
"peerDependencies": {
"react": ">= 16.14.0 < 19.0.0"
},
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@types/d3-scale": "^4.0.8"
}
}
4 changes: 4 additions & 0 deletions packages/sunburst/src/Sunburst.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const InnerSunburst = <RawDatum,>({
data,
id = defaultProps.id,
value = defaultProps.value,
innerRadius = defaultProps.innerRadius,
renderRootNode = defaultProps.renderRootNode,
valueFormat,
cornerRadius = defaultProps.cornerRadius,
layers = defaultProps.layers as SunburstLayer<RawDatum>[],
Expand Down Expand Up @@ -73,6 +75,8 @@ const InnerSunburst = <RawDatum,>({
valueFormat,
radius,
cornerRadius,
innerRadius,
renderRootNode,
colors,
colorBy,
inheritColorFromParent,
Expand Down
25 changes: 22 additions & 3 deletions packages/sunburst/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMemo } from 'react'
import { partition as d3Partition, hierarchy as d3Hierarchy } from 'd3-hierarchy'
import { scaleRadial as d3ScaleRadial } from 'd3-scale'
import cloneDeep from 'lodash/cloneDeep'
import sortBy from 'lodash/sortBy'
import { usePropertyAccessor, useTheme, useValueFormatter } from '@nivo/core'
Expand All @@ -21,6 +22,8 @@ export const useSunburst = <RawDatum>({
valueFormat,
radius,
cornerRadius = defaultProps.cornerRadius,
innerRadius = defaultProps.innerRadius,
renderRootNode = defaultProps.renderRootNode,
colors = defaultProps.colors,
colorBy = defaultProps.colorBy,
inheritColorFromParent = defaultProps.inheritColorFromParent,
Expand All @@ -32,6 +35,8 @@ export const useSunburst = <RawDatum>({
valueFormat?: DataProps<RawDatum>['valueFormat']
radius: number
cornerRadius?: SunburstCommonProps<RawDatum>['cornerRadius']
innerRadius?: SunburstCommonProps<RawDatum>['innerRadius']
renderRootNode?: SunburstCommonProps<RawDatum>['renderRootNode']
colors?: SunburstCommonProps<RawDatum>['colors']
colorBy?: SunburstCommonProps<RawDatum>['colorBy']
inheritColorFromParent?: SunburstCommonProps<RawDatum>['inheritColorFromParent']
Expand All @@ -58,7 +63,9 @@ export const useSunburst = <RawDatum>({

const partition = d3Partition<RawDatum>().size([2 * Math.PI, radius * radius])
// exclude root node
const descendants = partition(hierarchy).descendants().slice(1)
const descendants = renderRootNode
? partition(hierarchy).descendants()
: partition(hierarchy).descendants().slice(1)

const total = hierarchy.value ?? 0

Expand All @@ -68,6 +75,12 @@ export const useSunburst = <RawDatum>({
// are going to be computed first
const sortedNodes = sortBy(descendants, 'depth')

const innerRadiusOffset = radius * Math.min(innerRadius, 1)

const maxDepth = Math.max(...sortedNodes.map(n => n.depth))

const scale = d3ScaleRadial().domain([0, maxDepth]).range([innerRadiusOffset, radius])

return sortedNodes.reduce<ComputedDatum<RawDatum>[]>((acc, descendant) => {
const id = getId(descendant.data)
// d3 hierarchy node value is optional by default as it depends on
Expand All @@ -82,8 +95,12 @@ export const useSunburst = <RawDatum>({
const arc: Arc = {
startAngle: descendant.x0,
endAngle: descendant.x1,
innerRadius: Math.sqrt(descendant.y0),
outerRadius: Math.sqrt(descendant.y1),
innerRadius:
renderRootNode && descendant.depth === 0 ? 0 : scale(descendant.depth - 1),
outerRadius:
renderRootNode && descendant.depth === 0
? innerRadius
: scale(descendant.depth),
}

let parent: ComputedDatum<RawDatum> | undefined
Expand Down Expand Up @@ -125,6 +142,8 @@ export const useSunburst = <RawDatum>({
getColor,
inheritColorFromParent,
getChildColor,
innerRadius,
renderRootNode,
])

const arcGenerator = useArcGenerator({ cornerRadius })
Expand Down
2 changes: 2 additions & 0 deletions packages/sunburst/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export const defaultProps = {
id: 'id',
value: 'value',
cornerRadius: 0,
innerRadius: 0.4,
renderRootNode: false,
layers: ['arcs', 'arcLabels'] as SunburstLayerId[],
colors: { scheme: 'nivo' } as unknown as OrdinalColorScaleConfig,
colorBy: 'id' as const,
Expand Down
2 changes: 2 additions & 0 deletions packages/sunburst/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ export type SunburstCommonProps<RawDatum> = {
height: number
margin?: Box
cornerRadius: number
innerRadius: number
renderRootNode: boolean
theme: Theme
colors: OrdinalColorScaleConfig<Omit<ComputedDatum<RawDatum>, 'color' | 'fill'>>
colorBy: 'id' | 'depth'
Expand Down
Loading

0 comments on commit 9cf33f7

Please sign in to comment.