recharts
Version:
React charts
1,255 lines (1,036 loc) • 41.7 kB
JavaScript
'use strict';
var _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; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _class, _temp; /**
* @fileOverview Cartesian Chart
*/
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
var _rechartsScale = require('recharts-scale');
var _d3Scale = require('d3-scale');
var _d3Scale2 = _interopRequireDefault(_d3Scale);
var _d3Shape = require('d3-shape');
var _d3Shape2 = _interopRequireDefault(_d3Shape);
var _invariant = require('invariant');
var _invariant2 = _interopRequireDefault(_invariant);
var _ouiDomUtils = require('oui-dom-utils');
var _ouiDomUtils2 = _interopRequireDefault(_ouiDomUtils);
var _Layer = require('../container/Layer');
var _Layer2 = _interopRequireDefault(_Layer);
var _Tooltip = require('../component/Tooltip');
var _Tooltip2 = _interopRequireDefault(_Tooltip);
var _Legend = require('../component/Legend');
var _Legend2 = _interopRequireDefault(_Legend);
var _ReactUtils = require('../util/ReactUtils');
var _ReactUtils2 = _interopRequireDefault(_ReactUtils);
var _DOMUtils = require('../util/DOMUtils');
var _DOMUtils2 = _interopRequireDefault(_DOMUtils);
var _LodashUtils = require('../util/LodashUtils');
var _LodashUtils2 = _interopRequireDefault(_LodashUtils);
var _CartesianAxis = require('../cartesian/CartesianAxis');
var _CartesianAxis2 = _interopRequireDefault(_CartesianAxis);
var _CartesianGrid = require('../cartesian/CartesianGrid');
var _CartesianGrid2 = _interopRequireDefault(_CartesianGrid);
var _ReferenceLine = require('../cartesian/ReferenceLine');
var _ReferenceLine2 = _interopRequireDefault(_ReferenceLine);
var _XAxis = require('../cartesian/XAxis');
var _XAxis2 = _interopRequireDefault(_XAxis);
var _YAxis = require('../cartesian/YAxis');
var _YAxis2 = _interopRequireDefault(_YAxis);
var _Brush = require('../cartesian/Brush');
var _Brush2 = _interopRequireDefault(_Brush);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var ORIENT_MAP = {
xAxis: ['bottom', 'top'],
yAxis: ['left', 'right']
};
/**
* The base class of chart in cartesian coordinate system
*/
var CartesianChart = (_temp = _class = function (_Component) {
_inherits(CartesianChart, _Component);
function CartesianChart(props) {
_classCallCheck(this, CartesianChart);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(CartesianChart).call(this, props));
_this.state = {
dataStartIndex: 0,
dataEndIndex: _this.props.data.length - 1,
activeTooltipIndex: -1,
activeTooltipLabel: '',
activeTooltipCoord: { x: 0, y: 0 },
isTooltipActive: false,
activeLineKey: null,
activeBarKey: null
};
_this.validateAxes();
return _this;
}
_createClass(CartesianChart, [{
key: 'getStackGroupsByAxisId',
value: function getStackGroupsByAxisId(items, axisIdKey) {
var _this2 = this;
var stackGroups = items.reduce(function (result, item) {
var _item$props = item.props;
var stackId = _item$props.stackId;
var dataKey = _item$props.dataKey;
var axisId = item.props[axisIdKey];
if (!result[axisId]) {
result[axisId] = { hasStack: false, stackGroups: {} };
}
if (_LodashUtils2.default.isNumber(stackId) || _LodashUtils2.default.isString(stackId)) {
if (!result[axisId].stackGroups[stackId]) {
result[axisId].stackGroups[stackId] = {
items: []
};
}
result[axisId].stackGroups[stackId].items.push(item);
if (result[axisId].stackGroups[stackId].items.length >= 2) {
result[axisId].hasStack = true;
}
} else {
result[axisId].stackGroups[_LodashUtils2.default.getUniqueId('_stackId_')] = {
items: [item]
};
}
return result;
}, {});
return Object.keys(stackGroups).reduce(function (result, axisId) {
var group = stackGroups[axisId];
if (group.hasStack) {
group.stackGroups = Object.keys(group.stackGroups).reduce(function (res, stackId) {
var g = group.stackGroups[stackId];
res[stackId] = {
items: g.items,
stackedData: _this2.getStackedData(g.items)
};
return res;
}, {});
}
result[axisId] = group;
return result;
}, {});
}
}, {
key: 'getStackedData',
value: function getStackedData(stackItems) {
var data = this.props.data;
var dataKeys = stackItems.map(function (item) {
return item.props.dataKey;
});
var stack = _d3Shape2.default.stack().keys(dataKeys).value(function (d, key) {
return +d[key] || 0;
}).order(_d3Shape2.default.stackOrderNone).offset(_d3Shape2.default.stackOffsetNone);
return stack(data);
}
}, {
key: 'getStackedDataOfItem',
value: function getStackedDataOfItem(item, stackGroups) {
var stackId = item.props.stackId;
if (_LodashUtils2.default.isNumber(stackId) || _LodashUtils2.default.isString(stackId)) {
var group = stackGroups[stackId];
if (group && group.items.length) {
var itemIndex = -1;
for (var i = 0, len = group.items.length; i < len; i++) {
if (group.items[i] === item) {
itemIndex = i;
break;
}
}
return itemIndex >= 0 ? group.stackedData[itemIndex] : null;
}
}
return null;
}
/**
* Calculate coordinate of cursor in chart
* @param {Object} e Event object
* @param {Object} containerOffset The offset of main part in the svg element
* @return {Object} {chartX, chartY}
*/
}, {
key: 'getChartPosition',
value: function getChartPosition(e, containerOffset) {
return {
chartX: Math.round(e.pageX - containerOffset.left),
chartY: Math.round(e.pageY - containerOffset.top)
};
}
/**
* get domain of ticks
* @param {Array} ticks Ticks of axis
* @param {String} type The type of axis
* @return {Array} domain
*/
}, {
key: 'getDomainOfTicks',
value: function getDomainOfTicks(ticks, type) {
if (type === 'number') {
return [Math.min.apply(null, ticks), Math.max.apply(null, ticks)];
}
return ticks;
}
/**
* Get domain of data by key
* @param {String} key The unique key of a group of data
* @param {String} type The type of axis
* @return {Array} Domain of data
*/
}, {
key: 'getDomainByKey',
value: function getDomainByKey(key, type) {
var data = this.props.data;
var _state = this.state;
var dataStartIndex = _state.dataStartIndex;
var dataEndIndex = _state.dataEndIndex;
var domain = data.slice(dataStartIndex, dataEndIndex + 1).map(function (entry) {
return entry[key] || 0;
});
return type === 'number' ? [Math.min.apply(null, domain), Math.max.apply(null, domain)] : domain;
}
}, {
key: 'getDomainOfStackGroups',
value: function getDomainOfStackGroups(stackGroups) {
var _state2 = this.state;
var dataStartIndex = _state2.dataStartIndex;
var dataEndIndex = _state2.dataEndIndex;
return Object.keys(stackGroups).reduce(function (result, stackId) {
var group = stackGroups[stackId];
var stackedData = group.stackedData;
var minList = stackedData[0].slice(dataStartIndex, dataEndIndex + 1);
var maxList = stackedData[stackedData.length - 1].slice(dataStartIndex, dataEndIndex + 1);
var min = minList.reduce(function (res, entry) {
return Math.min(res, entry[0]);
}, Infinity);
var max = maxList.reduce(function (res, entry) {
return Math.max(res, entry[1]);
}, -Infinity);
return [Math.min(min, result[0]), Math.max(max, result[1])];
}, [Infinity, -Infinity]);
}
/**
* Get domain of data by the configuration of item element
* @param {Array} items The instances of item
* @param {String} type The type of axis, number - Number Axis, category - Category Axis
* @return {Array} Domain
*/
}, {
key: 'getDomainOfItemsWithSameAxis',
value: function getDomainOfItemsWithSameAxis(items, type) {
var _this3 = this;
var domains = items.map(function (item) {
return _this3.getDomainByKey(item.props.dataKey, type);
});
if (type === 'number') {
// Calculate the domain of number axis
return domains.reduce(function (result, entry) {
return [Math.min(result[0], entry[0]), Math.max(result[1], entry[1])];
}, [Infinity, -Infinity]);
}
var tag = {};
// Get the union set of category axis
return domains.reduce(function (result, entry) {
for (var i = 0, len = entry.length; i < len; i++) {
if (!tag[entry[i]]) {
tag[entry[i]] = true;
result.push(entry[i]);
}
}
return result;
}, []);
}
/**
* Get the configuration of all x-axis or y-axis
* @param {String} axisType The type of axis
* @param {Array} items The instances of item
* @param {Object} stackGroups The items grouped by axisId and stackId
* @return {Object} Configuration
*/
}, {
key: 'getAxisMap',
value: function getAxisMap() {
var axisType = arguments.length <= 0 || arguments[0] === undefined ? 'xAxis' : arguments[0];
var items = arguments[1];
var stackGroups = arguments[2];
var children = this.props.children;
var Axis = axisType === 'xAxis' ? _XAxis2.default : _YAxis2.default;
var axisIdKey = axisType === 'xAxis' ? 'xAxisId' : 'yAxisId';
// Get all the instance of Axis
var axes = _ReactUtils2.default.findAllByType(children, Axis);
var axisMap = {};
if (axes && axes.length) {
axisMap = this.getAxisMapByAxes(axes, items, axisType, axisIdKey, stackGroups);
} else if (items && items.length) {
axisMap = this.getAxisMapByItems(items, Axis, axisType, axisIdKey, stackGroups);
}
return axisMap;
}
/**
* Get the configuration of axis by the options of axis instance
* @param {Array} axes The instance of axes
* @param {Array} items The instances of item
* @param {String} axisType The type of axis, xAxis - x-axis, yAxis - y-axis
* @param {String} axisIdKey The unique id of an axis
* @param {Object} stackGroups The items grouped by axisId and stackId
* @return {Object} Configuration
*/
}, {
key: 'getAxisMapByAxes',
value: function getAxisMapByAxes(axes, items, axisType, axisIdKey, stackGroups) {
var _this4 = this;
var layout = this.props.layout;
var _state3 = this.state;
var dataEndIndex = _state3.dataEndIndex;
var dataStartIndex = _state3.dataStartIndex;
var len = dataEndIndex - dataStartIndex + 1;
var isCategoryAxis = layout === 'horizontal' && axisType === 'xAxis' || layout === 'vertical' && axisType === 'yAxis';
// Eliminate duplicated axes
var axisMap = axes.reduce(function (result, child) {
var _child$props = child.props;
var type = _child$props.type;
var dataKey = _child$props.dataKey;
var axisId = child.props[axisIdKey];
if (!result[axisId]) {
var domain = undefined;
var isDomainFixed = false;
if (dataKey) {
domain = _this4.getDomainByKey(dataKey, type);
} else if (stackGroups && stackGroups[axisId] && stackGroups[axisId].hasStack && type === 'number') {
domain = _this4.getDomainOfStackGroups(stackGroups[axisId].stackGroups);
} else if (isCategoryAxis) {
domain = _LodashUtils2.default.range(0, len);
} else {
domain = _this4.getDomainOfItemsWithSameAxis(items.filter(function (entry) {
return entry.props[axisIdKey] === axisId;
}), type);
}
if (type === 'number' && child.props.domain) {
isDomainFixed = true;
domain = _this4.parseSpecifiedDomain(child.props.domain, domain);
}
return _extends({}, result, _defineProperty({}, axisId, _extends({}, child.props, {
axisType: axisType,
domain: domain,
isDomainFixed: isDomainFixed
})));
}
return result;
}, {});
return axisMap;
}
/**
* Get the configuration of axis by the options of item, this kind of axis does not display in chart
* @param {Array} items The instances of item
* @param {ReactElement} Axis Axis Component
* @param {String} axisType The type of axis, xAxis - x-axis, yAxis - y-axis
* @param {String} axisIdKey The unique id of an axis
* @param {Object} stackGroups The items grouped by axisId and stackId
* @return {Object} Configuration
*/
}, {
key: 'getAxisMapByItems',
value: function getAxisMapByItems(items, Axis, axisType, axisIdKey, stackGroups) {
var _this5 = this;
var layout = this.props.layout;
var _state4 = this.state;
var dataEndIndex = _state4.dataEndIndex;
var dataStartIndex = _state4.dataStartIndex;
var len = dataEndIndex - dataStartIndex + 1;
var index = -1;
var isCategoryAxis = layout === 'horizontal' && axisType === 'xAxis' || layout === 'vertical' && axisType === 'yAxis';
// The default type of x-axis is category axis,
// The default contents of x-axis is the serial numbers of data
// The default type of y-axis is number axis
// The default contents of y-axis is the domain of data
var axisMap = items.reduce(function (result, child) {
var axisId = child.props[axisIdKey];
if (!result[axisId]) {
index++;
var domain = undefined;
if (isCategoryAxis) {
domain = _LodashUtils2.default.range(0, len);
} else if (stackGroups && stackGroups[axisId] && stackGroups[axisId].hasStack) {
domain = _this5.getDomainOfStackGroups(stackGroups[axisId].stackGroups);
} else {
domain = _this5.getDomainOfItemsWithSameAxis(items.filter(function (entry) {
return entry.props[axisIdKey] === axisId;
}), 'number');
}
return _extends({}, result, _defineProperty({}, axisId, {
axisType: axisType,
type: Axis.defaultProps.type,
hide: true,
isAutoGenerated: true,
width: Axis.defaultProps.width,
height: Axis.defaultProps.height,
tickCount: Axis.defaultProps.tickCount,
orientation: ORIENT_MAP[axisType][index % 2],
domain: domain
}));
}
return result;
}, {});
return axisMap;
}
/**
* Calculate the offset of main part in the svg element
* @param {Object} xAxisMap The configuration of x-axis
* @param {Object} yAxisMap The configuration of y-axis
* @return {Object} The offset of main part in the svg element
*/
}, {
key: 'getOffset',
value: function getOffset(xAxisMap, yAxisMap) {
var _props = this.props;
var width = _props.width;
var height = _props.height;
var margin = _props.margin;
var children = _props.children;
var brushItem = _ReactUtils2.default.findChildByType(children, _Brush2.default);
var offsetH = Object.keys(yAxisMap).reduce(function (result, id) {
var entry = yAxisMap[id];
var orientation = entry.orientation;
result[orientation] += entry.hide ? 0 : entry.width;
return result;
}, { left: margin.left || 0, right: margin.right || 0 });
var offsetV = Object.keys(xAxisMap).reduce(function (result, id) {
var entry = xAxisMap[id];
var orientation = entry.orientation;
result[orientation] += entry.hide ? 0 : entry.height;
return result;
}, { top: margin.top || 0, bottom: margin.bottom || 0 });
if (brushItem) {
offsetV.bottom += brushItem.props.height || _Brush2.default.defaultProps.height;
}
return _extends({}, offsetH, offsetV, {
width: width - offsetH.left - offsetH.right,
height: height - offsetV.top - offsetV.bottom
});
}
/**
* Get the main color of each graphic item
* @param {ReactElement} item A graphic item
* @return {String} Color
*/
}, {
key: 'getMainColorOfItem',
value: function getMainColorOfItem(item) {
var displayName = item.type.displayName;
var result = undefined;
switch (displayName) {
case 'Line':
result = item.props.stroke;
break;
default:
result = item.props.fill;
break;
}
return result;
}
/**
* Configure the scale function of axis
* @param {Object} scale The scale function
* @param {Object} opts The configuration of axis
* @return {Object} null
*/
}, {
key: 'setTicksOfScale',
value: function setTicksOfScale(scale, opts) {
// Give priority to use the options of ticks
if (opts.ticks && opts.ticks) {
scale.domain(this.getDomainOfTicks(opts.ticks, opts.type));
return;
}
if (opts.type === 'number' && opts.isAutoGenerated) {
scale.domain([0, scale.domain()[1]]);
} else if (opts.tickCount && opts.type === 'number' && !opts.isDomainFixed) {
// Calculate the ticks by the number of grid when the axis is a number axis
var domain = scale.domain();
var tickValues = (0, _rechartsScale.getNiceTickValues)(domain, opts.tickCount);
opts.ticks = tickValues;
scale.domain(this.getDomainOfTicks(tickValues, opts.type));
}
}
/**
* Calculate the scale function, position, width, height of axes
* @param {Object} axisMap The configuration of axes
* @param {Object} offset The offset of main part in the svg element
* @param {Object} axisType The type of axes, x-axis or y-axis
* @return {Object} Configuration
*/
}, {
key: 'getFormatAxisMap',
value: function getFormatAxisMap(axisMap, offset, axisType) {
var _this6 = this;
var _props2 = this.props;
var width = _props2.width;
var height = _props2.height;
var layout = _props2.layout;
var displayName = this.constructor.displayName;
var ids = Object.keys(axisMap);
var steps = {
left: offset.left,
right: width - offset.right,
top: offset.top,
bottom: height - offset.bottom
};
return ids.reduce(function (result, id) {
var axis = axisMap[id];
var orientation = axis.orientation;
var type = axis.type;
var domain = axis.domain;
var range = undefined;
if (axisType === 'xAxis') {
range = [offset.left, offset.left + offset.width];
} else {
range = layout === 'horizontal' ? [offset.top + offset.height, offset.top] : [offset.top, offset.top + offset.height];
}
var scale = undefined;
if (type === 'number') {
scale = _d3Scale2.default.linear().domain(domain).range(range);
} else if (displayName === 'LineChart' || displayName === 'AreaChart') {
scale = _d3Scale2.default.point().domain(domain).range(range);
} else {
scale = _d3Scale2.default.band().domain(domain).range(range);
}
_this6.setTicksOfScale(scale, axis);
var x = undefined;
var y = undefined;
if (axisType === 'xAxis') {
x = offset.left;
y = orientation === 'top' ? steps[orientation] - axis.height : steps[orientation];
} else {
x = orientation === 'left' ? steps[orientation] - axis.width : steps[orientation];
y = offset.top;
}
result[id] = _extends({}, axis, {
x: x, y: y, scale: scale,
width: axisType === 'xAxis' ? offset.width : axis.width,
height: axisType === 'yAxis' ? offset.height : axis.height
});
if (!axis.hide && axisType === 'xAxis') {
steps[orientation] += (orientation === 'top' ? -1 : 1) * result[id].height;
} else if (!axis.hide) {
steps[orientation] += (orientation === 'left' ? -1 : 1) * result[id].width;
}
return result;
}, {});
}
/**
* Get the ticks of an axis
* @param {Object} axis The configuration of an axis
* @param {Boolean} isGrid Whether or not are the ticks in grid
* @return {Array} Ticks
*/
}, {
key: 'getAxisTicks',
value: function getAxisTicks(axis) {
var isGrid = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
var scale = axis.scale;
var offset = isGrid && axis.type === 'category' ? scale.bandwidth() / 2 : 0;
if (axis.ticks) {
return axis.ticks.map(function (entry) {
return { coord: scale(entry) + offset, value: entry };
});
}
if (scale.ticks) {
return scale.ticks(axis.tickCount).map(function (entry) {
return { coord: scale(entry) + offset, value: entry };
});
}
return scale.domain().map(function (entry) {
return { coord: scale(entry) + offset, value: entry };
});
}
/**
* Calculate the ticks of grid
* @param {Array} ticks The ticks in axis
* @param {Number} min The minimun value of axis
* @param {Number} max The maximun value of axis
* @return {Array} Ticks
*/
}, {
key: 'getGridTicks',
value: function getGridTicks(ticks, min, max) {
var hasMin = undefined;
var hasMax = undefined;
var values = undefined;
values = ticks.map(function (entry) {
if (entry.coord === min) {
hasMin = true;
}
if (entry.coord === max) {
hasMax = true;
}
return entry.coord;
});
if (!hasMin) {
values.push(min);
}
if (!hasMax) {
values.push(max);
}
return values;
}
/**
* Get the information of mouse in chart, return null when the mouse is not in the chart
* @param {Object} xAxisMap The configuration of all x-axes
* @param {Object} yAxisMap The configuration of all y-axes
* @param {Object} offset The offset of main part in the svg element
* @param {Object} e The event object
* @return {Object} Mouse data
*/
}, {
key: 'getMouseInfo',
value: function getMouseInfo(xAxisMap, yAxisMap, offset, e) {
var isIn = e.chartX >= offset.left && e.chartX <= offset.left + offset.width && e.chartY >= offset.top && e.chartY <= offset.top + offset.height;
if (!isIn) {
return null;
}
var layout = this.props.layout;
var axisMap = layout === 'horizontal' ? xAxisMap : yAxisMap;
var pos = layout === 'horizontal' ? e.chartX : e.chartY;
var ids = Object.keys(axisMap);
var axis = axisMap[ids[0]];
var ticks = this.getAxisTicks(axis, true);
var index = 0;
var len = ticks.length;
if (len > 1) {
for (var i = 0; i < len; i++) {
if (i === 0 && pos <= (ticks[i].coord + ticks[i + 1].coord) / 2 || i > 0 && i < len - 1 && pos > (ticks[i].coord + ticks[i - 1].coord) / 2 && pos <= (ticks[i].coord + ticks[i + 1].coord) / 2 || i === len - 1 && pos > (ticks[i].coord + ticks[i - 1].coord) / 2) {
index = i;
break;
}
}
}
return {
activeTooltipIndex: index,
activeTooltipLabel: ticks[index].value,
activeTooltipCoord: {
x: layout === 'horizontal' ? ticks[index].coord : e.chartX,
y: layout === 'horizontal' ? e.chartY : ticks[index].coord
}
};
}
/**
* Get the content to be displayed in the tooltip
* @param {Array} items The instances of item
* @return {Array} The content of tooltip
*/
}, {
key: 'getTooltipContent',
value: function getTooltipContent(items) {
var _this7 = this;
var _state5 = this.state;
var activeLineKey = _state5.activeLineKey;
var activeBarKey = _state5.activeBarKey;
var activeAreaKey = _state5.activeAreaKey;
var activeTooltipIndex = _state5.activeTooltipIndex;
var dataStartIndex = _state5.dataStartIndex;
var dataEndIndex = _state5.dataEndIndex;
var data = this.props.data.slice(dataStartIndex, dataEndIndex + 1);
if (activeTooltipIndex < 0 || !items || !items.length) {
return null;
}
var activeItems = items;
if (activeLineKey) {
activeItems = items.filter(function (item) {
return item.props.dataKey === activeLineKey && item.type.displayName === 'Line';
});
} else if (activeBarKey) {
activeItems = items.filter(function (item) {
return item.props.dataKey === activeBarKey && item.type.displayName === 'Bar';
});
} else if (activeAreaKey) {
activeItems = items.filter(function (item) {
return item.props.dataKey === activeAreaKey && item.type.displayName === 'Area';
});
}
return activeItems.map(function (child) {
var _child$props2 = child.props;
var dataKey = _child$props2.dataKey;
var name = _child$props2.name;
var unit = _child$props2.unit;
var formatter = _child$props2.formatter;
return {
key: name || dataKey,
unit: unit || '',
color: _this7.getMainColorOfItem(child),
value: data[activeTooltipIndex][dataKey],
formatter: formatter
};
});
}
}, {
key: 'validateAxes',
value: function validateAxes() {
var _props3 = this.props;
var layout = _props3.layout;
var children = _props3.children;
var xAxes = _ReactUtils2.default.findAllByType(children, _XAxis2.default);
var yAxes = _ReactUtils2.default.findAllByType(children, _YAxis2.default);
if (layout === 'horizontal' && xAxes && xAxes.length) {
xAxes.forEach(function (axis) {
(0, _invariant2.default)(axis.props.type === 'category', 'x-axis should be category axis when the layout is horizontal');
});
} else if (layout === 'vertical') {
var displayName = this.constructor.displayName;
(0, _invariant2.default)(yAxes && yAxes.length, 'You should add <YAxis type="number"/> in ' + displayName + '.' + 'The layout is vertical now, y-axis should be category axis,' + 'but y-axis is number axis when no YAxis is added.');
(0, _invariant2.default)(xAxes && xAxes.length, 'You should add <XAxis /> in ' + displayName + '.' + 'The layout is vertical now, x-axis is category when no XAxis is added.');
if (yAxes && yAxes.length) {
yAxes.forEach(function (axis) {
(0, _invariant2.default)(axis.props.type === 'category', 'y-axis should be category axis when the layout is vertical');
});
}
}
return null;
}
}, {
key: 'parseSpecifiedDomain',
value: function parseSpecifiedDomain(specifiedDomain, autoDomain) {
if (!_LodashUtils2.default.isArray(specifiedDomain)) {
return autoDomain;
}
var domain = [];
if (!_LodashUtils2.default.isNumber(specifiedDomain[0]) || specifiedDomain[0] > autoDomain[0]) {
domain[0] = autoDomain[0];
} else {
domain[0] = specifiedDomain[0];
}
if (!_LodashUtils2.default.isNumber(specifiedDomain[1]) || specifiedDomain[1] < autoDomain[1]) {
domain[1] = autoDomain[1];
} else {
domain[1] = specifiedDomain[1];
}
return domain;
}
}, {
key: 'handleBrushChange',
value: function handleBrushChange(_ref) {
var startIndex = _ref.startIndex;
var endIndex = _ref.endIndex;
this.setState({
dataStartIndex: startIndex,
dataEndIndex: endIndex
});
}
/**
* The handler of mouse entering chart
* @param {Object} offset The offset of main part in the svg element
* @param {Object} xAxisMap The configuration of all x-axes
* @param {Object} yAxisMap The configuration of all y-axes
* @param {Object} e Event object
* @return {Null} null
*/
}, {
key: 'handleMouseEnter',
value: function handleMouseEnter(offset, xAxisMap, yAxisMap, e) {
var container = _reactDom2.default.findDOMNode(this);
var containerOffset = _ouiDomUtils2.default.getOffset(container);
var ne = this.getChartPosition(e, containerOffset);
var mouse = this.getMouseInfo(xAxisMap, yAxisMap, offset, ne);
if (mouse) {
this.setState(_extends({}, mouse, {
isTooltipActive: true,
chartX: ne.chartX,
chartY: ne.chartY
}));
}
}
/**
* The handler of mouse moving in chart
* @param {Object} offset The offset of main part in the svg element
* @param {Object} xAxisMap The configuration of all x-axes
* @param {Object} yAxisMap The configuration of all y-axes
* @param {Object} e Event object
* @return {Null} no return
*/
}, {
key: 'handleMouseMove',
value: function handleMouseMove(offset, xAxisMap, yAxisMap, e) {
var container = _reactDom2.default.findDOMNode(this);
var containerOffset = _ouiDomUtils2.default.getOffset(container);
var ne = this.getChartPosition(e, containerOffset);
var mouse = this.getMouseInfo(xAxisMap, yAxisMap, offset, ne);
if (mouse) {
this.setState(_extends({}, mouse, {
isTooltipActive: true,
chartX: ne.chartX,
chartY: ne.chartY
}));
} else {
this.setState({
isTooltipActive: false
});
}
}
/**
* The handler if mouse leaving chart
* @return {Null} no return
*/
}, {
key: 'handleMouseLeave',
value: function handleMouseLeave() {
this.setState({
isTooltipActive: false
});
}
/**
* Draw x-axes
* @param {Object} xAxisMap The configuration of all x-axes
* @return {ReactElement} The instance of x-axes
*/
}, {
key: 'renderXAxis',
value: function renderXAxis(xAxisMap) {
var _props4 = this.props;
var width = _props4.width;
var height = _props4.height;
var ids = xAxisMap && Object.keys(xAxisMap);
if (ids && ids.length) {
var xAxes = [];
for (var i = 0, len = ids.length; i < len; i++) {
var axis = xAxisMap[ids[i]];
if (!axis.hide) {
xAxes.push(_react2.default.createElement(_CartesianAxis2.default, _extends({}, axis, {
x: axis.x,
y: axis.y,
width: axis.width,
height: axis.height,
key: 'x-axis-' + ids[i],
orientation: axis.orientation,
viewBox: { x: 0, y: 0, width: width, height: height },
ticks: this.getAxisTicks(axis, true)
})));
}
}
return xAxes.length ? _react2.default.createElement(
_Layer2.default,
{ key: 'x-axis-layer', className: 'recharts-x-axis' },
xAxes
) : null;
}
}
/**
* Draw y-axes
* @param {Object} yAxisMap The configuration of all y-axes
* @return {ReactElement} The instance of y-axes
*/
}, {
key: 'renderYAxis',
value: function renderYAxis(yAxisMap) {
var _props5 = this.props;
var width = _props5.width;
var height = _props5.height;
var ids = yAxisMap && Object.keys(yAxisMap);
if (ids && ids.length) {
var yAxes = [];
for (var i = 0, len = ids.length; i < len; i++) {
var axis = yAxisMap[ids[i]];
if (!axis.hide) {
yAxes.push(_react2.default.createElement(_CartesianAxis2.default, _extends({}, axis, {
key: 'y-axis-' + ids[i],
x: axis.x,
y: axis.y,
width: axis.width,
height: axis.height,
orientation: axis.orientation,
viewBox: { x: 0, y: 0, width: width, height: height },
ticks: this.getAxisTicks(axis, true)
})));
}
}
return yAxes.length ? _react2.default.createElement(
_Layer2.default,
{ key: 'y-axis-layer', className: 'recharts-y-axis' },
yAxes
) : null;
}
}
/**
* Draw grid
* @param {Object} xAxisMap The configuration of all x-axes
* @param {Object} yAxisMap The configuration of all y-axes
* @param {Object} offset The offset of main part in the svg element
* @return {ReactElement} The instance of grid
*/
}, {
key: 'renderGrid',
value: function renderGrid(xAxisMap, yAxisMap, offset) {
var _props6 = this.props;
var children = _props6.children;
var width = _props6.width;
var height = _props6.height;
var gridItem = _ReactUtils2.default.findChildByType(children, _CartesianGrid2.default);
if (!gridItem) {
return null;
}
var xIds = Object.keys(xAxisMap);
var yIds = Object.keys(yAxisMap);
var xAxis = xAxisMap[xIds[0]];
var yAxis = yAxisMap[yIds[0]];
var verticalPoints = this.getGridTicks(_CartesianAxis2.default.getTicks(_extends({}, _CartesianAxis2.default.defaultProps, xAxis, {
ticks: this.getAxisTicks(xAxis, true),
viewBox: { x: 0, y: 0, width: width, height: height }
})), offset.left, offset.left + offset.width);
var horizontalPoints = this.getGridTicks(_CartesianAxis2.default.getTicks(_extends({}, _CartesianAxis2.default.defaultProps, yAxis, {
ticks: this.getAxisTicks(yAxis, true),
viewBox: { x: 0, y: 0, width: width, height: height }
})), offset.top, offset.top + offset.height);
return _react2.default.cloneElement(gridItem, {
key: 'grid',
x: offset.left,
y: offset.top,
width: offset.width,
height: offset.height,
verticalPoints: verticalPoints, horizontalPoints: horizontalPoints
});
}
/**
* Draw legend
* @param {Array} items The instances of item
* @return {ReactElement} The instance of Legend
*/
}, {
key: 'renderLegend',
value: function renderLegend(items) {
var _this8 = this;
var _props7 = this.props;
var children = _props7.children;
var width = _props7.width;
var height = _props7.height;
var legendItem = _ReactUtils2.default.findChildByType(children, _Legend2.default);
if (!legendItem) {
return null;
}
var legendData = items.map(function (child) {
var _child$props3 = child.props;
var dataKey = _child$props3.dataKey;
var name = _child$props3.name;
var legendType = _child$props3.legendType;
return {
type: legendType || 'square',
color: _this8.getMainColorOfItem(child),
value: name || dataKey
};
}, this);
return _react2.default.cloneElement(legendItem, _extends({}, _Legend2.default.getWithHeight(legendItem, width, height), {
payload: legendData
}));
}
/**
* Draw Tooltip
* @param {Array} items The instances of item
* @param {Object} offset The offset of main part in the svg element
* @return {ReactElement} The instance of Tooltip
*/
}, {
key: 'renderTooltip',
value: function renderTooltip(items, offset) {
var children = this.props.children;
var tooltipItem = _ReactUtils2.default.findChildByType(children, _Tooltip2.default);
if (!tooltipItem) {
return null;
}
var _state6 = this.state;
var chartX = _state6.chartX;
var chartY = _state6.chartY;
var isTooltipActive = _state6.isTooltipActive;
var activeTooltipLabel = _state6.activeTooltipLabel;
var activeTooltipCoord = _state6.activeTooltipCoord;
var viewBox = {
x: offset.left,
y: offset.top,
width: offset.width,
height: offset.height
};
return _react2.default.cloneElement(tooltipItem, {
viewBox: viewBox,
active: isTooltipActive,
label: activeTooltipLabel,
payload: isTooltipActive ? this.getTooltipContent(items) : [],
coordinate: activeTooltipCoord,
mouseX: chartX,
mouseY: chartY
});
}
}, {
key: 'renderBrush',
value: function renderBrush(xAxisMap, yAxisMap, offset) {
var _props8 = this.props;
var children = _props8.children;
var data = _props8.data;
var brushItem = _ReactUtils2.default.findChildByType(children, _Brush2.default);
if (!brushItem) {
return null;
}
var dataKey = brushItem.props.dataKey;
var height = (brushItem.props.height || _Brush2.default.defaultProps.height) + 1;
return _react2.default.cloneElement(brushItem, {
onChange: this.handleBrushChange.bind(this),
data: data.map(function (entry) {
return entry[dataKey];
}),
x: offset.left,
y: offset.top + offset.height + offset.bottom - height,
width: offset.width
});
}
}, {
key: 'renderReferenceLines',
value: function renderReferenceLines(xAxisMap, yAxisMap, offset) {
var children = this.props.children;
var lines = _ReactUtils2.default.findAllByType(children, _ReferenceLine2.default);
if (!lines || !lines.length) {
return null;
}
return lines.map(function (entry, i) {
return _react2.default.cloneElement(entry, {
key: 'reference-line-' + i,
xAxisMap: xAxisMap, yAxisMap: yAxisMap,
viewBox: {
x: offset.left,
y: offset.top,
width: offset.width,
height: offset.height
}
});
});
}
}]);
return CartesianChart;
}(_react.Component), _class.propTypes = {
width: _react.PropTypes.number,
height: _react.PropTypes.number,
data: _react.PropTypes.arrayOf(_react.PropTypes.object),
layout: _react.PropTypes.oneOf(['horizontal', 'vertical']),
margin: _react.PropTypes.shape({
top: _react.PropTypes.number,
right: _react.PropTypes.number,
bottom: _react.PropTypes.number,
left: _react.PropTypes.number
}),
className: _react.PropTypes.string,
stackType: _react.PropTypes.oneOf(['value', 'percent']),
title: _react.PropTypes.string,
style: _react.PropTypes.object,
barCategoryGap: _react.PropTypes.oneOfType([_react.PropTypes.number, _react.PropTypes.string]),
barGap: _react.PropTypes.number,
barSize: _react.PropTypes.number,
children: _react.PropTypes.oneOfType([_react.PropTypes.arrayOf(_react.PropTypes.node), _react.PropTypes.node])
}, _class.defaultProps = {
style: {},
barCategoryGap: '10%',
barGap: 4,
layout: 'horizontal',
margin: { top: 5, right: 5, bottom: 5, left: 5 }
}, _temp);
exports.default = CartesianChart;