Skip to content

Commit

Permalink
feat(bubble): improve bubble components
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte committed Sep 19, 2017
1 parent fc022c0 commit 0779f33
Show file tree
Hide file tree
Showing 26 changed files with 832 additions and 655 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ Join the [nivo discord community](https://discord.gg/n7Ft74f).

## Guides

- [colors](http://nivo.rocks/#/guides/colors)
- [colors](http://nivo.rocks/#/guides/colors)
- [gradients](http://nivo.rocks/#/guides/gradients)
- [patterns](http://nivo.rocks/#/guides/patterns)

## Repositories

Expand Down
1 change: 0 additions & 1 deletion src/components/charts/bar/Bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ const Bar = ({
}

const boundDefs = bindDefs(defs, result.bars, fill, {
idKey: 'key',
dataKey: 'data',
targetKey: 'data.fill',
})
Expand Down
14 changes: 2 additions & 12 deletions src/components/charts/bar/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import PropTypes from 'prop-types'
import noop from '../../../lib/noop'
import BarItem from './BarItem'
import { defsPropTypes } from '../../../props'

export const BarPropTypes = {
// data
Expand Down Expand Up @@ -52,18 +53,7 @@ export const BarPropTypes = {
// styling
borderRadius: PropTypes.number.isRequired,
getColor: PropTypes.func.isRequired, // computed
defs: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
})
).isRequired,
fill: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string,
match: PropTypes.oneOfType([PropTypes.oneOf(['*']), PropTypes.object, PropTypes.func])
.isRequired,
})
).isRequired,
...defsPropTypes,
borderWidth: PropTypes.number.isRequired,
borderColor: PropTypes.any.isRequired,
getBorderColor: PropTypes.func.isRequired,
Expand Down
215 changes: 112 additions & 103 deletions src/components/charts/bubble/Bubble.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,118 +7,127 @@
* file that was distributed with this source code.
*/
import React from 'react'
import _ from 'lodash'
import compose from 'recompose/compose'
import withPropsOnChange from 'recompose/withPropsOnChange'
import defaultProps from 'recompose/defaultProps'
import pure from 'recompose/pure'
import { getLabelGenerator } from '../../../lib/propertiesConverters'
import { getInheritedColorGenerator } from '../../../lib/colors'
import { bubblePropTypes, bubbleDefaultProps } from './props'
import BubblePlaceholders from './BubblePlaceholders'
import BasicTooltip from '../../tooltip/BasicTooltip'
import { TransitionMotion, spring } from 'react-motion'
import pick from 'lodash/pick'
import { colorMotionSpring, getInterpolatedColor } from '../../../lib/colors'
import Container from '../Container'
import enhance from './enhance'
import { nodeWillEnter, nodeWillLeave } from './motion'
import { getNodeHandlers } from './interactivity'
import SvgWrapper from '../SvgWrapper'

const createNodes = ({
const Bubble = ({
nodes,
nodeComponent,

// dimensions
margin,
outerWidth,
outerHeight,

// styling
theme,
borderWidth,
getBorderColor,
enableLabel,
getLabel,
labelSkipRadius,
getLabelTextColor,
}) => (nodes, { showTooltip, hideTooltip, theme }) => {
const renderedNodes = []
defs,

// exclude nodes with negative radius
nodes.filter(node => node.style.r > 0).forEach(node => {
const handleTooltip = e => {
showTooltip(
<BasicTooltip
id={node.data.id}
value={node.data.value}
enableChip={true}
color={node.style.color}
theme={theme}
/>,
e
)
}
// labels
getLabelTextColor,

renderedNodes.push(
<circle
key={`${node.key}.circle`}
r={node.style.r}
transform={`translate(${node.style.x},${node.style.y})`}
onMouseEnter={handleTooltip}
onMouseMove={handleTooltip}
onMouseLeave={hideTooltip}
onClick={node.onClick}
fill={node.style.color}
stroke={getBorderColor(node.style)}
strokeWidth={borderWidth}
/>
)
})
// motion
animate,
motionStiffness,
motionDamping,

if (enableLabel === true) {
nodes
.filter(node => {
return (
node.data.height === 0 &&
(labelSkipRadius === 0 || node.data.r >= labelSkipRadius)
)
})
.forEach(node => {
renderedNodes.push(
<text
key={`${node.key}.text`}
transform={`translate(${node.style.x},${node.style.y}) scale(${node.style
.scale})`}
textAnchor="middle"
alignmentBaseline="central"
style={{
fill: getLabelTextColor(node.style),
pointerEvents: 'none',
}}
>
{getLabel({ ...node.data.data, ...node.data })}
</text>
)
})
// interactivity
isInteractive,
onClick,
isZoomable,
zoomToNode,
}) => {
const springConfig = {
stiffness: motionStiffness,
damping: motionDamping,
}

return renderedNodes
}

const Bubble = props => (
<BubblePlaceholders {...props} namespace="svg">
{createNodes(props)}
</BubblePlaceholders>
)
const getHandlers = (node, showTooltip, hideTooltip) =>
getNodeHandlers(node, {
isInteractive,
onClick,
showTooltip,
hideTooltip,
isZoomable,
zoomToNode,
theme,
})

Bubble.propTypes = _.omit(bubblePropTypes, [
'children',
'namespace',
'transitionDuration',
'transitionEasing',
])
return (
<Container isInteractive={isInteractive} theme={theme}>
{({ showTooltip, hideTooltip }) => (
<SvgWrapper width={outerWidth} height={outerHeight} margin={margin} defs={defs}>
{!animate && (
<g>
{nodes.map(node =>
React.createElement(nodeComponent, {
key: node.path,
node,
style: {
...pick(node, ['scale', 'r', 'x', 'y', 'color']),
fill: node.fill,
borderWidth,
borderColor: getBorderColor(node),
labelTextColor: getLabelTextColor(node),
},
handlers: getHandlers(node, showTooltip, hideTooltip),
})
)}
</g>
)}
{animate && (
<TransitionMotion
willEnter={nodeWillEnter}
willLeave={nodeWillLeave(springConfig)}
styles={nodes.map(node => ({
key: node.path,
data: node,
style: {
scale: spring(1, springConfig),
r: spring(node.r, springConfig),
x: spring(node.x, springConfig),
y: spring(node.y, springConfig),
opacity: spring(1, springConfig),
...colorMotionSpring(node.color, springConfig),
},
}))}
>
{interpolatedStyles => (
<g>
{interpolatedStyles.map(({ style, data: node }) => {
style.color = getInterpolatedColor(style)

const enhance = compose(
defaultProps(
_.omit(bubbleDefaultProps, ['namespace', 'transitionDuration', 'transitionEasing'])
),
withPropsOnChange(['label', 'labelFormat'], ({ label, labelFormat }) => ({
getLabel: getLabelGenerator(label, labelFormat),
})),
withPropsOnChange(['borderColor'], ({ borderColor }) => ({
getBorderColor: getInheritedColorGenerator(borderColor),
})),
withPropsOnChange(['labelTextColor'], ({ labelTextColor }) => ({
getLabelTextColor: getInheritedColorGenerator(labelTextColor),
})),
pure
)
return React.createElement(nodeComponent, {
key: node.path,
node,
style: {
...style,
fill: node.fill,
borderWidth,
borderColor: getBorderColor(style),
labelTextColor: getLabelTextColor(style),
},
handlers: getHandlers(node, showTooltip, hideTooltip),
})
})}
</g>
)}
</TransitionMotion>
)}
</SvgWrapper>
)}
</Container>
)
}

const enhancedBubble = enhance(Bubble)
enhancedBubble.displayName = 'enhance(Bubble)'
Bubble.displayName = 'Bubble'

export default enhancedBubble
export default enhance(Bubble)
Loading

0 comments on commit 0779f33

Please sign in to comment.