victory-core
Version:
405 lines (398 loc) • 16 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.addBinsToParentPropsIfHistogram = addBinsToParentPropsIfHistogram;
exports.getAllEvents = getAllEvents;
exports.getCategories = getCategories;
exports.getCategoryAndAxisStringsFromChildren = getCategoryAndAxisStringsFromChildren;
exports.getChildStyle = getChildStyle;
exports.getColor = getColor;
exports.getData = getData;
exports.getDataFromChildren = getDataFromChildren;
exports.getDefaultDomainPadding = getDefaultDomainPadding;
exports.getDomain = getDomain;
exports.getDomainFromChildren = getDomainFromChildren;
exports.getScale = getScale;
exports.getStringsFromChildren = getStringsFromChildren;
exports.getStringsFromChildrenCategories = getStringsFromChildrenCategories;
exports.getStringsFromData = getStringsFromData;
exports.getStyle = getStyle;
exports.getWidth = getWidth;
var _react = _interopRequireDefault(require("react"));
var _defaults = _interopRequireDefault(require("lodash/defaults"));
var _uniq = _interopRequireDefault(require("lodash/uniq"));
var _groupBy = _interopRequireDefault(require("lodash/groupBy"));
var _uniqBy = _interopRequireDefault(require("lodash/uniqBy"));
var Axis = _interopRequireWildcard(require("./axis"));
var Style = _interopRequireWildcard(require("./style"));
var Data = _interopRequireWildcard(require("./data"));
var Domain = _interopRequireWildcard(require("./domain"));
var Events = _interopRequireWildcard(require("./events"));
var Collection = _interopRequireWildcard(require("./collection"));
var Helpers = _interopRequireWildcard(require("./helpers"));
var Scale = _interopRequireWildcard(require("./scale"));
var Log = _interopRequireWildcard(require("./log"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function addBinsToParentPropsIfHistogram(_ref) {
let {
children,
props,
childComponents,
parentProps
} = _ref;
const someChildrenAreHistograms = children.some(child => {
return child.type && child.type.role === "histogram";
});
const allChildrenAreHistograms = someChildrenAreHistograms && children.length && children.every(child => {
return child.type && child.type.role === "histogram";
});
if (someChildrenAreHistograms && !allChildrenAreHistograms) {
Log.warn("VictoryHistogram only supports being stacked with other VictoryHistogram components. Check to make sure that you are only passing VictoryHistogram components to VictoryStack");
}
// if we are stacking histograms, we need to generate explicit bins
// or else each histogram may end up having different bins
if (!allChildrenAreHistograms) {
return parentProps;
}
let childBins = props.bins || childComponents[0].props.bins;
// if we have explicit bins then we don't need to calculate them
if (!Array.isArray(childBins)) {
const combinedData = children.reduce((memo, child) => {
const xAccessor = Helpers.createAccessor(child.props.x || "x");
return memo.concat(child.props.data.map(datum => ({
x: xAccessor(datum)
})));
}, []);
// use the same function to generate bins as VictoryHistogram but with
// the combined data from above, then get explicit bins from that
const getFormattedHistogramData = children[0].type.getFormattedData;
childBins = getFormattedHistogramData({
data: combinedData,
bins: childBins
}).reduce((memo, _ref2, index) => {
let {
x0,
x1
} = _ref2;
return index === 0 ? memo.concat([x0, x1]) : memo.concat(x1);
}, []);
}
return {
...parentProps,
bins: childBins
};
}
function getDataFromChildren(props, childComponents) {
const {
polar,
startAngle,
endAngle,
categories,
minDomain,
maxDomain
} = props;
let parentProps = {
polar,
startAngle,
endAngle,
categories,
minDomain,
maxDomain
};
let stack = 0;
const children = childComponents ? childComponents.slice(0) : _react.default.Children.toArray(props.children);
parentProps = addBinsToParentPropsIfHistogram({
children,
props,
childComponents,
parentProps
});
const iteratee = (child, childName, parent) => {
const childProps = Object.assign({}, child.props, parentProps);
let childData;
let childElement = child;
if (!Data.isDataComponent(child)) {
return null;
} else if (child.type && Helpers.isFunction(child.type.getData)) {
childElement = parent ? /*#__PURE__*/_react.default.cloneElement(child, parent.props) : child;
childData = childElement.type.getData(childProps);
} else {
childData = Data.getData(childProps);
}
stack += 1;
return childData.map((datum, index) => Object.assign({
_stack: stack,
_group: index
}, datum));
};
const stacked = children.filter(c => c.type && c.type.role === "stack").length;
const combine = (memo, val) => memo.concat((0, _uniqBy.default)(val, "_group"));
const datasets = Helpers.reduceChildren(children, iteratee, props, [], combine);
const group = stacked ? "_group" : "_stack";
return Object.values((0, _groupBy.default)(datasets, group));
}
function getData(props, childComponents) {
if (props.data) {
return Data.getData(props);
}
return getDataFromChildren(props, childComponents || _react.default.Children.toArray(props.children));
}
function getWidth(props, groupLength, seriesLength) {
const {
datasets,
horizontal
} = props;
const range = horizontal ? Helpers.getRange(props, "y") : Helpers.getRange(props, "x");
const extent = Math.abs(range[1] - range[0]);
const seriesLengthValue = seriesLength !== undefined ? seriesLength : Array.isArray(datasets[0]) && datasets[0].length || 1;
const groupLengthValue = groupLength || datasets.length;
const bars = groupLengthValue * seriesLengthValue;
const barRatio = 0.5;
return Math.round(barRatio * extent / bars);
}
function getDefaultDomainPadding(props, axis, childComponents) {
if (props.polar || axis !== "x") {
return undefined;
}
const groupComponent = childComponents.filter(child => {
return child.type && child.type.role && child.type.role === "group";
});
if (groupComponent.length < 1) {
return undefined;
}
const {
offset,
children
} = groupComponent[0].props;
if (!offset) {
return undefined;
}
const firstChild = Array.isArray(children) && children[0];
if (!firstChild) {
return undefined;
}
let barWidth = firstChild.props.barWidth;
let dataLength = firstChild.props.data && firstChild.props.data.length || 1;
if (firstChild && firstChild.type.role === "stack") {
const nestedChild = firstChild.props.children && firstChild.props.children[0];
if (!nestedChild) {
return undefined;
}
barWidth = nestedChild.props.barWidth;
dataLength = firstChild.props.children.length;
}
const width = barWidth || getWidth(props, children.length, dataLength);
return {
x: width * children.length / 2 + (offset - width * ((children.length - 1) / 2))
};
}
function getDomainFromChildren(props, axis, childComponents) {
const children = childComponents ? childComponents.slice(0) : _react.default.Children.toArray(props.children);
const parentData = props.data ? Data.getData(props) : undefined;
const {
polar,
startAngle,
endAngle,
categories,
minDomain,
maxDomain,
horizontal
} = props;
const baseParentProps = {
horizontal,
polar,
startAngle,
endAngle,
minDomain,
maxDomain,
categories
};
const parentProps = parentData ? Object.assign(baseParentProps, {
data: parentData
}) : baseParentProps;
const iteratee = child => {
const sharedProps = Object.assign({}, child.props, parentProps);
if (!Domain.isDomainComponent(child)) {
return null;
} else if (child.type && Helpers.isFunction(child.type.getDomain)) {
return child.props && child.type.getDomain(sharedProps, axis);
}
return Domain.getDomain(sharedProps, axis);
};
const childDomains = Helpers.reduceChildren(children, iteratee, props);
const min = childDomains.length === 0 ? 0 : Collection.getMinValue(childDomains);
const max = childDomains.length === 0 ? 1 : Collection.getMaxValue(childDomains);
return [min, max];
}
function getDomain(props, axis, childComponents) {
const children = childComponents || _react.default.Children.toArray(props.children);
const propsDomain = Domain.getDomainFromProps(props, axis);
const domainPadding = getDefaultDomainPadding(props, axis, children);
let domain;
if (propsDomain) {
domain = propsDomain;
} else {
const minDomain = Domain.getMinFromProps(props, axis);
const maxDomain = Domain.getMaxFromProps(props, axis);
const dataset = (props.data || props.y) && Data.getData(props);
const dataDomain = dataset ? Domain.getDomainFromData(props, axis, dataset) : [];
const childDomain = getDomainFromChildren(props, axis, children);
const min = minDomain || Collection.getMinValue([...dataDomain, ...childDomain]);
const max = maxDomain || Collection.getMaxValue([...dataDomain, ...childDomain]);
domain = Domain.getDomainFromMinMax(min, max);
}
return Domain.formatDomain(domain, Object.assign({
domainPadding
}, props), axis);
}
function getScale(props, axis, childComponents) {
if (props.data) {
return Scale.getBaseScale(props, axis);
}
const children = childComponents ? childComponents.slice(0) : _react.default.Children.toArray(props.children);
const iteratee = child => {
const sharedProps = Object.assign({}, child.props, {
horizontal: props.horizontal
});
return Scale.getScaleType(sharedProps, axis);
};
const childScale = (0, _uniq.default)(Helpers.reduceChildren(children, iteratee, props));
// default to linear scale if more than one uniq scale type is given by children
return childScale.length > 1 ? Scale.getScaleFromName("linear") : Scale.getScaleFromName(childScale[0]);
}
function getAllEvents(props) {
const components = ["groupComponent", "containerComponent", "labelComponent"];
const componentEvents = Events.getComponentEvents(props, components);
let events = props.events;
if (Array.isArray(componentEvents)) {
events = Array.isArray(props.events) ? componentEvents.concat(...props.events) : componentEvents;
}
return events || [];
}
// eslint-disable-next-line max-params
function getColor(calculatedProps, child, index, theme) {
// check for styles first
const {
style
} = calculatedProps;
let {
colorScale,
color
} = calculatedProps;
if (style && style.data && style.data.fill) {
return style.data.fill;
}
colorScale = child.props && child.props.colorScale ? child.props.colorScale : colorScale;
color = child.props && child.props.color ? child.props.color : color;
if (!colorScale && !color) {
return undefined;
}
const colors = Array.isArray(colorScale) ? colorScale : Style.getColorScale(colorScale, theme);
return color || colors[index % colors.length];
}
function getStyle(theme, style, role) {
const defaultStyle = theme && theme[role] && theme[role].style ? theme[role].style : {};
return Helpers.getStyles(style, defaultStyle);
}
// eslint-disable-next-line max-params
function getChildStyle(child, index, calculatedProps, theme) {
const {
style,
role
} = calculatedProps;
const childStyle = child.props.style || {};
if (Array.isArray(childStyle)) {
return childStyle;
}
const childRole = child.type && child.type.role;
const defaultFill = childRole === "stack" ? undefined : getColor(calculatedProps, child, index, theme);
const defaultColor = childRole === "line" ? {
fill: "none",
stroke: defaultFill
} : {
fill: defaultFill
};
const dataWidth = role === "stack" ? {} : {
width: getWidth(calculatedProps)
};
const dataStyle = (0, _defaults.default)({}, childStyle.data, Object.assign({}, dataWidth, style.data, defaultColor));
const labelsStyle = (0, _defaults.default)({}, childStyle.labels, style.labels);
return {
...childStyle,
parent: style.parent,
data: dataStyle,
labels: labelsStyle
};
}
function getStringsFromChildrenCategories(childComponents, axis) {
const iteratee = child => {
if (!Domain.isDomainComponent(child)) {
return null;
}
const childProps = child.props || {};
return Data.getStringsFromCategories(childProps, axis);
};
return Helpers.reduceChildren(childComponents.slice(0), iteratee);
}
function getStringsFromData(childComponents) {
const iteratee = child => {
const childProps = child.props || {};
let data;
if (!Data.isDataComponent(child)) {
return null;
} else if (child.type && Helpers.isFunction(child.type.getData)) {
data = child.type.getData(childProps);
} else {
data = Data.getData(childProps);
}
return data.map(d => ({
x: d.xName,
y: d.yName
}));
};
const initialMemo = {
x: [],
y: []
};
const combine = (memo, datum) => {
const x = Array.isArray(datum) ? datum.map(d => d.x).filter(Boolean) : datum.x;
const y = Array.isArray(datum) ? datum.map(d => d.y).filter(Boolean) : datum.y;
return {
x: x !== undefined ? memo.x.concat(x) : memo.x,
y: y !== undefined ? memo.y.concat(y) : memo.y
};
};
return Helpers.reduceChildren(childComponents.slice(0), iteratee, {}, initialMemo, combine);
}
function getCategoryAndAxisStringsFromChildren(props, axis, childComponents) {
const categories = Data.getStringsFromCategories(props, axis);
const axisComponent = Axis.getAxisComponent(childComponents, axis);
const axisStrings = axisComponent ? Data.getStringsFromAxes(axisComponent.props, axis) : [];
const categoryStrings = categories.length ? categories : getStringsFromChildrenCategories(childComponents, axis);
return (0, _uniq.default)([...categoryStrings, ...axisStrings].flat());
}
function getStringsFromChildren(props, childComponents) {
const children = childComponents || _react.default.Children.toArray(props.children);
const xStrings = getCategoryAndAxisStringsFromChildren(props, "x", children);
const yStrings = getCategoryAndAxisStringsFromChildren(props, "y", children);
const dataStrings = getStringsFromData(children);
return {
x: (0, _uniq.default)([...xStrings, ...dataStrings.x].flat()),
y: (0, _uniq.default)([...yStrings, ...dataStrings.y].flat())
};
}
function getCategories(props, childComponents, allStrings) {
const xPropCategories = props.categories && Data.getStringsFromCategories(props, "x");
const yPropCategories = props.categories && Data.getStringsFromCategories(props, "y");
const fallbackRequired = !xPropCategories || !yPropCategories;
const fallbackProps = fallbackRequired ? allStrings || getStringsFromChildren(props, childComponents) : {};
const xCategories = xPropCategories || fallbackProps.x;
const yCategories = yPropCategories || fallbackProps.y;
return {
x: xCategories.length > 0 ? xCategories : undefined,
y: yCategories.length > 0 ? yCategories : undefined
};
}