UNPKG

@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
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';