Skip to content

Commit

Permalink
feat(bump): add ability to use custom point component
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Dec 13, 2019
1 parent 3d48b94 commit b29fed2
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 29 deletions.
1 change: 1 addition & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function loadStories() {
require('../packages/bar/stories/raceChart.stories')
require('../packages/bar/stories/barCanvas.stories')
require('../packages/bullet/stories/bullet.stories')
require('../packages/bump/stories/bump.stories')
require('../packages/calendar/stories/calendar.stories')
require('../packages/chord/stories/chord.stories')
require('../packages/circle-packing/stories/bubble.stories')
Expand Down
3 changes: 2 additions & 1 deletion packages/bump/src/bump/Bump.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const Bump = props => {
endLabelPadding,
endLabelTextColor,

pointComponent,
pointSize,
activePointSize,
inactivePointSize,
Expand Down Expand Up @@ -149,7 +150,7 @@ const Bump = props => {
))}
</Fragment>
),
points: <Points key="points" points={points} />,
points: <Points key="points" pointComponent={pointComponent} points={points} />,
}

if (startLabel !== false) {
Expand Down
37 changes: 37 additions & 0 deletions packages/bump/src/bump/Point.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* This file is part of the nivo project.
*
* Copyright 2016-present, Raphaël Benitte.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { memo } from 'react'
import PropTypes from 'prop-types'

const pointStyle = { pointerEvents: 'none' }

const Point = ({ x, y, size, color, borderColor, borderWidth }) => {
return (
<circle
cx={x}
cy={y}
r={size / 2}
fill={color}
strokeWidth={borderWidth}
stroke={borderColor}
style={pointStyle}
/>
)
}

Point.propTypes = {
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
size: PropTypes.number.isRequired,
color: PropTypes.string.isRequired,
borderColor: PropTypes.string.isRequired,
borderWidth: PropTypes.number.isRequired,
}

export default memo(Point)
53 changes: 26 additions & 27 deletions packages/bump/src/bump/Points.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,21 @@ import { useMotionConfig } from '@nivo/core'

const pointStyle = { pointerEvents: 'none' }

const Points = ({ points }) => {
const Points = ({ pointComponent, points }) => {
const { animate, springConfig } = useMotionConfig()

if (!animate) {
return points.map(point => (
<circle
key={point.id}
cx={point.x}
cy={point.y}
r={point.style.size / 2}
strokeWidth={point.style.borderWidth}
stroke={point.borderColor}
fill={point.color}
style={pointStyle}
/>
))
return points.map(point => {
return React.createElement(pointComponent, {
key: point.id,
x: point.x,
y: point.y,
size: point.style.size,
color: point.color,
borderColor: point.borderColor,
borderWidth: point.style.borderWidth,
})
})
}

return (
Expand All @@ -39,32 +38,32 @@ const Points = ({ points }) => {
style: {
x: spring(point.x, springConfig),
y: spring(point.y, springConfig),
r: spring(point.style.size / 2, springConfig),
strokeWidth: spring(point.style.borderWidth, springConfig),
size: spring(point.style.size, springConfig),
borderWidth: spring(point.style.borderWidth, springConfig),
},
}))}
>
{interpolated => (
<>
{interpolated.map(({ key, style, data: point }) => (
<circle
key={key}
cx={style.x}
cy={style.y}
r={Math.max(style.r, 0)}
strokeWidth={Math.max(style.strokeWidth, 0)}
stroke={point.borderColor}
fill={point.color}
style={pointStyle}
/>
))}
{interpolated.map(({ key, style, data: point }) => {
return React.createElement(pointComponent, {
key,
x: style.x,
y: point.y,
size: Math.max(style.size, 0),
color: point.color,
borderColor: point.borderColor,
borderWidth: Math.max(style.borderWidth, 0),
})
})}
</>
)}
</TransitionMotion>
)
}

Points.propTypes = {
pointComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).isRequired,
points: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
Expand Down
3 changes: 3 additions & 0 deletions packages/bump/src/bump/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { motionPropTypes } from '@nivo/core'
import { ordinalColorsPropType, inheritedColorPropType } from '@nivo/colors'
import { axisPropType } from '@nivo/axes'
import LineTooltip from './LineTooltip'
import Point from './Point'

const commonPropTypes = {
data: PropTypes.arrayOf(
Expand Down Expand Up @@ -54,6 +55,7 @@ const commonPropTypes = {
endLabelPadding: PropTypes.number.isRequired,
endLabelTextColor: inheritedColorPropType.isRequired,

pointComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).isRequired,
pointSize: PropTypes.oneOfType([PropTypes.number, PropTypes.func]).isRequired,
activePointSize: PropTypes.oneOfType([PropTypes.number, PropTypes.func]).isRequired,
inactivePointSize: PropTypes.oneOfType([PropTypes.number, PropTypes.func]).isRequired,
Expand Down Expand Up @@ -127,6 +129,7 @@ const commonDefaultProps = {

export const BumpDefaultProps = {
...commonDefaultProps,
pointComponent: Point,
animate: true,
motionStiffness: 90,
motionDamping: 15,
Expand Down
5 changes: 5 additions & 0 deletions packages/bump/stories/.eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
globals:
module: true

rules:
react/prop-types: 0
45 changes: 45 additions & 0 deletions packages/bump/stories/bump.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import range from 'lodash/range'
import shuffle from 'lodash/shuffle'
import { Bump } from '../src'

const generateData = () => {
const years = range(2000, 2005)
const ranks = range(1, 7)

const series = ranks.map(rank => {
return {
id: `Serie ${rank}`,
data: [],
}
})

years.forEach(year => {
shuffle(ranks).forEach((rank, i) => {
series[i].data.push({
x: year,
y: rank,
})
})
})

return series
}

const commonProps = {
width: 900,
height: 360,
margin: { top: 40, right: 100, bottom: 40, left: 100 },
titleOffsetX: -80,
data: generateData(),
spacing: 80,
}

const stories = storiesOf('Bump', module)

stories.add('default', () => <Bump {...commonProps} />)

stories.add('Custom points', () => <Bump {...commonProps} />)

stories.add('Missing data', () => <Bump {...commonProps} />)
6 changes: 5 additions & 1 deletion website/src/data/components/bump/meta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ Bump:
tags:
- svg
- isomorphic
stories: []
stories:
- label: Custom points
link: bump--custom-points
- label: Missing data
link: bump--missing-data
description: |
The Bump chart can be used to show the ranking of several series
over time. It is quite similar to [line](self:/line/) charts,
Expand Down

0 comments on commit b29fed2

Please sign in to comment.