diff --git a/src/components/axes/Axes.js b/src/components/axes/Axes.js
new file mode 100644
index 000000000..e835d8644
--- /dev/null
+++ b/src/components/axes/Axes.js
@@ -0,0 +1,87 @@
+/*
+ * 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, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Axis from './Axis'
+
+const horizontalPositions = ['top', 'bottom']
+const verticalPositions = ['left', 'right']
+const positions = [...horizontalPositions, ...verticalPositions]
+
+const axisPropType = PropTypes.shape({
+ tickSize: PropTypes.number,
+ tickPadding: PropTypes.number,
+ format: PropTypes.func,
+})
+
+export default class Axes extends Component {
+ static propTypes = {
+ xScale: PropTypes.func.isRequired,
+ yScale: PropTypes.func.isRequired,
+
+ width: PropTypes.number.isRequired,
+ height: PropTypes.number.isRequired,
+
+ axes: PropTypes.shape({
+ top: axisPropType,
+ right: axisPropType,
+ bottom: axisPropType,
+ left: axisPropType,
+ }).isRequired,
+
+ theme: PropTypes.object.isRequired,
+ }
+
+ static defaultProps = {}
+
+ render() {
+ const {
+ xScale,
+ yScale,
+ width,
+ height,
+ axes,
+ theme,
+ animate,
+ motionStiffness,
+ motionDamping,
+ } = this.props
+
+ return (
+
+ {positions.map(position => {
+ if (!axes[position]) return null
+
+ const axis = axes[position]
+ if (axis.enabled !== undefined && axis.enabled === false)
+ return null
+
+ const scale = horizontalPositions.includes(position)
+ ? xScale
+ : yScale
+
+ return (
+
+ )
+ })}
+
+ )
+ }
+}
diff --git a/src/components/axes/Grid.js b/src/components/axes/Grid.js
index 10d44e891..ac81d6264 100644
--- a/src/components/axes/Grid.js
+++ b/src/components/axes/Grid.js
@@ -23,9 +23,12 @@ export default class Grid extends Component {
static propTypes = {
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
+
xScale: PropTypes.func,
yScale: PropTypes.func,
+
theme: PropTypes.object.isRequired,
+
// motion
animate: PropTypes.bool.isRequired,
motionStiffness: PropTypes.number.isRequired,
@@ -43,7 +46,6 @@ export default class Grid extends Component {
const {
width,
height,
- scales,
xScale,
yScale,
theme,
diff --git a/src/components/axes/index.js b/src/components/axes/index.js
index a36805c13..d6017bdb7 100644
--- a/src/components/axes/index.js
+++ b/src/components/axes/index.js
@@ -7,4 +7,5 @@
* file that was distributed with this source code.
*/
export Axis from './Axis'
+export Axes from './Axes'
export Grid from './Grid'
diff --git a/src/components/charts/bars/Bar.js b/src/components/charts/bars/Bar.js
index 45f494240..79d174b2b 100644
--- a/src/components/charts/bars/Bar.js
+++ b/src/components/charts/bars/Bar.js
@@ -10,17 +10,11 @@ import {
generateStackedBars,
} from '../../../lib/charts/bar'
import SvgWrapper from '../SvgWrapper'
-import Axis from '../../axes/Axis'
+import Axes from '../../axes/Axes'
import Grid from '../../axes/Grid'
import BarItem from './BarItem'
import BarItemLabel from './BarItemLabel'
-const axisPropType = PropTypes.shape({
- tickSize: PropTypes.number,
- tickPadding: PropTypes.number,
- format: PropTypes.func,
-})
-
export default class Bar extends Component {
static propTypes = {
// data
@@ -50,12 +44,7 @@ export default class Bar extends Component {
xPadding: PropTypes.number.isRequired,
// axes
- axes: PropTypes.shape({
- top: axisPropType,
- right: axisPropType,
- bottom: axisPropType,
- left: axisPropType,
- }),
+ axes: PropTypes.object.isRequired,
enableGridX: PropTypes.bool.isRequired,
enableGridY: PropTypes.bool.isRequired,
@@ -81,8 +70,12 @@ export default class Bar extends Component {
xPadding: 0.1,
enableLabels: true,
axes: {
- left: {},
- bottom: {},
+ left: {
+ enabled: true,
+ },
+ bottom: {
+ enabled: true,
+ },
},
enableGridX: false,
enableGridY: true,
@@ -187,28 +180,16 @@ export default class Bar extends Component {
height={height}
xScale={enableGridX ? result.xScale : null}
yScale={enableGridY ? result.yScale : null}
+ {...motionProps}
+ />
+
- {['top', 'right', 'bottom', 'left'].map(position => {
- if (!axes[position]) return null
-
- const axis = axes[position]
- const scale = ['top', 'bottom'].includes(position)
- ? result.xScale
- : result.yScale
-
- return (
-
- )
- })}
{bars}
{enableLabels &&
result.bars.map(d => )}
diff --git a/src/components/charts/line/Line.js b/src/components/charts/line/Line.js
index 014c89608..99934aea4 100644
--- a/src/components/charts/line/Line.js
+++ b/src/components/charts/line/Line.js
@@ -8,58 +8,156 @@
*/
import React, { Component } from 'react'
import PropTypes from 'prop-types'
-import _ from 'lodash'
-import { curvePropMapping, curvePropType } from '../../../properties/curve'
+import { merge } from 'lodash'
import { line } from 'd3'
+import Nivo, { defaultTheme } from '../../../Nivo'
+import { margin as marginPropType } from '../../../PropTypes'
+import { getColorRange } from '../../../ColorUtils'
+import SvgWrapper from '../SvgWrapper'
+import {
+ generateLines,
+ generateStackedLines,
+} from '../../../lib/charts/line'
+import { curvePropMapping, curvePropType } from '../../../properties/curve'
+import Axes from '../../axes/Axes'
+import Grid from '../../axes/Grid'
export default class Line extends Component {
static propTypes = {
- scales: PropTypes.object.isRequired,
+ // data
+ data: PropTypes.arrayOf(
+ PropTypes.shape({
+ id: PropTypes.string.isRequired,
+ data: PropTypes.arrayOf(
+ PropTypes.shape({
+ x: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string,
+ ]).isRequired,
+ y: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string,
+ ]).isRequired,
+ })
+ ).isRequired,
+ })
+ ).isRequired,
+
+ stacked: PropTypes.bool.isRequired,
curve: curvePropType.isRequired,
- color: PropTypes.string.isRequired,
+
+ width: PropTypes.number.isRequired,
+ height: PropTypes.number.isRequired,
+ margin: marginPropType,
+
+ // axes
+ axes: PropTypes.object.isRequired,
+ enableGridX: PropTypes.bool.isRequired,
+ enableGridY: PropTypes.bool.isRequired,
+
+ theme: PropTypes.object.isRequired,
+ colors: PropTypes.any.isRequired,
+
+ // motion
+ animate: PropTypes.bool.isRequired,
+ motionStiffness: PropTypes.number.isRequired,
+ motionDamping: PropTypes.number.isRequired,
}
static defaultProps = {
- scales: {},
+ stacked: false,
curve: 'linear',
- color: '#000',
+ margin: Nivo.defaults.margin,
+ axes: {
+ left: {
+ enabled: true,
+ },
+ bottom: {
+ enabled: true,
+ },
+ },
+ enableGridX: true,
+ enableGridY: true,
+ colors: Nivo.defaults.colorRange,
+ theme: {},
+ animate: true,
+ motionStiffness: Nivo.defaults.motionStiffness,
+ motionDamping: Nivo.defaults.motionDamping,
}
render() {
const {
data,
- scales,
- xScale: _xScale,
- yScale: _yScale,
- x,
- y,
+ stacked,
curve,
- color,
+ margin: _margin,
+ width: _width,
+ height: _height,
+ axes,
+ enableGridX,
+ enableGridY,
+ theme: _theme,
+ colors,
+ animate,
+ motionStiffness,
+ motionDamping,
} = this.props
- const xScale = scales[_xScale]
- const yScale = scales[_yScale]
+ const margin = Object.assign({}, Nivo.defaults.margin, _margin)
+ const width = _width - margin.left - margin.right
+ const height = _height - margin.top - margin.bottom
- const getX = _.isFunction(x) ? x : d => d[x]
- const getY = _.isFunction(y) ? y : d => d[y]
+ const theme = merge({}, defaultTheme, _theme)
+ const color = getColorRange(colors)
- const points = data.map(d => ({
- x: xScale(getX(d)),
- y: yScale(getY(d)),
- }))
+ const motionProps = {
+ animate,
+ motionDamping,
+ motionStiffness,
+ }
+
+ let result
+ if (stacked === true) {
+ result = generateStackedLines(data, width, height)
+ } else {
+ result = generateLines(data, width, height)
+ }
const lineGenerator = line()
.x(d => d.x)
.y(d => d.y)
.curve(curvePropMapping[curve])
+ const { xScale, yScale, lines } = result
+
return (
-
+
+
+
+ {lines.map(({ id, points }) => (
+
+ ))}
+
)
}
}
diff --git a/src/lib/charts/line/index.js b/src/lib/charts/line/index.js
new file mode 100644
index 000000000..e1a9b0830
--- /dev/null
+++ b/src/lib/charts/line/index.js
@@ -0,0 +1,129 @@
+import { range, max, maxBy, sumBy, uniq } from 'lodash'
+import { scalePoint, scaleLinear } from 'd3'
+
+/**
+ * Generates X scale.
+ *
+ * @param {Array.