From 42f1cfe35027879cfeb8f62fcd09a765f6afaab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Benitte?= Date: Tue, 12 Dec 2017 21:13:46 +0900 Subject: [PATCH] feat(line): add LineChartSvg component --- packages/nivo-line/src/compute.js | 4 +- .../legacy/{LineDots.js => LineDotsSvg.js} | 0 packages/nivo-line/src/legacy/_Line.js | 363 ------------------ packages/nivo-line/src/props.js | 11 - packages/nivo-line/src/svg/LineAreaSvg.js | 41 +- packages/nivo-line/src/svg/LineChartSvg.js | 270 +++++++++++++ packages/nivo-line/src/svg/LineDotsSvg.js | 164 ++++++++ packages/nivo-line/src/svg/LineSvg.js | 43 ++- .../src/svg/ResponsiveLineChartSvg.js | 19 + packages/nivo-line/src/svg/index.js | 2 + website/src/SiteMap.js | 2 +- .../src/components/charts/line/Line/index.js | 244 +----------- .../charts/line/LineComposite/Code.js | 72 ++++ .../charts/line/LineComposite/index.js | 362 +++++++++++++++++ .../components/charts/line/defaultProps.js | 3 +- 15 files changed, 975 insertions(+), 625 deletions(-) rename packages/nivo-line/src/legacy/{LineDots.js => LineDotsSvg.js} (100%) delete mode 100644 packages/nivo-line/src/legacy/_Line.js create mode 100644 packages/nivo-line/src/svg/LineChartSvg.js create mode 100644 packages/nivo-line/src/svg/LineDotsSvg.js create mode 100644 packages/nivo-line/src/svg/ResponsiveLineChartSvg.js create mode 100644 website/src/components/charts/line/LineComposite/Code.js create mode 100644 website/src/components/charts/line/LineComposite/index.js diff --git a/packages/nivo-line/src/compute.js b/packages/nivo-line/src/compute.js index 545e11a19..d01986b9f 100644 --- a/packages/nivo-line/src/compute.js +++ b/packages/nivo-line/src/compute.js @@ -138,8 +138,8 @@ export const generateLines = (data, xScale, yScale, color) => points: serieData.map(d => Object.assign({}, d, { value: d.y, - x: xScale(d.x), - y: yScale(d.y), + x: d.x, + y: d.y, }) ), } diff --git a/packages/nivo-line/src/legacy/LineDots.js b/packages/nivo-line/src/legacy/LineDotsSvg.js similarity index 100% rename from packages/nivo-line/src/legacy/LineDots.js rename to packages/nivo-line/src/legacy/LineDotsSvg.js diff --git a/packages/nivo-line/src/legacy/_Line.js b/packages/nivo-line/src/legacy/_Line.js deleted file mode 100644 index 9da4cd036..000000000 --- a/packages/nivo-line/src/legacy/_Line.js +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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 { min, max, maxBy } from 'lodash' -import React from 'react' -import { sortBy } from 'lodash' -import { area, line } from 'd3-shape' -import compose from 'recompose/compose' -import pure from 'recompose/pure' -import setDisplayName from 'recompose/setDisplayName' -import withPropsOnChange from 'recompose/withPropsOnChange' -import defaultProps from 'recompose/defaultProps' -import { curveFromProp } from '@nivo/core' -import { getInheritedColorGenerator } from '@nivo/core' -import { withTheme, withColors, withDimensions, withMotion } from '@nivo/core' -import { Container, SvgWrapper } from '@nivo/core' -import { getScales, getStackedScales, generateLines, generateStackedLines } from './compute' -import { CartesianMarkers } from '@nivo/core' -import { Axes, Axis, Grid } from '@nivo/core' -import { BoxLegendSvg } from '@nivo/legends' -import LineAreas from './LineAreas' -import LineLines from './LineLines' -import LineSlices from './LineSlices' -import LineDots from './LineDots' -import { LinePropTypes, LineDefaultProps } from './props' -import { scaleLinear, scaleLog } from 'd3-scale' - -const Line = ({ - data, - - //lines, - lineGenerator, - areaGenerator, - xScale, - yScale, - slices, - - // dimensions - margin, - width, - height, - outerWidth, - outerHeight, - - // axes & grid - axisTop, - axisRight, - axisBottom, - axisLeft, - enableGridX, - enableGridY, - - lineWidth, - enableArea, - areaOpacity, - - // dots - enableDots, - dotSymbol, - dotSize, - getDotColor, - dotBorderWidth, - getDotBorderColor, - enableDotLabel, - dotLabel, - dotLabelFormat, - dotLabelYOffset, - - // markers - markers, - - // theming - theme, - - // motion - animate, - motionStiffness, - motionDamping, - - // interactivity - isInteractive, - tooltipFormat, - - // stackTooltip - enableStackTooltip, - - legends, - - scales, - dataScales, - getColor, -}) => { - const motionProps = { - animate, - motionDamping, - motionStiffness, - } - - const numericScales = ['linear', 'log'] - - const scs = scales.map(scale => { - const scaleSeries = - scale.selector === '*' ? data : data.filter(serie => scale.selector.includes(serie.id)) - let [minValue, maxValue] = scale.domain - - if (numericScales.includes(scale.type)) { - if (minValue === 'auto') { - minValue = min(scaleSeries.map(serie => min(serie.data.map(d => d[scale.axis])))) - } - if (maxValue === 'auto') { - maxValue = max(scaleSeries.map(serie => max(serie.data.map(d => d[scale.axis])))) - } - } - - let s - if (scale.type === 'linear') { - s = scaleLinear().domain([minValue, maxValue]) - } else if (scale.type === 'log') { - s = scaleLog().domain([minValue, maxValue]) - } - s.id = scale.id - - if (scale.axis === 'x') { - s.range([0, width]) - } else if (scale.axis === 'y') { - s.range([height, 0]) - } - - return s - }) - - const lines = [] - Object.keys(dataScales).forEach(serieId => { - const serieScales = dataScales[serieId] - const serie = data.find(({ id }) => id === serieId) - const xs = scs.find(({ id }) => id === serieScales.x) - const ys = scs.find(({ id }) => id === serieScales.y) - - lines.push({ - id: serieId, - color: getColor(serie), - data: serie, - points: serie.data.map(d => - Object.assign({}, d, { - value: d.y, - x: xs(d.x), - y: ys(d.y), - }) - ), - }) - }) - - console.log(lines) - - return ( - - {({ showTooltip, hideTooltip }) => ( - - {/* - - */} - - {axisLeft && ( - id === axisLeft.scale)} - /> - )} - {axisRight && ( - id === axisRight.scale)} - /> - )} - {/* - id === 'x')} - yScale={scs.find(({ id }) => id === 'y')} - width={width} - height={height} - theme={theme} - top={axisTop} - right={axisRight} - bottom={axisBottom} - left={axisLeft} - {...motionProps} - /> - */} - {enableArea && ( - - )} - - {/*isInteractive && - enableStackTooltip && ( - - )*/} - {enableDots && ( - - )} - {legends.map((legend, i) => { - const legendData = lines - .map(line => ({ - label: line.id, - fill: line.color, - })) - .reverse() - - return ( - - ) - })} - - )} - - ) -} - -Line.propTypes = LinePropTypes - -const enhance = compose( - defaultProps(LineDefaultProps), - withTheme(), - withColors(), - withDimensions(), - withMotion(), - withPropsOnChange(['curve', 'height'], ({ curve, height }) => ({ - areaGenerator: area() - .defined(d => d && d.value !== null) - .x(d => d.x) - .y0(height) - .y1(d => d.y) - .curve(curveFromProp(curve)), - lineGenerator: line() - .defined(d => d && d.value !== null) - .x(d => d.x) - .y(d => d.y) - .curve(curveFromProp(curve)), - })), - /* - withPropsOnChange( - ['data', 'stacked', 'width', 'height', 'minY', 'maxY'], - ({ data, stacked, width, height, margin, minY, maxY }) => { - let scales - const args = { data, width, height, minY, maxY } - if (stacked === true) { - scales = getStackedScales(args) - } else { - scales = getScales(args) - } - - return { - margin, - width, - height, - ...scales, - } - } - ), - withPropsOnChange( - ['getColor', 'xScale', 'yScale'], - ({ data, stacked, xScale, yScale, getColor }) => { - let lines - if (stacked === true) { - lines = generateStackedLines(data, xScale, yScale, getColor) - } else { - lines = generateLines(data, xScale, yScale, getColor) - } - - const slices = xScale.domain().map((id, i) => { - let points = sortBy( - lines.map(line => ({ - id: line.id, - value: line.points[i].value, - y: line.points[i].y, - color: line.color, - })), - 'y' - ) - - return { - id, - x: xScale(id), - points, - } - }) - - return { lines, slices } - } - ), - */ - withPropsOnChange(['dotColor'], ({ dotColor }) => ({ - getDotColor: getInheritedColorGenerator(dotColor), - })), - withPropsOnChange(['dotBorderColor'], ({ dotBorderColor }) => ({ - getDotBorderColor: getInheritedColorGenerator(dotBorderColor), - })), - pure -) - -export default setDisplayName('Line')(enhance(Line)) diff --git a/packages/nivo-line/src/props.js b/packages/nivo-line/src/props.js index 778deb0c4..babd83a2c 100644 --- a/packages/nivo-line/src/props.js +++ b/packages/nivo-line/src/props.js @@ -24,19 +24,8 @@ export const LinePropTypes = { }) ).isRequired, - /* - scales: scalesPropType({ - ids: PropTypes.oneOfType([ - PropTypes.oneOf(['*']), - PropTypes.arrayOf(PropTypes.string), - ]).isRequired, - }), - */ - stacked: PropTypes.bool.isRequired, curve: lineCurvePropType.isRequired, - areaGenerator: PropTypes.func.isRequired, - lineGenerator: PropTypes.func.isRequired, lines: PropTypes.array.isRequired, slices: PropTypes.array.isRequired, diff --git a/packages/nivo-line/src/svg/LineAreaSvg.js b/packages/nivo-line/src/svg/LineAreaSvg.js index ddfa6f3b7..9cda4cc20 100644 --- a/packages/nivo-line/src/svg/LineAreaSvg.js +++ b/packages/nivo-line/src/svg/LineAreaSvg.js @@ -8,16 +8,23 @@ */ import React from 'react' import PropTypes from 'prop-types' +import compose from 'recompose/compose' +import defaultProps from 'recompose/defaultProps' +import withPropsOnChange from 'recompose/withPropsOnChange' import pure from 'recompose/pure' +import setDisplayName from 'recompose/setDisplayName' +import { area } from 'd3-shape' import { SmartMotion, motionPropTypes, defaultAnimate, defaultMotionDamping, defaultMotionStiffness, + curvePropType, + curveFromProp, } from '@nivo/core' -const LineArea = ({ +const LineAreaSvg = ({ data, generator, xScale, @@ -54,7 +61,7 @@ const LineArea = ({ ) } -LineArea.propTypes = { +LineAreaSvg.propTypes = { data: PropTypes.arrayOf( PropTypes.shape({ x: PropTypes.number, @@ -64,16 +71,32 @@ LineArea.propTypes = { generator: PropTypes.func.isRequired, xScale: PropTypes.func.isRequired, yScale: PropTypes.func.isRequired, + height: PropTypes.number.isRequired, + + curve: curvePropType.isRequired, // motion ...motionPropTypes, } -LineArea.defaultProps = { - // motion - animate: defaultAnimate, - motionDamping: defaultMotionDamping, - motionStiffness: defaultMotionStiffness, -} +const enhance = compose( + defaultProps({ + curve: 'linear', + + // motion + animate: defaultAnimate, + motionDamping: defaultMotionDamping, + motionStiffness: defaultMotionStiffness, + }), + withPropsOnChange(['curve', 'height'], ({ curve, height }) => ({ + generator: area() + .defined(d => d && d.x !== null && d.y !== null) + .x(d => d.x) + .y0(height) + .y1(d => d.y) + .curve(curveFromProp(curve)), + })), + pure +) -export default pure(LineArea) +export default setDisplayName('LineAreaSvg')(enhance(LineAreaSvg)) diff --git a/packages/nivo-line/src/svg/LineChartSvg.js b/packages/nivo-line/src/svg/LineChartSvg.js new file mode 100644 index 000000000..d8c1e0138 --- /dev/null +++ b/packages/nivo-line/src/svg/LineChartSvg.js @@ -0,0 +1,270 @@ +/* + * 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 { sortBy } from 'lodash' +import compose from 'recompose/compose' +import pure from 'recompose/pure' +import withPropsOnChange from 'recompose/withPropsOnChange' +import defaultProps from 'recompose/defaultProps' +import setDisplayName from 'recompose/setDisplayName' +import { getInheritedColorGenerator } from '@nivo/core' +import { withTheme, withColors, withDimensions, withMotion } from '@nivo/core' +import { Container, SvgWrapper } from '@nivo/core' +import { getScales, getStackedScales, generateLines, generateStackedLines } from '../compute' +import { CartesianMarkers } from '@nivo/core' +import { Axes, Grid } from '@nivo/axes' +import { BoxLegendSvg } from '@nivo/legends' +import LineSvg from './LineSvg' +import LineAreaSvg from './LineAreaSvg' +import LineDotsSvg from './LineDotsSvg' +/* +import LineSlices from './LineSlices' +*/ +import { LinePropTypes, LineDefaultProps } from '../props' + +const LineChartSvg = ({ + lines, + xScale, + yScale, + slices, + + // dimensions + margin, + width, + height, + outerWidth, + outerHeight, + + // axes & grid + axisTop, + axisRight, + axisBottom, + axisLeft, + enableGridX, + enableGridY, + + lineWidth, + enableArea, + areaOpacity, + + // dots + enableDots, + dotSymbol, + dotSize, + dotColor, + dotBorderWidth, + dotBorderColor, + enableDotLabel, + dotLabel, + dotLabelFormat, + dotLabelYOffset, + + // markers + markers, + + // theming + theme, + + // motion + animate, + motionStiffness, + motionDamping, + + // interactivity + isInteractive, + tooltipFormat, + + // stackTooltip + enableStackTooltip, + + legends, +}) => { + const motionProps = { + animate, + motionDamping, + motionStiffness, + } + + return ( + + {({ showTooltip, hideTooltip }) => ( + + + + + {enableArea && + lines.map(line => ( + + ))} + {lines.map(line => ( + + ))} + {/* + {isInteractive && + enableStackTooltip && ( + + )} + */} + {enableDots && + lines.map(line => ( + + ))} + {legends.map((legend, i) => { + const legendData = lines.map(line => ({ + label: line.id, + fill: line.color, + })) + + return ( + + ) + })} + + )} + + ) +} + +LineChartSvg.propTypes = LinePropTypes + +const enhance = compose( + defaultProps(LineDefaultProps), + withTheme(), + withColors(), + withDimensions(), + withMotion(), + withPropsOnChange( + ['data', 'stacked', 'width', 'height', 'minY', 'maxY'], + ({ data, stacked, width, height, margin, minY, maxY }) => { + let scales + const args = { data, width, height, minY, maxY } + if (stacked === true) { + scales = getStackedScales(args) + } else { + scales = getScales(args) + } + + return { + margin, + width, + height, + ...scales, + } + } + ), + withPropsOnChange( + ['getColor', 'xScale', 'yScale'], + ({ data, stacked, xScale, yScale, getColor }) => { + let lines + if (stacked === true) { + lines = generateStackedLines(data, xScale, yScale, getColor) + } else { + lines = generateLines(data, xScale, yScale, getColor) + } + + const slices = xScale.domain().map((id, i) => { + let points = sortBy( + lines.map(line => ({ + id: line.id, + value: line.points[i].value, + y: line.points[i].y, + color: line.color, + })), + 'y' + ) + + return { + id, + x: xScale(id), + points, + } + }) + + return { lines, slices } + } + ), + pure +) + +export default setDisplayName('LineChartSvg')(enhance(LineChartSvg)) diff --git a/packages/nivo-line/src/svg/LineDotsSvg.js b/packages/nivo-line/src/svg/LineDotsSvg.js new file mode 100644 index 000000000..884edd214 --- /dev/null +++ b/packages/nivo-line/src/svg/LineDotsSvg.js @@ -0,0 +1,164 @@ +/* + * 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 } from 'react' +import PropTypes from 'prop-types' +import compose from 'recompose/compose' +import withPropsOnChange from 'recompose/withPropsOnChange' +import pure from 'recompose/pure' +import setDisplayName from 'recompose/setDisplayName' +import { TransitionMotion, spring } from 'react-motion' +import { motionPropTypes } from '@nivo/core' +import { getLabelGenerator } from '@nivo/core' +import { DotsItem } from '@nivo/core' + +const LineDotsSvg = ({ + data, + xScale, + yScale, + + symbol, + size, + color, + borderWidth, + borderColor, + + // labels + enableLabel, + getLabel, + labelYOffset, + + // theming + theme, + + // motion + animate, + motionStiffness, + motionDamping, +}) => { + const points = data.points.filter(point => point.value !== null).map(point => { + const pointData = { + serie: { id: data.id }, + x: point.key, + y: point.value, + } + + return { + key: `${data.id}.${point.x}`, + x: xScale(point.x), + y: yScale(point.y), + fill: color(data), + stroke: borderColor(data), + label: enableLabel ? getLabel(pointData) : null, + } + }) + + if (animate !== true) { + return ( + + {points.map(point => ( + + ))} + + ) + } + const springConfig = { + motionDamping, + motionStiffness, + } + + return ( + ({ + key: point.key, + data: point, + style: { + x: spring(point.x, springConfig), + y: spring(point.y, springConfig), + size: spring(size, springConfig), + }, + }))} + > + {interpolatedStyles => ( + + {interpolatedStyles.map(({ key, style, data: point }) => ( + + ))} + + )} + + ) +} + +LineDotsSvg.propTypes = { + data: PropTypes.shape({ + id: PropTypes.string.isRequired, + }), + xScale: PropTypes.func.isRequired, + yScale: PropTypes.func.isRequired, + + symbol: PropTypes.func, + size: PropTypes.number.isRequired, + color: PropTypes.func.isRequired, + borderWidth: PropTypes.number.isRequired, + borderColor: PropTypes.func.isRequired, + + // labels + enableLabel: PropTypes.bool.isRequired, + label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + labelFormat: PropTypes.string, + labelYOffset: PropTypes.number, + + // theming + theme: PropTypes.shape({ + dots: PropTypes.shape({ + textColor: PropTypes.string.isRequired, + fontSize: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, + + // motion + ...motionPropTypes, +} + +LineDotsSvg.defaultProps = { + // labels + enableLabel: false, + label: 'y', +} + +const enhance = compose( + withPropsOnChange(['label', 'labelFormat'], ({ label, labelFormat }) => ({ + getLabel: getLabelGenerator(label, labelFormat), + })), + pure +) + +export default setDisplayName('LineDotsSvg')(enhance(LineDotsSvg)) diff --git a/packages/nivo-line/src/svg/LineSvg.js b/packages/nivo-line/src/svg/LineSvg.js index 0680d2b82..3f66c4fdb 100644 --- a/packages/nivo-line/src/svg/LineSvg.js +++ b/packages/nivo-line/src/svg/LineSvg.js @@ -8,16 +8,23 @@ */ import React from 'react' import PropTypes from 'prop-types' +import compose from 'recompose/compose' +import defaultProps from 'recompose/defaultProps' +import withPropsOnChange from 'recompose/withPropsOnChange' import pure from 'recompose/pure' +import setDisplayName from 'recompose/setDisplayName' +import { line } from 'd3-shape' import { SmartMotion, motionPropTypes, defaultAnimate, defaultMotionDamping, defaultMotionStiffness, + curvePropType, + curveFromProp, } from '@nivo/core' -const Line = ({ +const LineSvg = ({ data, generator, xScale, @@ -55,7 +62,7 @@ const Line = ({ ) } -Line.propTypes = { +LineSvg.propTypes = { data: PropTypes.arrayOf( PropTypes.shape({ x: PropTypes.number, @@ -66,6 +73,8 @@ Line.propTypes = { xScale: PropTypes.func.isRequired, yScale: PropTypes.func.isRequired, + curve: curvePropType.isRequired, + // style size: PropTypes.number.isRequired, @@ -73,14 +82,26 @@ Line.propTypes = { ...motionPropTypes, } -Line.defaultProps = { - // style - size: 2, +const enhance = compose( + defaultProps({ + curve: 'linear', - // motion - animate: defaultAnimate, - motionDamping: defaultMotionDamping, - motionStiffness: defaultMotionStiffness, -} + // style + size: 2, + + // motion + animate: defaultAnimate, + motionDamping: defaultMotionDamping, + motionStiffness: defaultMotionStiffness, + }), + withPropsOnChange(['curve'], ({ curve }) => ({ + generator: line() + .defined(d => d && d.x !== null && d.y !== null) + .x(d => d.x) + .y(d => d.y) + .curve(curveFromProp(curve)), + })), + pure +) -export default pure(Line) +export default setDisplayName('LineSvg')(enhance(LineSvg)) diff --git a/packages/nivo-line/src/svg/ResponsiveLineChartSvg.js b/packages/nivo-line/src/svg/ResponsiveLineChartSvg.js new file mode 100644 index 000000000..38410c79b --- /dev/null +++ b/packages/nivo-line/src/svg/ResponsiveLineChartSvg.js @@ -0,0 +1,19 @@ +/* + * 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 { ResponsiveWrapper } from '@nivo/core' +import LineChartSvg from './LineChartSvg' + +const ResponsiveLineChartSvg = props => ( + + {({ width, height }) => } + +) + +export default ResponsiveLineChartSvg diff --git a/packages/nivo-line/src/svg/index.js b/packages/nivo-line/src/svg/index.js index fa9bcd009..4054cf737 100644 --- a/packages/nivo-line/src/svg/index.js +++ b/packages/nivo-line/src/svg/index.js @@ -8,3 +8,5 @@ */ export { default as LineSvg } from './LineSvg' export { default as LineAreaSvg } from './LineAreaSvg' +export { default as LineChartSvg } from './LineChartSvg' +export { default as ResponsiveLineChartSvg } from './ResponsiveLineChartSvg' diff --git a/website/src/SiteMap.js b/website/src/SiteMap.js index 4ac904d4d..db59181a8 100644 --- a/website/src/SiteMap.js +++ b/website/src/SiteMap.js @@ -229,7 +229,7 @@ const SITEMAP = [ { className: 'react', path: '/', - label: 'Line', + label: 'LineChartSvg', component: Line, exact: true, tags: ['svg', 'isomorphic'], diff --git a/website/src/components/charts/line/Line/index.js b/website/src/components/charts/line/Line/index.js index ac76e360d..5688d31ca 100644 --- a/website/src/components/charts/line/Line/index.js +++ b/website/src/components/charts/line/Line/index.js @@ -11,11 +11,7 @@ import omit from 'lodash/omit' import { Link } from 'react-router-dom' import MediaQuery from 'react-responsive' import { generatePointsSerie } from '@nivo/generators' -import { ResponsiveWrapper } from '@nivo/core' -import { Scales, LinearScaleX, LinearScaleY } from '@nivo/scales' -import { XAxis, YAxis, Grid } from '@nivo/axes' -import { LineSvg, LineDefaultProps, Lines, LineAreas, LineAreaSvg } from '@nivo/line' -import { defaultTheme } from '@nivo/core' +import { LineDefaultProps, ResponsiveLineChartSvg } from '@nivo/line' import ChartHeader from '../../../ChartHeader' import ChartTabs from '../../../ChartTabs' import LineControls from '../LineControls' @@ -27,36 +23,21 @@ import defaultProps from '../defaultProps' import propsMapper from '../propsMapper' const generateData = () => { - const a = generatePointsSerie({ - x1: 120, - xStep: 2, - y0: 10, - y1: 80, - yRand: 3, - easing: 'random', - }) - - const b = generatePointsSerie({ - x1: 90, - xStep: 1, - y0: 0, - y1: 42, - yRand: 12, - easing: 'random', - }) + const keys = ['A', 'B', 'C', 'D', 'E'] - const c = generatePointsSerie({ - x0: 5, - x1: 120, - xStep: 3, - y0: 24, - y1: 2, - yRand: 3, - easing: 'random', - xGaps: [[35, 45], [85, 95]], + return keys.map((key, i) => { + return { + id: key, + data: generatePointsSerie({ + x1: 120, + xStep: 10, + y0: Math.random() * 80, + y1: Math.random() * 80, + yRand: 3, + easing: 'random', + }), + } }) - - return { a, b, c } } export default class LinePage extends Component { @@ -91,14 +72,14 @@ export default class LinePage extends Component { const mappedSettings = propsMapper(settings) - const code = generateCode('ResponsiveLine', mappedSettings, { + const code = generateCode('ResponsiveLineChartSvg', mappedSettings, { pkg: '@nivo/line', defaults: LineDefaultProps, }) const header = ( @@ -158,198 +139,7 @@ export default class LinePage extends Component { {description} - - {({ width, height }) => ( - - , - , - , - ]} - > - {scales => ( - - - - - - {settings.enableAreas && ( - - {generator => ( - - - - - - )} - - )} - - {generator => ( - - - - - - )} - - - )} - - - )} - + { + return dedent(` + import React, { Fragment } from 'react' + import { + Scales, LinearScaleX, LinearScaleY, + AxisX, AxisY, + Lines, Line, + LineAreas, LineArea, + } from '@nivo/line' + + , + , + + ]}> + {scales => ( + + + + + + {generator => ( + + + + + )} + + + {generator => ( + + + + + )} + + + )} + + `) +} diff --git a/website/src/components/charts/line/LineComposite/index.js b/website/src/components/charts/line/LineComposite/index.js new file mode 100644 index 000000000..3e17dfc1b --- /dev/null +++ b/website/src/components/charts/line/LineComposite/index.js @@ -0,0 +1,362 @@ +/* + * 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, Fragment } from 'react' +import omit from 'lodash/omit' +import { Link } from 'react-router-dom' +import MediaQuery from 'react-responsive' +import { generatePointsSerie } from '@nivo/generators' +import { ResponsiveWrapper } from '@nivo/core' +import { Scales, LinearScaleX, LinearScaleY } from '@nivo/scales' +import { XAxis, YAxis, Grid } from '@nivo/axes' +import { LineSvg, LineDefaultProps, LineAreas, LineAreaSvg } from '@nivo/line' +import { defaultTheme } from '@nivo/core' +import ChartHeader from '../../../ChartHeader' +import ChartTabs from '../../../ChartTabs' +import LineControls from '../LineControls' +import generateCode from '../../../../lib/generateChartCode' +import ComponentPropsDocumentation from '../../../properties/ComponentPropsDocumentation' +import properties from '../props' +import config from '../../../../config' +import defaultProps from '../defaultProps' +import propsMapper from '../propsMapper' + +const generateData = () => { + const a = generatePointsSerie({ + x1: 120, + xStep: 2, + y0: 10, + y1: 80, + yRand: 3, + easing: 'random', + }) + + const b = generatePointsSerie({ + x1: 90, + xStep: 1, + y0: 0, + y1: 42, + yRand: 12, + easing: 'random', + }) + + const c = generatePointsSerie({ + x0: 5, + x1: 120, + xStep: 3, + y0: 24, + y1: 2, + yRand: 3, + easing: 'random', + xGaps: [[35, 45], [85, 95]], + }) + + return { a, b, c } +} + +export default class LinePage extends Component { + state = { + data: generateData(), + settings: { + ...omit(defaultProps, ['width', 'height']), + legends: [ + { + anchor: 'bottom-right', + direction: 'column', + translateX: 100, + itemWidth: 80, + itemHeight: 20, + symbolSize: 12, + symbolShape: 'circle', + }, + ], + }, + } + + diceRoll = () => { + this.setState({ data: generateData() }) + } + + handleSettingsUpdate = settings => { + this.setState({ settings }) + } + + render() { + const { data, settings } = this.state + + const mappedSettings = propsMapper(settings) + + const code = generateCode('ResponsiveLine', mappedSettings, { + pkg: '@nivo/line', + defaults: LineDefaultProps, + }) + + const header = ( + + ) + + const description = ( +
+

Line chart with stacking ability.

+

+ Given an array of data series having an id and a nested array of points (with x, + y properties), it will compute the line for each data serie.  If stacked is + true, y values will be automatically aggregated.
+ This component also accept empty values, but please note that they must be + explicitly defined though, eg. {'{ x: 10, y: null }'}. +

+

+ The responsive alternative of this component is ResponsiveLine. +

+

+ This component is available in the{' '} + + nivo-api + , see{' '} + + sample + {' '} + or try it using the API client. You can also see + more example usages in{' '} + + the storybook + . +

+

+ See the dedicated guide on how to setup + legends for this component. +

+
+ ) + + return ( +
+
+ + {header} + {description} + + + + {({ width, height }) => ( + + , + , + , + ]} + > + {scales => ( + + + + + + + + + + + + + )} + + + )} + + + + +
+
+ + {header} + {description} + +
+
+ ) + } +} diff --git a/website/src/components/charts/line/defaultProps.js b/website/src/components/charts/line/defaultProps.js index 1b95155a5..6f927224a 100644 --- a/website/src/components/charts/line/defaultProps.js +++ b/website/src/components/charts/line/defaultProps.js @@ -83,7 +83,8 @@ export default { dotLabelYOffset: -12, // area - enableAreas: false, + enableArea: true, + enableAreas: true, areaOpacity: 0.2, // motion