UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

126 lines (115 loc) 5.26 kB
import _get from "lodash/get"; import _map from "lodash/map"; import _keys from "lodash/keys"; import _last from "lodash/last"; import _flatten from "lodash/flatten"; import _max from "lodash/max"; import _isDate from "lodash/isDate"; import _isFinite from "lodash/isFinite"; import _first from "lodash/first"; import _every from "lodash/every"; function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } import React from 'react'; import PropTypes from 'react-peek/prop-types'; import { lucidClassNames } from '../../util/style-helpers'; import { omitProps } from '../../util/component-types'; import { groupByFields } from '../../util/chart-helpers'; import * as d3Shape from 'd3-shape'; import * as chartConstants from '../../constants/charts'; import Line from '../Line/Line'; var cx = lucidClassNames.bind('&-Lines'); var arrayOf = PropTypes.arrayOf, func = PropTypes.func, number = PropTypes.number, object = PropTypes.object, bool = PropTypes.bool, string = PropTypes.string; var isUniform = function isUniform(array) { return _every(array, function (val) { return val === _first(array); }); }; var defaultProps = { xField: 'x', yFields: ['y'], isStacked: false, colorOffset: 0, palette: chartConstants.PALETTE_7 }; export var Lines = function Lines(props) { var className = props.className, data = props.data, isStacked = props.isStacked, palette = props.palette, colorMap = props.colorMap, colorOffset = props.colorOffset, xScale = props.xScale, xField = props.xField, yFields = props.yFields, yScaleOriginal = props.yScale, yStackedMax = props.yStackedMax, passThroughs = _objectWithoutProperties(props, ["className", "data", "isStacked", "palette", "colorMap", "colorOffset", "xScale", "xField", "yFields", "yScale", "yStackedMax"]); // Copy the original so we can mutate it var yScale = yScaleOriginal.copy(); // If we are stacked, we need to calculate a new domain based on the sum of // the various series' y data. One row per series. var transformedData = isStacked ? d3Shape.stack().keys(yFields)(data) : groupByFields(data, yFields); var stackedArea = d3Shape.area().defined(function (a) { return _isFinite(a[0]) && _isFinite(a[1]); }).x(function (a, i) { return xScale(data[i][xField]); }).y0(function (a) { return yScale(a[1]); }).y1(function (a) { return yScale(a[0]); }); var area = d3Shape.area().defined(function (a) { return _isFinite(a) || _isDate(a); }).x(function (a, i) { return xScale(data[i][xField]); }).y(function (a, i) { return yScale(a); }); // If we are stacked, we need to calculate a new domain based on the sum of // the various group's y data if (isStacked) { yScale.domain([yScale.domain()[0], // only stacks well if this is `0` yStackedMax || _max(_flatten(_last(transformedData)))]); } return /*#__PURE__*/React.createElement("g", _extends({}, omitProps(passThroughs, undefined, _keys(Lines.propTypes)), { className: cx(className, '&') }), _map(transformedData, function (d, dIndex) { return /*#__PURE__*/React.createElement("g", { key: dIndex }, /*#__PURE__*/React.createElement(Line, { color: _get(colorMap, yFields[dIndex], palette[(dIndex + colorOffset) % palette.length]), d: isStacked ? stackedArea(d) : area(d) // Fixes a bug in chrome by forcing a reflow of the element (ANXR-1405) , style: isUniform(d) ? { transform: 'scaleX(0.999)' } : undefined })); })); }; Lines.defaultProps = defaultProps; Lines.displayName = 'Lines'; Lines.peek = { description: "\n\t\t*For use within an `svg`*\n\n\t\tLines are typically used to represent continuous data and can be\n\t\tstacked.\n\t", categories: ['visualizations', 'chart primitives'], madeFrom: ['Line'] }; Lines.propTypes = { className: string, top: number, left: number, palette: arrayOf(string), colorMap: object, data: arrayOf(object).isRequired, xScale: func.isRequired, yScale: func.isRequired, yStackedMax: number, xField: string, yFields: arrayOf(string), isStacked: bool, colorOffset: number }; export default Lines;