victory-box-plot
Version:
Box Plot Component for Victory
148 lines (145 loc) • 5.15 kB
JavaScript
import React from "react";
import { Helpers, VictoryLabel, addEvents, LineSegment, VictoryContainer, VictoryTheme, Box, Whisker, DefaultTransitions, UserProps } from "victory-core";
import { getDomain, getData, getBaseProps } from "./helper-methods";
const fallbackProps = {
width: 450,
height: 300,
padding: {
top: 20,
right: 20,
bottom: 20,
left: 20
}
};
const defaultData = [{
x: 1,
min: 5,
q1: 7,
median: 12,
q3: 18,
max: 20
}, {
x: 2,
min: 2,
q1: 5,
median: 8,
q3: 12,
max: 15
}];
const options = {
components: [{
name: "min"
}, {
name: "minLabels"
}, {
name: "max"
}, {
name: "maxLabels"
}, {
name: "median"
}, {
name: "medianLabels"
}, {
name: "q1"
}, {
name: "q1Labels"
}, {
name: "q3"
}, {
name: "q3Labels"
}, {
name: "parent",
index: "parent"
}]
};
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
class VictoryBoxPlotBase extends React.Component {
static animationWhitelist = ["data", "domain", "height", "padding", "style", "width"];
static displayName = "VictoryBoxPlot";
static role = "boxplot";
static defaultTransitions = DefaultTransitions.discreteTransitions();
static defaultProps = {
containerComponent: /*#__PURE__*/React.createElement(VictoryContainer, null),
data: defaultData,
dataComponent: /*#__PURE__*/React.createElement(Box, null),
groupComponent: /*#__PURE__*/React.createElement("g", {
role: "presentation"
}),
maxComponent: /*#__PURE__*/React.createElement(Whisker, null),
maxLabelComponent: /*#__PURE__*/React.createElement(VictoryLabel, null),
medianComponent: /*#__PURE__*/React.createElement(LineSegment, null),
medianLabelComponent: /*#__PURE__*/React.createElement(VictoryLabel, null),
minComponent: /*#__PURE__*/React.createElement(Whisker, null),
minLabelComponent: /*#__PURE__*/React.createElement(VictoryLabel, null),
q1Component: /*#__PURE__*/React.createElement(Box, null),
q1LabelComponent: /*#__PURE__*/React.createElement(VictoryLabel, null),
q3Component: /*#__PURE__*/React.createElement(Box, null),
q3LabelComponent: /*#__PURE__*/React.createElement(VictoryLabel, null),
samples: 50,
sortKey: "x",
sortOrder: "ascending",
standalone: true,
theme: VictoryTheme.grayscale
};
static getDomain(props, axis) {
return getDomain(props, axis);
}
static getData(props) {
return getData(props);
}
static getBaseProps(props) {
return getBaseProps(props, fallbackProps);
}
static expectedComponents = ["maxComponent", "maxLabelComponent", "medianComponent", "medianLabelComponent", "minComponent", "minLabelComponent", "q1Component", "q1LabelComponent", "q3Component", "q3LabelComponent", "groupComponent", "containerComponent"];
renderBoxPlot(props) {
const types = ["q1", "q3", "max", "min", "median"];
const dataComponents = types.map(type => {
return this.dataKeys.reduce((validDataComponents, _key, index) => {
const baseComponent = props[`${type}Component`];
const componentProps = this.getComponentProps(baseComponent, type, index);
if (this.shouldRenderDatum(componentProps.datum)) {
validDataComponents.push( /*#__PURE__*/React.cloneElement(baseComponent, componentProps));
}
return validDataComponents;
}, []);
}).flat();
const labelComponents = types.map(type => {
const components = this.dataKeys.reduce((validComponents, _key, index) => {
const name = `${type}Labels`;
const baseComponent = props[`${type}LabelComponent`];
const labelProps = this.getComponentProps(baseComponent, name, index);
if (labelProps.text !== undefined && labelProps.text !== null) {
validComponents.push( /*#__PURE__*/React.cloneElement(baseComponent, labelProps));
}
return validComponents;
}, []);
return components.filter(Boolean);
}).flat();
const children = [...dataComponents, ...labelComponents];
return this.renderContainer(props.groupComponent, children);
}
// Overridden in native versions
shouldAnimate() {
return !!this.props.animate;
}
shouldRenderDatum(datum) {
const hasX = !Helpers.isNil(datum._x);
const hasY = !Helpers.isNil(datum._y);
const hasSummaryStatistics = !Helpers.isNil(datum._min) && !Helpers.isNil(datum._max) && !Helpers.isNil(datum._median) && !Helpers.isNil(datum._q1) && !Helpers.isNil(datum._q3);
return hasSummaryStatistics && (this.props.horizontal ? hasY : hasX);
}
render() {
const {
animationWhitelist,
role
} = VictoryBoxPlot;
const props = Helpers.modifyProps(this.props, fallbackProps, role);
if (this.shouldAnimate()) {
return this.animateComponent(props, animationWhitelist);
}
const children = this.renderBoxPlot(props);
const component = props.standalone ? this.renderContainer(props.containerComponent, children) : children;
return UserProps.withSafeUserProps(component, props);
}
}
export const VictoryBoxPlot = addEvents(VictoryBoxPlotBase, options);