Skip to content

Commit

Permalink
feat(bump): improve AreaBump typings and add support for series extra…
Browse files Browse the repository at this point in the history
… properties
  • Loading branch information
plouc committed Dec 29, 2021
1 parent 1afc0a4 commit a68d98d
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 222 deletions.
41 changes: 21 additions & 20 deletions packages/bump/src/area-bump/Area.tsx
Expand Up @@ -6,22 +6,23 @@ import {
AreaBumpCommonProps,
AreaBumpComputedSerie,
AreaBumpDatum,
AreaBumpSerieExtraProps,
} from './types'

interface AreaProps<D extends AreaBumpDatum> {
serie: AreaBumpComputedSerie<D>
interface AreaProps<Datum extends AreaBumpDatum, ExtraProps extends AreaBumpSerieExtraProps> {
serie: AreaBumpComputedSerie<Datum, ExtraProps>
areaGenerator: AreaBumpAreaGenerator
blendMode: AreaBumpCommonProps<D>['blendMode']
isInteractive: AreaBumpCommonProps<D>['isInteractive']
onMouseEnter?: AreaBumpCommonProps<D>['onMouseEnter']
onMouseMove?: AreaBumpCommonProps<D>['onMouseMove']
onMouseLeave?: AreaBumpCommonProps<D>['onMouseLeave']
onClick?: AreaBumpCommonProps<D>['onClick']
setCurrentSerie: any
tooltip: AreaBumpCommonProps<D>['tooltip']
blendMode: AreaBumpCommonProps<Datum, ExtraProps>['blendMode']
isInteractive: AreaBumpCommonProps<Datum, ExtraProps>['isInteractive']
onMouseEnter?: AreaBumpCommonProps<Datum, ExtraProps>['onMouseEnter']
onMouseMove?: AreaBumpCommonProps<Datum, ExtraProps>['onMouseMove']
onMouseLeave?: AreaBumpCommonProps<Datum, ExtraProps>['onMouseLeave']
onClick?: AreaBumpCommonProps<Datum, ExtraProps>['onClick']
setActiveSerieIds: (serieIds: string[]) => void
tooltip: AreaBumpCommonProps<Datum, ExtraProps>['tooltip']
}

export const Area = <D extends AreaBumpDatum>({
export const Area = <Datum extends AreaBumpDatum, ExtraProps extends AreaBumpSerieExtraProps>({
serie,
areaGenerator,
blendMode,
Expand All @@ -30,33 +31,33 @@ export const Area = <D extends AreaBumpDatum>({
onMouseMove,
onMouseLeave,
onClick,
setCurrentSerie,
setActiveSerieIds,
tooltip,
}: AreaProps<D>) => {
const handlers = useAreaBumpSerieHandlers<D>({
}: AreaProps<Datum, ExtraProps>) => {
const handlers = useAreaBumpSerieHandlers<Datum, ExtraProps>({
serie,
isInteractive,
onMouseEnter,
onMouseMove,
onMouseLeave,
onClick,
setCurrent: setCurrentSerie,
setActiveSerieIds,
tooltip,
})

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

const animatedPath = useAnimatedPath(areaGenerator(serie.areaPoints)!)
const animatedPath = useAnimatedPath(areaGenerator(serie.areaPoints) || '')
const animatedProps = useSpring<{
color: string
fillOpacity: number
stroke: string
strokeOpacity: number
}>({
color: serie.color,
fillOpacity: serie.style.fillOpacity,
stroke: serie.style.borderColor,
strokeOpacity: serie.style.borderOpacity,
fillOpacity: serie.fillOpacity,
stroke: serie.borderColor,
strokeOpacity: serie.borderOpacity,
config: springConfig,
immediate: !animate,
})
Expand All @@ -67,7 +68,7 @@ export const Area = <D extends AreaBumpDatum>({
fill={serie.fill ? serie.fill : animatedProps.color}
fillOpacity={animatedProps.fillOpacity}
stroke={animatedProps.stroke}
strokeWidth={serie.style.borderWidth}
strokeWidth={serie.borderWidth}
strokeOpacity={animatedProps.strokeOpacity}
style={{ mixBlendMode: blendMode }}
onMouseEnter={handlers.onMouseEnter}
Expand Down
77 changes: 51 additions & 26 deletions packages/bump/src/area-bump/AreaBump.tsx
@@ -1,4 +1,4 @@
import { useState, Fragment, useMemo, ReactNode, createElement } from 'react'
import { Fragment, useMemo, ReactNode, createElement } from 'react'
import {
// @ts-ignore
bindDefs,
Expand All @@ -16,71 +16,93 @@ import {
DefaultAreaBumpDatum,
AreaBumpLayerId,
AreaBumpCustomLayerProps,
AreaBumpSerieExtraProps,
} from './types'
import { areaBumpSvgDefaultProps } from './defaults'

type InnerAreaBumpProps<D extends AreaBumpDatum> = Omit<
AreaBumpSvgProps<D>,
type InnerAreaBumpProps<
Datum extends AreaBumpDatum,
ExtraProps extends AreaBumpSerieExtraProps
> = Omit<
AreaBumpSvgProps<Datum, ExtraProps>,
'animate' | 'motionConfig' | 'renderWrapper' | 'theme'
>

const InnerAreaBump = <D extends AreaBumpDatum>({
const InnerAreaBump = <Datum extends AreaBumpDatum, ExtraProps extends AreaBumpSerieExtraProps>({
data,
align = areaBumpSvgDefaultProps.align,

width,
height,
margin: partialMargin,

layers = areaBumpSvgDefaultProps.layers,
layers = areaBumpSvgDefaultProps.layers as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['layers']
>,

interpolation = areaBumpSvgDefaultProps.interpolation,
spacing = areaBumpSvgDefaultProps.spacing,
xPadding = areaBumpSvgDefaultProps.xPadding,

colors = areaBumpSvgDefaultProps.colors,
colors = areaBumpSvgDefaultProps.colors as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['colors']
>,
blendMode = areaBumpSvgDefaultProps.blendMode,
fillOpacity = areaBumpSvgDefaultProps.fillOpacity,
activeFillOpacity = areaBumpSvgDefaultProps.activeFillOpacity,
inactiveFillOpacity = areaBumpSvgDefaultProps.inactiveFillOpacity,
defs = areaBumpSvgDefaultProps.defs,
fill = areaBumpSvgDefaultProps.fill,
fill = areaBumpSvgDefaultProps.fill as NonNullable<AreaBumpSvgProps<Datum, ExtraProps>['fill']>,
borderWidth = areaBumpSvgDefaultProps.borderWidth,
activeBorderWidth = areaBumpSvgDefaultProps.activeBorderWidth,
inactiveBorderWidth = areaBumpSvgDefaultProps.inactiveBorderWidth,
borderColor = areaBumpSvgDefaultProps.borderColor,
borderColor = areaBumpSvgDefaultProps.borderColor as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['borderColor']
>,
borderOpacity = areaBumpSvgDefaultProps.borderOpacity,
activeBorderOpacity = areaBumpSvgDefaultProps.activeBorderOpacity,
inactiveBorderOpacity = areaBumpSvgDefaultProps.inactiveBorderOpacity,

startLabel = areaBumpSvgDefaultProps.startLabel,
startLabel = areaBumpSvgDefaultProps.startLabel as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['startLabel']
>,
startLabelPadding = areaBumpSvgDefaultProps.startLabelPadding,
startLabelTextColor = areaBumpSvgDefaultProps.startLabelTextColor,
endLabel = areaBumpSvgDefaultProps.endLabel,
startLabelTextColor = areaBumpSvgDefaultProps.startLabelTextColor as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['startLabelTextColor']
>,
endLabel = areaBumpSvgDefaultProps.endLabel as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['endLabel']
>,
endLabelPadding = areaBumpSvgDefaultProps.endLabelPadding,
endLabelTextColor = areaBumpSvgDefaultProps.endLabelTextColor,
endLabelTextColor = areaBumpSvgDefaultProps.endLabelTextColor as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['endLabelTextColor']
>,

enableGridX = areaBumpSvgDefaultProps.enableGridX,
axisTop = areaBumpSvgDefaultProps.axisTop,
axisBottom = areaBumpSvgDefaultProps.axisBottom,

isInteractive = areaBumpSvgDefaultProps.isInteractive,
defaultActiveSerieIds = areaBumpSvgDefaultProps.defaultActiveSerieIds,
onMouseEnter,
onMouseMove,
onMouseLeave,
onClick,
tooltip = areaBumpSvgDefaultProps.tooltip,
tooltip = areaBumpSvgDefaultProps.tooltip as NonNullable<
AreaBumpSvgProps<Datum, ExtraProps>['tooltip']
>,
role = areaBumpSvgDefaultProps.role,
}: InnerAreaBumpProps<D>) => {
const [currentSerie, setCurrentSerie] = useState(null)

}: InnerAreaBumpProps<Datum, ExtraProps>) => {
const { margin, innerWidth, innerHeight, outerWidth, outerHeight } = useDimensions(
width,
height,
partialMargin
)

const { series, xScale, heightScale, areaGenerator } = useAreaBump<D>({
const { series, xScale, heightScale, areaGenerator, setActiveSerieIds } = useAreaBump<
Datum,
ExtraProps
>({
data,
width: innerWidth,
height: innerHeight,
Expand All @@ -100,7 +122,7 @@ const InnerAreaBump = <D extends AreaBumpDatum>({
activeBorderOpacity,
inactiveBorderOpacity,
isInteractive,
current: currentSerie,
defaultActiveSerieIds,
})

const boundDefs = useMemo(
Expand Down Expand Up @@ -137,13 +159,13 @@ const InnerAreaBump = <D extends AreaBumpDatum>({
layerById.areas = (
<Fragment key="areas">
{series.map(serie => (
<Area<D>
<Area<Datum, ExtraProps>
key={serie.id}
areaGenerator={areaGenerator}
serie={serie}
blendMode={blendMode}
isInteractive={isInteractive}
setCurrentSerie={setCurrentSerie}
setActiveSerieIds={setActiveSerieIds}
onMouseEnter={onMouseEnter}
onMouseMove={onMouseMove}
onMouseLeave={onMouseLeave}
Expand All @@ -159,7 +181,7 @@ const InnerAreaBump = <D extends AreaBumpDatum>({
layerById.labels = (
<Fragment key="labels">
{startLabel !== false && (
<AreasLabels<D>
<AreasLabels<Datum, ExtraProps>
label={startLabel}
series={series}
position="start"
Expand All @@ -168,7 +190,7 @@ const InnerAreaBump = <D extends AreaBumpDatum>({
/>
)}
{endLabel !== false && (
<AreasLabels<D>
<AreasLabels<Datum, ExtraProps>
label={endLabel}
series={series}
position="end"
Expand All @@ -180,7 +202,7 @@ const InnerAreaBump = <D extends AreaBumpDatum>({
)
}

const customLayerProps: AreaBumpCustomLayerProps<D> = useMemo(
const customLayerProps: AreaBumpCustomLayerProps<Datum, ExtraProps> = useMemo(
() => ({
innerWidth,
innerHeight,
Expand Down Expand Up @@ -212,14 +234,17 @@ const InnerAreaBump = <D extends AreaBumpDatum>({
)
}

export const AreaBump = <D extends AreaBumpDatum = DefaultAreaBumpDatum>({
export const AreaBump = <
Datum extends AreaBumpDatum = DefaultAreaBumpDatum,
ExtraProps extends AreaBumpSerieExtraProps = Record<string, unknown>
>({
isInteractive = areaBumpSvgDefaultProps.isInteractive,
animate = areaBumpSvgDefaultProps.animate,
motionConfig = areaBumpSvgDefaultProps.motionConfig,
theme,
renderWrapper,
...otherProps
}: AreaBumpSvgProps<D>) => (
}: AreaBumpSvgProps<Datum, ExtraProps>) => (
<Container
{...{
animate,
Expand All @@ -229,6 +254,6 @@ export const AreaBump = <D extends AreaBumpDatum = DefaultAreaBumpDatum>({
theme,
}}
>
<InnerAreaBump<D> isInteractive={isInteractive} {...otherProps} />
<InnerAreaBump<Datum, ExtraProps> isInteractive={isInteractive} {...otherProps} />
</Container>
)
20 changes: 14 additions & 6 deletions packages/bump/src/area-bump/AreaTooltip.tsx
@@ -1,10 +1,18 @@
import { BasicTooltip } from '@nivo/tooltip'
import { AreaBumpDatum, AreaBumpComputedSerie } from './types'
import { AreaBumpDatum, AreaBumpComputedSerie, AreaBumpSerieExtraProps } from './types'

interface AreaTooltipProps<D extends AreaBumpDatum> {
serie: AreaBumpComputedSerie<D>
interface AreaTooltipProps<
Datum extends AreaBumpDatum,
ExtraProps extends AreaBumpSerieExtraProps
> {
serie: AreaBumpComputedSerie<Datum, ExtraProps>
}

export const AreaTooltip = <D extends AreaBumpDatum>({ serie }: AreaTooltipProps<D>) => {
return <BasicTooltip id={serie.id} enableChip={true} color={serie.color} />
}
export const AreaTooltip = <
Datum extends AreaBumpDatum,
ExtraProps extends AreaBumpSerieExtraProps
>({
serie,
}: AreaTooltipProps<Datum, ExtraProps>) => (
<BasicTooltip id={serie.id} enableChip={true} color={serie.color} />
)
24 changes: 16 additions & 8 deletions packages/bump/src/area-bump/AreasLabels.tsx
@@ -1,28 +1,36 @@
import { useSprings, animated } from '@react-spring/web'
import { useTheme, useMotionConfig } from '@nivo/core'
import { InheritedColorConfig } from '@nivo/colors'
import { AreaBumpComputedSerie, AreaBumpDatum, AreaBumpLabel } from './types'
import {
AreaBumpComputedSerie,
AreaBumpDatum,
AreaBumpLabel,
AreaBumpSerieExtraProps,
} from './types'
import { useAreaBumpSeriesLabels } from './hooks'

interface AreaLabelsProps<D extends AreaBumpDatum> {
label: Exclude<AreaBumpLabel<D>, false>
series: AreaBumpComputedSerie<D>[]
interface AreaLabelsProps<Datum extends AreaBumpDatum, ExtraProps extends AreaBumpSerieExtraProps> {
label: Exclude<AreaBumpLabel<Datum, ExtraProps>, false>
series: AreaBumpComputedSerie<Datum, ExtraProps>[]
position: 'start' | 'end'
padding: number
color: InheritedColorConfig<AreaBumpComputedSerie<D>>
color: InheritedColorConfig<AreaBumpComputedSerie<Datum, ExtraProps>>
}

export const AreasLabels = <D extends AreaBumpDatum>({
export const AreasLabels = <
Datum extends AreaBumpDatum,
ExtraProps extends AreaBumpSerieExtraProps
>({
label,
series,
position,
padding,
color,
}: AreaLabelsProps<D>) => {
}: AreaLabelsProps<Datum, ExtraProps>) => {
const theme = useTheme()
const { animate, config: springConfig } = useMotionConfig()

const labels = useAreaBumpSeriesLabels<D>({
const labels = useAreaBumpSeriesLabels<Datum, ExtraProps>({
label,
series,
position,
Expand Down
18 changes: 14 additions & 4 deletions packages/bump/src/area-bump/ResponsiveAreaBump.tsx
@@ -1,11 +1,21 @@
import { ResponsiveWrapper } from '@nivo/core'
import { AreaBumpDatum, AreaBumpSvgProps, DefaultAreaBumpDatum } from './types'
import {
AreaBumpDatum,
AreaBumpSerieExtraProps,
AreaBumpSvgProps,
DefaultAreaBumpDatum,
} from './types'
import { AreaBump } from './AreaBump'

export const ResponsiveAreaBump = <D extends AreaBumpDatum = DefaultAreaBumpDatum>(
props: Omit<AreaBumpSvgProps<D>, 'width' | 'height'>
export const ResponsiveAreaBump = <
Datum extends AreaBumpDatum = DefaultAreaBumpDatum,
ExtraProps extends AreaBumpSerieExtraProps = Record<string, unknown>
>(
props: Omit<AreaBumpSvgProps<Datum, ExtraProps>, 'width' | 'height'>
) => (
<ResponsiveWrapper>
{({ width, height }) => <AreaBump<D> width={width} height={height} {...props} />}
{({ width, height }) => (
<AreaBump<Datum, ExtraProps> width={width} height={height} {...props} />
)}
</ResponsiveWrapper>
)

0 comments on commit a68d98d

Please sign in to comment.