Skip to content

Commit

Permalink
feat(arcs): add the ability to pass custom arc label/arc link label c…
Browse files Browse the repository at this point in the history
…omponents
  • Loading branch information
plouc committed Dec 18, 2020
1 parent 547b635 commit 8fb574c
Show file tree
Hide file tree
Showing 12 changed files with 229 additions and 102 deletions.
4 changes: 3 additions & 1 deletion packages/arcs/src/ArcsLayer.tsx
Expand Up @@ -6,7 +6,9 @@ import { useArcsTransition } from './useArcsTransition'
import { ArcTransitionMode } from './arcTransitionMode'
import { ArcMouseHandler, ArcShape, ArcShapeProps } from './ArcShape'

type ArcComponent<Datum extends DatumWithArcAndColor> = (props: ArcShapeProps<Datum>) => JSX.Element
export type ArcComponent<Datum extends DatumWithArcAndColor> = (
props: ArcShapeProps<Datum>
) => JSX.Element

interface ArcsLayerProps<Datum extends DatumWithArcAndColor> {
center: [number, number]
Expand Down
40 changes: 40 additions & 0 deletions packages/arcs/src/arc_labels/ArcLabel.tsx
@@ -0,0 +1,40 @@
import React, { CSSProperties } from 'react'
import { SpringValue, Interpolation, animated } from 'react-spring'
import { useTheme } from '@nivo/core'
import { DatumWithArcAndColor } from '../types'

const staticStyle: CSSProperties = {
pointerEvents: 'none',
}

export interface ArcLabelProps<Datum extends DatumWithArcAndColor> {
datum: Datum
label: string
style: {
progress: SpringValue<number>
transform: Interpolation<string>
textColor: string
}
}

export const ArcLabel = <Datum extends DatumWithArcAndColor>({
label,
style,
}: ArcLabelProps<Datum>) => {
const theme = useTheme()

return (
<animated.g transform={style.transform} opacity={style.progress} style={staticStyle}>
<animated.text
textAnchor="middle"
dominantBaseline="central"
style={{
...theme.labels.text,
fill: style.textColor,
}}
>
{label}
</animated.text>
</animated.g>
)
}
53 changes: 24 additions & 29 deletions packages/arcs/src/arc_labels/ArcLabelsLayer.tsx
@@ -1,5 +1,4 @@
import React, { useMemo, CSSProperties } from 'react'
import { animated } from 'react-spring'
import React, { useMemo } from 'react'
import {
// @ts-ignore
getLabelGenerator,
Expand All @@ -11,20 +10,22 @@ import { useArcCentersTransition } from '../centers'
import { ArcTransitionMode } from '../arcTransitionMode'
import { DatumWithArcAndColor } from '../types'
import { ArcLabelsProps } from './props'
import { ArcLabel, ArcLabelProps } from './ArcLabel'

const sliceStyle: CSSProperties = {
pointerEvents: 'none',
}
export type ArcLabelComponent<Datum extends DatumWithArcAndColor> = (
props: ArcLabelProps<Datum>
) => JSX.Element

interface ArcLabelsLayerProps<Datum extends DatumWithArcAndColor> {
center: [number, number]
data: Datum[]
// CompletePieSvgProps<RawDatum>['arcLabel']
// @todo add proper label accessor type
label: any
radiusOffset: ArcLabelsProps<Datum, Datum>['arcLabelsRadiusOffset']
skipAngle: ArcLabelsProps<Datum, Datum>['arcLabelsSkipAngle']
textColor: ArcLabelsProps<Datum, Datum>['arcLabelsTextColor']
radiusOffset: ArcLabelsProps<Datum>['arcLabelsRadiusOffset']
skipAngle: ArcLabelsProps<Datum>['arcLabelsSkipAngle']
textColor: ArcLabelsProps<Datum>['arcLabelsTextColor']
transitionMode: ArcTransitionMode
component?: ArcLabelComponent<Datum>
}

export const ArcLabelsLayer = <Datum extends DatumWithArcAndColor>({
Expand All @@ -35,6 +36,7 @@ export const ArcLabelsLayer = <Datum extends DatumWithArcAndColor>({
radiusOffset,
skipAngle,
textColor,
component = ArcLabel,
}: ArcLabelsLayerProps<Datum>) => {
const getLabel = useMemo(() => getLabelGenerator(labelAccessor), [labelAccessor])
const theme = useTheme()
Expand All @@ -57,33 +59,26 @@ export const ArcLabelsLayer = <Datum extends DatumWithArcAndColor>({
transitionMode
)

const Label: ArcLabelComponent<Datum> = component

return (
<g transform={`translate(${center[0]},${center[1]})`}>
{transition((transitionProps, datum) => {
return (
<animated.g
key={datum.id}
transform={interpolate(
return React.createElement(Label, {
key: datum.id,
datum,
label: getLabel(datum),
style: {
...transitionProps,
transform: interpolate(
transitionProps.startAngle,
transitionProps.endAngle,
transitionProps.innerRadius,
transitionProps.outerRadius
)}
opacity={transitionProps.progress}
style={sliceStyle}
>
<animated.text
textAnchor="middle"
dominantBaseline="central"
style={{
...theme.labels.text,
fill: getTextColor(datum),
}}
>
{getLabel(datum)}
</animated.text>
</animated.g>
)
),
textColor: getTextColor(datum),
},
})
})}
</g>
)
Expand Down
9 changes: 6 additions & 3 deletions packages/arcs/src/arc_labels/props.ts
@@ -1,10 +1,13 @@
import { InheritedColorConfig } from '@nivo/colors'
import { ArcLabelComponent } from './ArcLabelsLayer'
import { DatumWithArcAndColor } from '../types'

// @ts-ignore
export interface ArcLabelsProps<RawDatum, Datum> {
// string | LabelAccessorFunction<RawDatum>
export interface ArcLabelsProps<Datum extends DatumWithArcAndColor> {
// @todo fix label accessor
// string | LabelAccessorFunction<Datum['data']>
arcLabel: any
arcLabelsRadiusOffset: number
arcLabelsSkipAngle: number
arcLabelsTextColor: InheritedColorConfig<Datum>
component: ArcLabelComponent<Datum>
}
27 changes: 27 additions & 0 deletions packages/arcs/src/arc_link_labels/ArcLinkLabel.tsx
@@ -0,0 +1,27 @@
import React from 'react'
import { SpringValue, Interpolation, animated } from 'react-spring'
import { DatumWithArcAndColor } from '../types'

export interface ArcLinkLabelProps<Datum extends DatumWithArcAndColor> {
datum: Datum
style: {
linkColor: SpringValue<string>
thickness: number
opacity: SpringValue<number>
path: Interpolation<string>
}
}

export const ArcLinkLabel = <Datum extends DatumWithArcAndColor>({
style,
}: ArcLinkLabelProps<Datum>) => {
return (
<animated.path
fill="none"
stroke={style.linkColor}
strokeWidth={style.thickness}
opacity={style.opacity}
d={style.path}
/>
)
}
51 changes: 29 additions & 22 deletions packages/arcs/src/arc_link_labels/ArcLinkLabelsLayer.tsx
@@ -1,21 +1,26 @@
import React from 'react'
import { animated } from 'react-spring'
import { useArcLinkLabelsTransition } from './useArcLinkLabelsTransition'
import { DatumWithArcAndColor } from '../types'
import { useArcLinkLabelsTransition } from './useArcLinkLabelsTransition'
import { ArcLinkLabelsProps } from './props'
import { ArcLinkLabel, ArcLinkLabelProps } from './ArcLinkLabel'

export type ArcLinkLabelComponent<Datum extends DatumWithArcAndColor> = (
props: ArcLinkLabelProps<Datum>
) => JSX.Element

interface ArcLinkLabelsLayerProps<Datum extends DatumWithArcAndColor> {
center: [number, number]
data: Datum[]
label: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabel']
skipAngle: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsSkipAngle']
offset: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsOffset']
diagonalLength: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsDiagonalLength']
straightLength: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsStraightLength']
strokeWidth: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsThickness']
textOffset: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsTextOffset']
textColor: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsTextColor']
linkColor: ArcLinkLabelsProps<Datum, Datum>['arcLinkLabelsColor']
label: ArcLinkLabelsProps<Datum>['arcLinkLabel']
skipAngle: ArcLinkLabelsProps<Datum>['arcLinkLabelsSkipAngle']
offset: ArcLinkLabelsProps<Datum>['arcLinkLabelsOffset']
diagonalLength: ArcLinkLabelsProps<Datum>['arcLinkLabelsDiagonalLength']
straightLength: ArcLinkLabelsProps<Datum>['arcLinkLabelsStraightLength']
strokeWidth: ArcLinkLabelsProps<Datum>['arcLinkLabelsThickness']
textOffset: ArcLinkLabelsProps<Datum>['arcLinkLabelsTextOffset']
textColor: ArcLinkLabelsProps<Datum>['arcLinkLabelsTextColor']
linkColor: ArcLinkLabelsProps<Datum>['arcLinkLabelsColor']
component?: ArcLinkLabelComponent<Datum>
}

export const ArcLinkLabelsLayer = <Datum extends DatumWithArcAndColor>({
Expand All @@ -30,6 +35,7 @@ export const ArcLinkLabelsLayer = <Datum extends DatumWithArcAndColor>({
textOffset,
textColor,
linkColor,
component = ArcLinkLabel,
}: ArcLinkLabelsLayerProps<Datum>) => {
const { transition, interpolateLink } = useArcLinkLabelsTransition<Datum>({
data,
Expand All @@ -43,27 +49,28 @@ export const ArcLinkLabelsLayer = <Datum extends DatumWithArcAndColor>({
textColor,
})

const Label: ArcLinkLabelComponent<Datum> = component

return (
<g transform={`translate(${center[0]},${center[1]})`}>
{transition((transitionProps, datum) => {
return (
<animated.path
key={datum.id}
fill="none"
stroke={transitionProps.linkColor}
strokeWidth={strokeWidth}
opacity={transitionProps.opacity}
d={interpolateLink(
return React.createElement(Label, {
key: datum.id,
datum,
style: {
...transitionProps,
thickness: strokeWidth,
path: interpolateLink(
transitionProps.startAngle,
transitionProps.endAngle,
transitionProps.innerRadius,
transitionProps.outerRadius,
transitionProps.offset,
transitionProps.diagonalLength,
transitionProps.straightLength
)}
/>
)
),
},
})
})}
</g>
)
Expand Down
8 changes: 5 additions & 3 deletions packages/arcs/src/arc_link_labels/props.ts
@@ -1,8 +1,9 @@
import { InheritedColorConfig } from '@nivo/colors'
import { ArcLinkLabelComponent } from './ArcLinkLabelsLayer'
import { DatumWithArcAndColor } from '../types'

// @ts-ignore
export interface ArcLinkLabelsProps<RawDatum, Datum> {
// string | LabelAccessorFunction<RawDatum>
export interface ArcLinkLabelsProps<Datum extends DatumWithArcAndColor> {
// string | LabelAccessorFunction<Datum['data']>
arcLinkLabel: any
arcLinkLabelsSkipAngle: number
arcLinkLabelsTextOffset: number
Expand All @@ -12,4 +13,5 @@ export interface ArcLinkLabelsProps<RawDatum, Datum> {
arcLinkLabelsStraightLength: number
arcLinkLabelsThickness: number
arcLinkLabelsColor: InheritedColorConfig<Datum>
component: ArcLinkLabelComponent<Datum>
}
4 changes: 4 additions & 0 deletions packages/pie/src/Pie.tsx
Expand Up @@ -48,6 +48,7 @@ const InnerPie = <RawDatum,>({
arcLabelsSkipAngle = defaultProps.arcLabelsSkipAngle,
arcLabelsTextColor = defaultProps.arcLabelsTextColor,
arcLabelsRadiusOffset = defaultProps.arcLabelsRadiusOffset,
arcLabelComponent,

// arc link labels
enableArcLinkLabels = defaultProps.enableArcLinkLabels,
Expand All @@ -60,6 +61,7 @@ const InnerPie = <RawDatum,>({
arcLinkLabelsTextOffset = defaultProps.arcLinkLabelsTextOffset,
arcLinkLabelsTextColor = defaultProps.arcLinkLabelsTextColor,
arcLinkLabelsColor = defaultProps.arcLinkLabelsColor,
arcLinkLabelComponent,

// styling
defs = defaultProps.defs,
Expand Down Expand Up @@ -139,6 +141,7 @@ const InnerPie = <RawDatum,>({
textOffset={arcLinkLabelsTextOffset}
textColor={arcLinkLabelsTextColor}
linkColor={arcLinkLabelsColor}
component={arcLinkLabelComponent}
/>
)
}
Expand Down Expand Up @@ -175,6 +178,7 @@ const InnerPie = <RawDatum,>({
skipAngle={arcLabelsSkipAngle}
textColor={arcLabelsTextColor}
transitionMode={transitionMode}
component={arcLabelComponent}
/>
)
}
Expand Down
13 changes: 9 additions & 4 deletions packages/pie/src/types.ts
Expand Up @@ -111,8 +111,8 @@ export type CommonPieProps<RawDatum> = {
legends: LegendProps[]

role: string
} & Partial<ArcLabelsProps<RawDatum, ComputedDatum<RawDatum>>> &
Partial<ArcLinkLabelsProps<RawDatum, ComputedDatum<RawDatum>>>
} & Partial<ArcLabelsProps<ComputedDatum<RawDatum>>> &
Partial<ArcLinkLabelsProps<ComputedDatum<RawDatum>>>

export type PieHandlers<RawDatum, ElementType> = {
onClick?: MouseEventHandler<RawDatum, ElementType>
Expand All @@ -121,6 +121,11 @@ export type PieHandlers<RawDatum, ElementType> = {
onMouseLeave?: MouseEventHandler<RawDatum, ElementType>
}

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

export type PieSvgProps<RawDatum> = DataProps<RawDatum> &
Dimensions &
Partial<CommonPieProps<RawDatum>> &
Expand All @@ -130,7 +135,7 @@ export type PieSvgProps<RawDatum> = DataProps<RawDatum> &
animate?: boolean
motionConfig?: ModernMotionProps['motionConfig']
transitionMode?: ArcTransitionMode
}
} & PieSvgCustomComponents<RawDatum>

export type CompletePieSvgProps<RawDatum> = DataProps<RawDatum> &
Dimensions &
Expand All @@ -141,7 +146,7 @@ export type CompletePieSvgProps<RawDatum> = DataProps<RawDatum> &
animate: boolean
motionConfig: ModernMotionProps['motionConfig']
transitionMode: ArcTransitionMode
}
} & PieSvgCustomComponents<RawDatum>

export type PieCanvasProps<RawDatum> = DataProps<RawDatum> &
Dimensions &
Expand Down

0 comments on commit 8fb574c

Please sign in to comment.