lucid-ui
Version:
A UI component library from AppNexus.
126 lines (115 loc) • 5.26 kB
JavaScript
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;