Skip to content

Commit

Permalink
feat(pie): add support for onClick event
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte authored and Raphaël Benitte committed May 18, 2018
1 parent 129572e commit b171044
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 35 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[*.js]
indent_style = space
indent_size = 4
max_line_length = 100
47 changes: 18 additions & 29 deletions packages/nivo-pie/src/Pie.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
*/
import React from 'react'
import { pie as d3Pie, arc as d3Arc } from 'd3-shape'
import { Motion, TransitionMotion, spring } from 'react-motion'
import { Motion, spring } from 'react-motion'
import { getInheritedColorGenerator } from '@nivo/core'
import { getLabelGenerator } from '@nivo/core'
import { degreesToRadians, radiansToDegrees } from '@nivo/core'
import { bindDefs } from '@nivo/core'
import { Container, SvgWrapper } from '@nivo/core'
import { BasicTooltip } from '@nivo/core'
import { BoxLegendSvg } from '@nivo/legends'
import PieSlice from './PieSlice'
import PieRadialLabels from './PieRadialLabels'
import PieSlicesLabels from './PieSlicesLabels'
import { PiePropTypes } from './props'
Expand Down Expand Up @@ -71,6 +71,7 @@ const Pie = ({

// interactivity
isInteractive,
onClick,
tooltipFormat,

legends,
Expand Down Expand Up @@ -169,33 +170,21 @@ const Pie = ({
interpolatingStyle.centerY
})`}
>
{arcsData.map(d => {
const handleTooltip = e =>
showTooltip(
<BasicTooltip
id={d.data.label}
value={d.data.value}
enableChip={true}
color={d.data.color}
theme={theme}
format={tooltipFormat}
/>,
e
)

return (
<path
key={d.data.id}
d={interpolatedArc(d)}
fill={d.data.fill ? d.data.fill : d.data.color}
strokeWidth={borderWidth}
stroke={borderColor(d.data)}
onMouseEnter={handleTooltip}
onMouseMove={handleTooltip}
onMouseLeave={hideTooltip}
/>
)
})}
{arcsData.map(d => (
<PieSlice
key={d.data.id}
data={d.data}
path={interpolatedArc(d)}
color={d.data.color}
fill={d.data.fill ? d.data.fill : d.data.color}
borderWidth={borderWidth}
borderColor={borderColor(d.data)}
showTooltip={showTooltip}
hideTooltip={hideTooltip}
theme={theme}
onClick={onClick}
/>
))}
{enableSlicesLabels && (
<PieSlicesLabels
data={arcsData}
Expand Down
89 changes: 89 additions & 0 deletions packages/nivo-pie/src/PieSlice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 from 'react'
import PropTypes from 'prop-types'
import compose from 'recompose/compose'
import withPropsOnChange from 'recompose/withPropsOnChange'
import pure from 'recompose/pure'
import { BasicTooltip } from '@nivo/core'

const PieSlice = ({
data,

path,
color,
fill,
borderWidth,
borderColor,

showTooltip,
hideTooltip,
onClick,
tooltipFormat,

theme,
}) => {
const handleTooltip = e =>
showTooltip(
<BasicTooltip
id={data.label}
value={data.value}
enableChip={true}
color={color}
theme={theme}
format={tooltipFormat}
/>,
e
)

return (
<path
key={data.id}
d={path}
fill={fill}
strokeWidth={borderWidth}
stroke={borderColor}
onMouseEnter={handleTooltip}
onMouseMove={handleTooltip}
onMouseLeave={hideTooltip}
onClick={onClick}
/>
)
}

PieSlice.propTypes = {
data: PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
value: PropTypes.number.isRequired,
}).isRequired,

path: PropTypes.string.isRequired,
color: PropTypes.string.isRequired,
fill: PropTypes.string.isRequired,
borderWidth: PropTypes.number.isRequired,
borderColor: PropTypes.string.isRequired,

tooltipFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
showTooltip: PropTypes.func.isRequired,
hideTooltip: PropTypes.func.isRequired,
onClick: PropTypes.func,

theme: PropTypes.shape({
tooltip: PropTypes.shape({}).isRequired,
}).isRequired,
}

const enhance = compose(
withPropsOnChange(['data', 'onClick'], ({ data, onClick }) => ({
onClick: event => onClick(data, event),
})),
pure
)

export default enhance(PieSlice)
3 changes: 3 additions & 0 deletions packages/nivo-pie/src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* file that was distributed with this source code.
*/
import PropTypes from 'prop-types'
import { noop } from '@nivo/core'
import { LegendPropShape } from '@nivo/legends'

export const PiePropTypes = {
Expand Down Expand Up @@ -60,6 +61,7 @@ export const PiePropTypes = {

// interactivity
isInteractive: PropTypes.bool,
onClick: PropTypes.func.isRequired,
tooltipFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),

legends: PropTypes.arrayOf(PropTypes.shape(LegendPropShape)).isRequired,
Expand Down Expand Up @@ -92,6 +94,7 @@ export const PieDefaultProps = {

// interactivity
isInteractive: true,
onClick: noop,

legends: [],
}
11 changes: 10 additions & 1 deletion website/src/components/charts/pie/Pie.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export default class Pie extends Component {
this.setState({ settings })
}

handleNodeClick = (node, event) => {
alert(`${node.label}: ${node.value}\nclicked at x: ${event.clientX}, y: ${event.clientY}`)
}

render() {
const { data, diceRoll } = this.props
const { settings } = this.state
Expand Down Expand Up @@ -115,7 +119,12 @@ export default class Pie extends Component {
{description}
</MediaQuery>
<ChartTabs chartClass="pie" code={code} data={data} diceRoll={diceRoll}>
<ResponsivePie data={data} {...mappedSettings} theme={nivoTheme} />
<ResponsivePie
data={data}
{...mappedSettings}
theme={nivoTheme}
onClick={this.handleNodeClick}
/>
</ChartTabs>
<PieControls
scope="Pie"
Expand Down
27 changes: 23 additions & 4 deletions website/src/components/charts/pie/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@ export default [
controlType: 'switch',
controlGroup: 'Base',
},
/*##################################################################################################################
/*
————————————————————————————————————————————————————————————————————————————
Styling
##################################################################################################################*/
————————————————————————————————————————————————————————————————————————————
*/
{
key: 'colors',
description: 'Defines color range.',
Expand Down Expand Up @@ -362,6 +364,13 @@ export default [
withCustomColor: true,
},
},
/*
————————————————————————————————————————————————————————————————————————————
Interactivity
————————————————————————————————————————————————————————————————————————————
*/
{
key: 'isInteractive',
scopes: ['Pie'],
Expand All @@ -372,11 +381,21 @@ export default [
controlType: 'switch',
controlGroup: 'Interactivity',
},
/*##################################################################################################################
{
key: 'onClick',
scopes: ['Pie'],
description:
'onClick handler for pie slices, it receives clicked slice data and mouse event.',
type: '{Function}',
required: false,
},
/*
————————————————————————————————————————————————————————————————————————————
Motion
##################################################################################################################*/
————————————————————————————————————————————————————————————————————————————
*/
{
key: 'animate',
scopes: ['Pie'],
Expand Down
11 changes: 10 additions & 1 deletion website/src/lib/generateChartCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,18 @@ const generate = (

const imports = [name, ...children.map(([c]) => c)].map(i => `import { ${i} } from '${pkg}'`)

let responsiveWarning = ''
if (name.indexOf('Responsive') === 0) {
responsiveWarning = [
``,
`// make sure parent container have a defined height when using responsive component,`,
`// otherwise height will be 0 and no chart will be rendered.`,
].join('\n')
}

return `import { render } from 'react-dom'
${imports.join('\n')}
${responsiveWarning}
render((
<${name}
${properties.join('\n ')}
Expand Down

0 comments on commit b171044

Please sign in to comment.