Skip to content

Commit

Permalink
feat(sunburst): use arcs package
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc authored and wyze committed Apr 23, 2021
1 parent 296f5d1 commit bf225e7
Show file tree
Hide file tree
Showing 24 changed files with 669 additions and 653 deletions.
2 changes: 1 addition & 1 deletion packages/arcs/src/arc_labels/ArcLabelsLayer.tsx
Expand Up @@ -19,7 +19,7 @@ interface ArcLabelsLayerProps<Datum extends DatumWithArcAndColor> {
skipAngle: ArcLabelsProps<Datum>['arcLabelsSkipAngle']
textColor: ArcLabelsProps<Datum>['arcLabelsTextColor']
transitionMode: ArcTransitionMode
component?: ArcLabelComponent<Datum>
component?: ArcLabelsProps<Datum>['arcLabelsComponent']
}

export const ArcLabelsLayer = <Datum extends DatumWithArcAndColor>({
Expand Down
2 changes: 1 addition & 1 deletion packages/arcs/src/arc_labels/props.ts
Expand Up @@ -8,5 +8,5 @@ export interface ArcLabelsProps<Datum extends DatumWithArcAndColor> {
arcLabelsRadiusOffset: number
arcLabelsSkipAngle: number
arcLabelsTextColor: InheritedColorConfig<Datum>
component: ArcLabelComponent<Datum>
arcLabelsComponent: ArcLabelComponent<Datum>
}
2 changes: 1 addition & 1 deletion packages/arcs/src/useArcGenerator.ts
Expand Up @@ -17,7 +17,7 @@ export const useArcGenerator = ({
}: {
cornerRadius?: number
padAngle?: number
}): ArcGenerator =>
} = {}): ArcGenerator =>
useMemo(
() =>
d3Arc<Arc>()
Expand Down
3 changes: 1 addition & 2 deletions packages/pie/package.json
Expand Up @@ -34,8 +34,7 @@
"@nivo/legends": "0.67.0",
"@nivo/tooltip": "0.67.0",
"d3-shape": "^1.3.5",
"lodash": "^4.17.11",
"react-spring": "9.1.2"
"lodash": "^4.17.11"
},
"devDependencies": {
"@nivo/core": "0.67.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/pie/src/Pie.tsx
Expand Up @@ -48,7 +48,7 @@ const InnerPie = <RawDatum,>({
arcLabelsSkipAngle = defaultProps.arcLabelsSkipAngle,
arcLabelsTextColor = defaultProps.arcLabelsTextColor,
arcLabelsRadiusOffset = defaultProps.arcLabelsRadiusOffset,
arcLabelComponent,
arcLabelsComponent,

// arc link labels
enableArcLinkLabels = defaultProps.enableArcLinkLabels,
Expand Down Expand Up @@ -178,7 +178,7 @@ const InnerPie = <RawDatum,>({
skipAngle={arcLabelsSkipAngle}
textColor={arcLabelsTextColor}
transitionMode={transitionMode}
component={arcLabelComponent}
component={arcLabelsComponent}
/>
)
}
Expand Down
9 changes: 7 additions & 2 deletions packages/pie/src/hooks.ts
Expand Up @@ -2,7 +2,12 @@ import { useMemo, useState } from 'react'
import { get } from 'lodash'
import { pie as d3Pie } from 'd3-shape'
import { ArcGenerator, useArcGenerator, computeArcBoundingBox } from '@nivo/arcs'
import { degreesToRadians, radiansToDegrees, useValueFormatter } from '@nivo/core'
import {
degreesToRadians,
radiansToDegrees,
useValueFormatter,
usePropertyAccessor,
} from '@nivo/core'
import { OrdinalColorScaleConfig, useOrdinalColorScale } from '@nivo/colors'
import { defaultProps } from './props'
import { CompletePieSvgProps, ComputedDatum, PieArc, PieCustomLayerProps } from './types'
Expand All @@ -26,7 +31,7 @@ export const useNormalizedData = <RawDatum extends MayHaveLabel>({
}: Pick<CompletePieSvgProps<RawDatum>, 'id' | 'value' | 'valueFormat' | 'colors'> & {
data: RawDatum[]
}): Omit<ComputedDatum<RawDatum>, 'arc' | 'fill'>[] => {
const getId = useMemo(() => (typeof id === 'function' ? id : (d: RawDatum) => get(d, id)), [id])
const getId = usePropertyAccessor<RawDatum, string | number>(id)
const getValue = useMemo(
() => (typeof value === 'function' ? value : (d: RawDatum) => get(d, value)),
[value]
Expand Down
28 changes: 14 additions & 14 deletions packages/pie/src/types.ts
@@ -1,5 +1,13 @@
import * as React from 'react'
import { Box, Dimensions, Theme, SvgDefsAndFill, ModernMotionProps, ValueFormat } from '@nivo/core'
import {
Box,
Dimensions,
Theme,
SvgDefsAndFill,
ModernMotionProps,
ValueFormat,
PropertyAccessor,
} from '@nivo/core'
import {
Arc,
ArcGenerator,
Expand All @@ -11,16 +19,13 @@ import { OrdinalColorScaleConfig, InheritedColorConfig } from '@nivo/colors'
import { LegendProps } from '@nivo/legends'

export type DatumId = string | number
export type DatumValue = number
export type DatumFormattedValue = string | number
export type ValueFormatter = (value: number) => DatumFormattedValue

// Default datum to use when `id` and `value` properties
// use default values, should be redefined if using
// a different structure.
export interface DefaultRawDatum {
id: DatumId
value: DatumValue
value: number
}

export interface PieArc extends Arc {
Expand All @@ -36,8 +41,8 @@ export interface PieArc extends Arc {
export interface ComputedDatum<RawDatum> {
id: DatumId
label: DatumId
value: DatumValue
formattedValue: DatumFormattedValue
value: number
formattedValue: string
color: string
// only defined in case gradients or patterns are used
// and the datum matches one of the rules.
Expand All @@ -47,10 +52,6 @@ export interface ComputedDatum<RawDatum> {
arc: PieArc
}

export type DatumIdAccessorFunction<RawDatum> = (datum: RawDatum) => DatumId
export type DatumValueAccessorFunction<RawDatum> = (datum: RawDatum) => DatumValue
export type LabelAccessorFunction<RawDatum> = (datum: ComputedDatum<RawDatum>) => string | number

export interface DataProps<RawDatum> {
data: RawDatum[]
}
Expand Down Expand Up @@ -80,8 +81,8 @@ export type PieCustomLayer<RawDatum> = React.FC<PieCustomLayerProps<RawDatum>>
export type PieLayer<RawDatum> = PieLayerId | PieCustomLayer<RawDatum>

export type CommonPieProps<RawDatum> = {
id: string | DatumIdAccessorFunction<RawDatum>
value: string | DatumValueAccessorFunction<RawDatum>
id: PropertyAccessor<RawDatum, DatumId>
value: PropertyAccessor<RawDatum, number>
valueFormat?: ValueFormat<number>

margin: Box
Expand Down Expand Up @@ -122,7 +123,6 @@ export type PieHandlers<RawDatum, ElementType> = {
}

export type PieSvgCustomComponents<RawDatum> = {
arcLabelComponent?: ArcLabelsProps<ComputedDatum<RawDatum>>['component']
arcLinkLabelComponent?: ArcLinkLabelsProps<ComputedDatum<RawDatum>>['component']
}

Expand Down
2 changes: 1 addition & 1 deletion packages/pie/stories/pie.stories.tsx
Expand Up @@ -208,7 +208,7 @@ stories.add('custom arc label component', () => (
arcLinkLabelsOffset={2}
arcLinkLabelsColor={{ from: 'color' }}
arcLinkLabelsThickness={3}
arcLabelComponent={({ datum, label, style }) => (
arcLabelsComponent={({ datum, label, style }) => (
<animated.g transform={style.transform} style={{ pointerEvents: 'none' }}>
<circle fill={style.textColor} cy={6} r={15} />
<circle fill="#ffffff" stroke={datum.color} strokeWidth={2} r={16} />
Expand Down
6 changes: 3 additions & 3 deletions packages/pie/tests/Pie.test.tsx
Expand Up @@ -414,7 +414,7 @@ describe('Pie', () => {
width={400}
height={400}
data={sampleData}
arcLabelComponent={CustomArcLabel}
arcLabelsComponent={CustomArcLabel}
animate={false}
/>
)
Expand Down Expand Up @@ -700,7 +700,7 @@ describe('Pie', () => {
)
expect(wrapper.find('ArcShape')).toHaveLength(3)

wrapper.setProps({ layers: ['radialLabels', 'sliceLabels', 'legends'] })
wrapper.setProps({ layers: ['arcLinkLabels', 'arcLabels', 'legends'] })
expect(wrapper.find('ArcShape')).toHaveLength(0)
})

Expand All @@ -713,7 +713,7 @@ describe('Pie', () => {
height={400}
data={sampleData}
innerRadius={0.5}
layers={['slices', 'radialLabels', 'sliceLabels', 'legends', CustomLayer]}
layers={['arcs', 'arcLinkLabels', 'arcLabels', 'legends', CustomLayer]}
animate={false}
/>
)
Expand Down
8 changes: 3 additions & 5 deletions packages/sunburst/package.json
Expand Up @@ -29,17 +29,15 @@
"!dist/tsconfig.tsbuildinfo"
],
"dependencies": {
"@nivo/arcs": "0.67.0",
"@nivo/colors": "0.67.0",
"@nivo/tooltip": "0.67.0",
"d3-hierarchy": "^1.1.8",
"d3-shape": "^1.3.5",
"lodash": "^4.17.11",
"react-spring": "9.1.2"
"lodash": "^4.17.11"
},
"devDependencies": {
"@nivo/core": "0.67.0",
"@types/d3-hierarchy": "^1.1.7",
"@types/d3-shape": "^1.3.5"
"@types/d3-hierarchy": "^1.1.7"
},
"peerDependencies": {
"@nivo/core": "0.67.0",
Expand Down
86 changes: 86 additions & 0 deletions packages/sunburst/src/Arcs.tsx
@@ -0,0 +1,86 @@
import React, { createElement, useMemo } from 'react'
import { ArcGenerator, ArcsLayer } from '@nivo/arcs'
import { ComputedDatum, CompleteSvgProps } from './types'
import { useTooltip } from '@nivo/tooltip'

interface ArcsProps<RawDatum> {
center: [number, number]
data: ComputedDatum<RawDatum>[]
arcGenerator: ArcGenerator
borderWidth: CompleteSvgProps<RawDatum>['borderWidth']
borderColor: CompleteSvgProps<RawDatum>['borderColor']
isInteractive: CompleteSvgProps<RawDatum>['isInteractive']
onClick?: CompleteSvgProps<RawDatum>['onClick']
onMouseEnter?: CompleteSvgProps<RawDatum>['onMouseEnter']
onMouseMove?: CompleteSvgProps<RawDatum>['onMouseMove']
onMouseLeave?: CompleteSvgProps<RawDatum>['onMouseLeave']
tooltip: CompleteSvgProps<RawDatum>['tooltip']
transitionMode: CompleteSvgProps<RawDatum>['transitionMode']
}

export const Arcs = <RawDatum,>({
center,
data,
arcGenerator,
borderWidth,
borderColor,
isInteractive,
onClick,
onMouseEnter,
onMouseMove,
onMouseLeave,
tooltip,
transitionMode,
}: ArcsProps<RawDatum>) => {
const { showTooltipFromEvent, hideTooltip } = useTooltip()

const handleClick = useMemo(() => {
if (!isInteractive) return undefined

return (datum: ComputedDatum<RawDatum>, event: React.MouseEvent<SVGPathElement>) => {
onClick?.(datum, event)
}
}, [isInteractive, onClick])

const handleMouseEnter = useMemo(() => {
if (!isInteractive) return undefined

return (datum: ComputedDatum<RawDatum>, event: React.MouseEvent<SVGPathElement>) => {
showTooltipFromEvent(createElement(tooltip, datum), event)
onMouseEnter?.(datum, event)
}
}, [isInteractive, showTooltipFromEvent, onMouseEnter])

const handleMouseMove = useMemo(() => {
if (!isInteractive) return undefined

return (datum: ComputedDatum<RawDatum>, event: React.MouseEvent<SVGPathElement>) => {
showTooltipFromEvent(createElement(tooltip, datum), event)
onMouseMove?.(datum, event)
}
}, [isInteractive, showTooltipFromEvent, onMouseMove])

const handleMouseLeave = useMemo(() => {
if (!isInteractive) return undefined

return (datum: ComputedDatum<RawDatum>, event: React.MouseEvent<SVGPathElement>) => {
hideTooltip()
onMouseLeave?.(datum, event)
}
}, [isInteractive, hideTooltip, onMouseLeave])

return (
<ArcsLayer<ComputedDatum<RawDatum>>
center={center}
data={data}
arcGenerator={arcGenerator}
borderWidth={borderWidth}
borderColor={borderColor}
transitionMode={transitionMode}
onClick={handleClick}
onMouseEnter={handleMouseEnter}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
/>
)
}

0 comments on commit bf225e7

Please sign in to comment.