Skip to content

Commit

Permalink
feat(bar): use @nivo/axes instead of @nivo/core for SVG axes
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte committed Sep 8, 2018
1 parent 203f719 commit 3b22c6f
Show file tree
Hide file tree
Showing 14 changed files with 3,832 additions and 3,714 deletions.
82 changes: 82 additions & 0 deletions packages/axes/src/components/Axes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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, { Fragment, PureComponent } from 'react'
import PropTypes from 'prop-types'
import { motionPropTypes, axisThemePropType } from '@nivo/core'
import Axis from './Axis'
import { axisPropType } from '../props'

const positions = ['top', 'right', 'bottom', 'left']

export default class Axes extends PureComponent {
static propTypes = {
xScale: PropTypes.func.isRequired,
yScale: PropTypes.func.isRequired,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
top: axisPropType,
right: axisPropType,
bottom: axisPropType,
left: axisPropType,
theme: PropTypes.shape({
axis: axisThemePropType.isRequired,
}).isRequired,
...motionPropTypes,
}

render() {
const {
xScale,
yScale,
width,
height,
top,
right,
bottom,
left,
theme,
animate,
motionStiffness,
motionDamping,
} = this.props

const axes = { top, right, bottom, left }

return (
<Fragment>
{positions.map(position => {
const axis = axes[position]

if (!axis) return null

const isXAxis = position === 'top' || position === 'bottom'
const ticksPosition =
position === 'top' || position === 'left' ? 'before' : 'after'

return (
<Axis
key={position}
{...axis}
axis={isXAxis ? 'x' : 'y'}
x={position === 'right' ? width : 0}
y={position === 'bottom' ? height : 0}
scale={isXAxis ? xScale : yScale}
length={isXAxis ? width : height}
ticksPosition={ticksPosition}
theme={theme}
animate={animate}
motionDamping={motionDamping}
motionStiffness={motionStiffness}
/>
)
})}
</Fragment>
)
}
}
4 changes: 2 additions & 2 deletions packages/axes/src/components/Axis.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class Axis extends Component {
if (legendPosition === 'start') {
textAnchor = 'start'
legendY = length
} else if (legendPosition === 'center') {
} else if (legendPosition === 'middle') {
textAnchor = 'middle'
legendY = length / 2
} else if (legendPosition === 'end') {
Expand All @@ -136,7 +136,7 @@ class Axis extends Component {
legendY = legendOffset
if (legendPosition === 'start') {
textAnchor = 'start'
} else if (legendPosition === 'center') {
} else if (legendPosition === 'middle') {
textAnchor = 'middle'
legendX = length / 2
} else if (legendPosition === 'end') {
Expand Down
2 changes: 2 additions & 0 deletions packages/axes/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { default as Axes } from './components/Axes'
export { default as Axis } from './components/Axis'
export * from './canvas'
export * from './props'
29 changes: 29 additions & 0 deletions packages/axes/src/props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 PropTypes from 'prop-types'

export const axisPropTypes = {
ticksPosition: PropTypes.oneOf(['before', 'after']),
tickValues: PropTypes.oneOfType([
PropTypes.number,
PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.instanceOf(Date)])
),
]),
tickSize: PropTypes.number,
tickPadding: PropTypes.number,
tickRotation: PropTypes.number,
tickFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
renderTick: PropTypes.func,
legend: PropTypes.node,
legendPosition: PropTypes.oneOf(['start', 'middle', 'end']),
legendOffset: PropTypes.number,
}

export const axisPropType = PropTypes.shape(axisPropTypes)
1 change: 1 addition & 0 deletions packages/bar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"umd/"
],
"dependencies": {
"@nivo/axes": "0.49.0",
"@nivo/core": "0.49.0",
"@nivo/legends": "0.49.0",
"d3-scale": "^2.1.2",
Expand Down
3 changes: 2 additions & 1 deletion packages/bar/src/Bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
*/
import React from 'react'
import { TransitionMotion, spring } from 'react-motion'
import { bindDefs, Container, SvgWrapper, Grid, Axes, CartesianMarkers } from '@nivo/core'
import { bindDefs, Container, SvgWrapper, Grid, CartesianMarkers } from '@nivo/core'
import { Axes } from '@nivo/axes'
import { BoxLegendSvg } from '@nivo/legends'
import { generateGroupedBars, generateStackedBars } from './compute'
import setDisplayName from 'recompose/setDisplayName'
Expand Down
22 changes: 6 additions & 16 deletions packages/bar/src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
* file that was distributed with this source code.
*/
import PropTypes from 'prop-types'
import { noop } from '@nivo/core'
import { defsPropTypes } from '@nivo/core'
import { noop, defsPropTypes } from '@nivo/core'
import { axisPropType } from '@nivo/axes'
import { LegendPropShape } from '@nivo/legends'
import BarItem from './BarItem'

export const BarPropTypes = {
// data
data: PropTypes.arrayOf(PropTypes.object).isRequired,
indexBy: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
getIndex: PropTypes.func.isRequired, // computed
Expand All @@ -28,20 +27,17 @@ export const BarPropTypes = {
padding: PropTypes.number.isRequired,
innerPadding: PropTypes.number.isRequired,

// axes & grid
axisTop: PropTypes.object,
axisRight: PropTypes.object,
axisBottom: PropTypes.object,
axisLeft: PropTypes.object,
axisTop: axisPropType,
axisRight: axisPropType,
axisBottom: axisPropType,
axisLeft: axisPropType,
enableGridX: PropTypes.bool.isRequired,
enableGridY: PropTypes.bool.isRequired,
gridXValues: PropTypes.arrayOf(PropTypes.number),
gridYValues: PropTypes.arrayOf(PropTypes.number),

// customization
barComponent: PropTypes.func.isRequired,

// labels
enableLabel: PropTypes.bool.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
labelFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
Expand All @@ -53,15 +49,13 @@ export const BarPropTypes = {
labelLinkColor: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
getLabelLinkColor: PropTypes.func.isRequired, // computed

// styling
borderRadius: PropTypes.number.isRequired,
getColor: PropTypes.func.isRequired, // computed
...defsPropTypes,
borderWidth: PropTypes.number.isRequired,
borderColor: PropTypes.any.isRequired,
getBorderColor: PropTypes.func.isRequired,

// interactivity
isInteractive: PropTypes.bool,
onClick: PropTypes.func.isRequired,
tooltipFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
Expand Down Expand Up @@ -91,16 +85,13 @@ export const BarDefaultProps = {
padding: 0.1,
innerPadding: 0,

// axes & grid
axisBottom: {},
axisLeft: {},
enableGridX: false,
enableGridY: true,

// customization
barComponent: BarItem,

// labels
enableLabel: true,
label: 'value',
labelSkipWidth: 0,
Expand All @@ -114,7 +105,6 @@ export const BarDefaultProps = {
borderWidth: 0,
borderColor: 'inherit',

// interactivity
isInteractive: true,
onClick: noop,

Expand Down
62 changes: 55 additions & 7 deletions packages/bar/stories/bar.stories.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { Fragment } from 'react'
import { storiesOf } from '@storybook/react'
import { withInfo } from '@storybook/addon-info'
import { generateCountriesData, sets } from '@nivo/generators'
Expand Down Expand Up @@ -103,14 +103,14 @@ const divergingCommonProps = {
},
axisBottom: {
legend: 'USERS',
legendPosition: 'center',
legendPosition: 'middle',
legendOffset: 50,
tickSize: 0,
tickPadding: 12,
},
axisLeft: null,
axisRight: {
format: v => `${Math.abs(v)}%`,
tickValueFormat: v => `${Math.abs(v)}%`,
},
markers: [
{
Expand Down Expand Up @@ -185,10 +185,10 @@ stories.add(
<Bar
{...commonProps}
axisLeft={{
format: value =>
Number(value).toLocaleString('ru-RU', {
tickValueFormat: value =>
`${Number(value).toLocaleString('ru-RU', {
minimumFractionDigits: 2,
}),
})} ₽`,
}}
tooltipFormat={value =>
`${Number(value).toLocaleString('ru-RU', {
Expand All @@ -205,7 +205,7 @@ stories.add(
<Bar
{...commonProps}
axisLeft={{
format: value =>
tickValueFormat: value =>
Number(value).toLocaleString('ru-RU', {
minimumFractionDigits: 2,
}),
Expand All @@ -225,3 +225,51 @@ stories.add(
/>
))
)

stories.add(
'custom axis ticks',
withInfo(`
You can customize rendering of axis ticks using the corresponding axis \`renderTick\` property.
`)(() => (
<Bar
{...commonProps}
axisLeft={null}
axisBottom={{
renderTick: tick => (
<g key={tick.key} transform={`translate(${tick.x},${tick.y + 22})`}>
<rect
x={-14}
y={-6}
rx={3}
ry={3}
width={28}
height={24}
fill="rgba(0, 0, 0, .05)"
/>
<rect
x={-12}
y={-12}
rx={2}
ry={2}
width={24}
height={24}
fill="rgb(232, 193, 160)"
/>
<line stroke="rgb(232, 193, 160)" strokeWidth={1.5} y1={-22} y2={-12} />
<text
textAnchor="middle"
alignmentBaseline="middle"
style={{
...tick.theme.axis.ticks.text,
fill: '#333',
fontSize: 10,
}}
>
{tick.value}
</text>
</g>
),
}}
/>
))
)
Loading

0 comments on commit 3b22c6f

Please sign in to comment.