@data-ui/xy-chart
Version:
A package of charts with standard x- and y- axes. https://williaster.github.io/data-ui
209 lines (186 loc) • 7.43 kB
JavaScript
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
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); }
import { BoxPlot } from '@vx/stats';
import { FocusBlurHandler } from '@data-ui/shared';
import { Group } from '@vx/group';
import PropTypes from 'prop-types';
import React from 'react';
import { color as themeColors } from '@data-ui/theme';
import { callOrValue, isDefined } from '../utils/chartUtils';
import { boxPlotSeriesDataShape } from '../utils/propShapes';
import sharedSeriesProps from '../utils/sharedSeriesProps';
var propTypes = _extends({}, sharedSeriesProps, {
containerEvents: PropTypes.bool,
data: boxPlotSeriesDataShape.isRequired,
fill: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
horizontal: PropTypes.bool,
stroke: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
strokeWidth: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
fillOpacity: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
widthRatio: PropTypes.number,
containerProps: PropTypes.object,
// eslint-disable-line react/forbid-prop-types
outlierProps: PropTypes.object,
// eslint-disable-line react/forbid-prop-types
boxProps: PropTypes.object,
// eslint-disable-line react/forbid-prop-types
minProps: PropTypes.object,
// eslint-disable-line react/forbid-prop-types
maxProps: PropTypes.object,
// eslint-disable-line react/forbid-prop-types
medianProps: PropTypes.object // eslint-disable-line react/forbid-prop-types
});
var defaultProps = {
containerEvents: true,
stroke: themeColors.darkGray,
strokeWidth: 2,
fill: themeColors.default,
fillOpacity: 1,
horizontal: false,
widthRatio: 1,
containerProps: null,
outlierProps: null,
boxProps: null,
minProps: null,
maxProps: null,
medianProps: null
};
var MAX_BOX_WIDTH = 50;
var x = function x(d) {
return d.x;
};
var y = function y(d) {
return d.y;
};
var min = function min(d) {
return d.min;
};
var max = function max(d) {
return d.max;
};
var median = function median(d) {
return d.median;
};
var firstQuartile = function firstQuartile(d) {
return d.firstQuartile;
};
var thirdQuartile = function thirdQuartile(d) {
return d.thirdQuartile;
};
var outliers = function outliers(d) {
return d.outliers || [];
};
var BoxPlotSeries =
/*#__PURE__*/
function (_React$PureComponent) {
_inheritsLoose(BoxPlotSeries, _React$PureComponent);
function BoxPlotSeries() {
return _React$PureComponent.apply(this, arguments) || this;
}
var _proto = BoxPlotSeries.prototype;
_proto.render = function render() {
var _this$props = this.props,
containerEvents = _this$props.containerEvents,
data = _this$props.data,
fill = _this$props.fill,
stroke = _this$props.stroke,
strokeWidth = _this$props.strokeWidth,
xScale = _this$props.xScale,
yScale = _this$props.yScale,
horizontal = _this$props.horizontal,
widthRatio = _this$props.widthRatio,
fillOpacity = _this$props.fillOpacity,
containerProps = _this$props.containerProps,
outlierProps = _this$props.outlierProps,
boxProps = _this$props.boxProps,
minProps = _this$props.minProps,
maxProps = _this$props.maxProps,
medianProps = _this$props.medianProps,
onMouseMove = _this$props.onMouseMove,
onMouseLeave = _this$props.onMouseLeave,
disableMouseEvents = _this$props.disableMouseEvents,
onClick = _this$props.onClick;
if (!xScale || !yScale) return null;
var offsetScale = horizontal ? yScale : xScale;
var offsetValue = horizontal ? y : x;
var valueScale = horizontal ? xScale : yScale;
var boxWidth = offsetScale.bandwidth();
var actualWidth = Math.min(MAX_BOX_WIDTH, boxWidth);
var offset = (offsetScale.offset || 0) - (boxWidth - actualWidth) / 2;
var offsetPropName = horizontal ? 'top' : 'left';
var offsetProp = function offsetProp(d) {
var _ref;
return _ref = {}, _ref[offsetPropName] = offsetScale(offsetValue(d)) - offset + (1 - widthRatio) / 2 * actualWidth, _ref;
};
var mouseEventProps = function mouseEventProps(d, i) {
return {
onMouseMove: disableMouseEvents ? null : onMouseMove && function () {
return function (event) {
onMouseMove({
event: event,
data: data,
datum: d,
index: i
});
};
},
onMouseLeave: disableMouseEvents ? null : onMouseLeave && function () {
return onMouseLeave;
},
onClick: disableMouseEvents ? null : onClick && function () {
return function (event) {
onClick({
event: event,
data: data,
datum: d,
index: i
});
};
}
};
};
return React.createElement(Group, null, data.map(function (d, i) {
var mouseEvents = mouseEventProps(d, i);
return isDefined(min(d)) && React.createElement(FocusBlurHandler, {
key: offsetValue(d),
xlinkHref: "#",
onBlur: disableMouseEvents ? null : onMouseLeave,
onFocus: disableMouseEvents ? null : function (event) {
onMouseMove({
event: event,
data: data,
datum: d,
index: i
});
}
}, React.createElement(BoxPlot, _extends({
min: min(d),
max: max(d)
}, offsetProp(d), {
firstQuartile: firstQuartile(d),
thirdQuartile: thirdQuartile(d),
median: median(d),
boxWidth: actualWidth * widthRatio,
outliers: outliers(d),
fill: d.fill || callOrValue(fill, d, i),
stroke: d.stroke || callOrValue(stroke, d, i),
strokeWidth: d.strokeWidth || callOrValue(strokeWidth, d, i),
fillOpacity: d.fillOpacity || callOrValue(fillOpacity, d, i),
valueScale: valueScale,
horizontal: horizontal,
container: containerEvents,
containerProps: (containerEvents || containerProps || undefined) && _extends({}, containerProps, containerEvents && mouseEvents),
outlierProps: (!containerEvents || outlierProps || undefined) && _extends({}, outlierProps, !containerEvents && mouseEvents),
boxProps: (!containerEvents || boxProps || undefined) && _extends({}, boxProps, !containerEvents && mouseEvents),
minProps: (!containerEvents || minProps || undefined) && _extends({}, minProps, !containerEvents && mouseEvents),
maxProps: (!containerEvents || maxProps || undefined) && _extends({}, maxProps, !containerEvents && mouseEvents),
medianProps: (!containerEvents || medianProps || undefined) && _extends({}, medianProps, !containerEvents && mouseEvents)
})));
}));
};
return BoxPlotSeries;
}(React.PureComponent);
export { BoxPlotSeries as default };
BoxPlotSeries.propTypes = propTypes;
BoxPlotSeries.defaultProps = defaultProps;
BoxPlotSeries.displayName = 'BoxPlotSeries';