UNPKG

victory-chart

Version:
203 lines (186 loc) 6.98 kB
import React, { PropTypes } from "react"; import { PropTypes as CustomPropTypes, Helpers, VictoryTransition, VictoryLabel, addEvents, VictoryContainer, VictoryTheme, DefaultTransitions, ErrorBar, Data } from "victory-core"; import { partialRight } from "lodash"; import ErrorBarHelpers from "./helper-methods"; const fallbackProps = { width: 450, height: 300, padding: 50 }; const defaultData = [ {x: 1, y: 1, errorX: 0.1, errorY: 0.1}, {x: 2, y: 2, errorX: 0.2, errorY: 0.2}, {x: 3, y: 3, errorX: 0.3, errorY: 0.3}, {x: 4, y: 4, errorX: 0.4, errorY: 0.4} ]; class VictoryErrorBar extends React.Component { static displayName = "VictoryErrorBar"; static role = "errorBar"; static defaultTransitions = DefaultTransitions.discreteTransitions(); static propTypes = { animate: PropTypes.object, borderWidth: PropTypes.number, categories: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.string), PropTypes.shape({ x: PropTypes.arrayOf(PropTypes.string), y: PropTypes.arrayOf(PropTypes.string) }) ]), containerComponent: PropTypes.element, data: PropTypes.array, domainPadding: PropTypes.oneOfType([ PropTypes.shape({ x: PropTypes.oneOfType([ PropTypes.number, CustomPropTypes.domain ]), y: PropTypes.oneOfType([ PropTypes.number, CustomPropTypes.domain ]) }), PropTypes.number ]), dataComponent: PropTypes.element, domain: PropTypes.oneOfType([ CustomPropTypes.domain, PropTypes.shape({ x: CustomPropTypes.domain, y: CustomPropTypes.domain }) ]), errorX: PropTypes.oneOfType([ PropTypes.func, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string, PropTypes.arrayOf(PropTypes.string) ]), errorY: PropTypes.oneOfType([ PropTypes.func, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string, PropTypes.arrayOf(PropTypes.string) ]), events: PropTypes.arrayOf(PropTypes.shape({ target: PropTypes.oneOf(["data", "labels", "parent"]), eventKey: PropTypes.oneOfType([ PropTypes.array, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string ]), eventHandlers: PropTypes.object })), eventKey: PropTypes.oneOfType([ PropTypes.func, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string ]), groupComponent: PropTypes.element, height: CustomPropTypes.nonNegative, horizontal: PropTypes.bool, labels: PropTypes.oneOfType([ PropTypes.func, PropTypes.array ]), labelComponent: PropTypes.element, name: PropTypes.string, padding: PropTypes.oneOfType([ PropTypes.number, PropTypes.shape({ top: PropTypes.number, bottom: PropTypes.number, left: PropTypes.number, right: PropTypes.number }) ]), samples: CustomPropTypes.nonNegative, scale: PropTypes.oneOfType([ CustomPropTypes.scale, PropTypes.shape({ x: CustomPropTypes.scale, y: CustomPropTypes.scale }) ]), sharedEvents: PropTypes.shape({ events: PropTypes.array, getEventState: PropTypes.func }), standalone: PropTypes.bool, style: PropTypes.shape({ parent: PropTypes.object, data: PropTypes.object, labels: PropTypes.object }), theme: PropTypes.object, width: CustomPropTypes.nonNegative, x: PropTypes.oneOfType([ PropTypes.func, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string, PropTypes.arrayOf(PropTypes.string) ]), y: PropTypes.oneOfType([ PropTypes.func, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string, PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf(PropTypes.func) ]) }; static defaultProps = { data: defaultData, scale: "linear", standalone: true, dataComponent: <ErrorBar/>, labelComponent: <VictoryLabel/>, containerComponent: <VictoryContainer/>, groupComponent: <g/>, theme: VictoryTheme.grayscale }; static getDomain = ErrorBarHelpers.getDomain.bind(ErrorBarHelpers); static getData = Data.getData.bind(Data); static getBaseProps = partialRight( ErrorBarHelpers.getBaseProps.bind(ErrorBarHelpers), fallbackProps); static expectedComponents = [ "dataComponent", "labelComponent", "groupComponent", "containerComponent" ]; renderContainer(props, group) { const { containerComponent } = props; const parentProps = this.getComponentProps(containerComponent, "parent", "parent"); return React.cloneElement(containerComponent, parentProps, group); } renderGroup(children, style) { return React.cloneElement( this.props.groupComponent, { role: "presentation", style}, children ); } renderData(props) { const { dataComponent, labelComponent, groupComponent } = props; const dataComponents = []; const labelComponents = []; for (let index = 0, len = this.dataKeys.length; index < len; index++) { const dataProps = this.getComponentProps(dataComponent, "data", index); dataComponents[index] = React.cloneElement(dataComponent, dataProps); const labelProps = this.getComponentProps(labelComponent, "labels", index); if (labelProps && labelProps.text !== undefined && labelProps.text !== null) { labelComponents[index] = React.cloneElement(labelComponent, labelProps); } } return labelComponents.length > 0 ? React.cloneElement(groupComponent, {}, ...dataComponents, ...labelComponents) : dataComponents; } shouldAnimate() { return !!this.props.animate; } render() { const props = Helpers.modifyProps(this.props, fallbackProps, "errorbar"); const { animate, style, standalone, theme } = props; if (this.shouldAnimate()) { // Do less work by having `VictoryAnimation` tween only values that // make sense to tween. In the future, allow customization of animated // prop whitelist/blacklist? const whitelist = [ "data", "domain", "height", "padding", "samples", "style", "width", "x", "y", "errorX", "errorY", "borderWidth" ]; return ( <VictoryTransition animate={animate} animationWhitelist={whitelist}> {React.createElement(this.constructor, props)} </VictoryTransition> ); } const styleObject = theme && theme.errorbar && theme.errorbar.style ? theme.errorbar.style : {}; const baseStyle = Helpers.getStyles(style, styleObject, "auto", "100%"); const group = this.renderGroup(this.renderData(props), baseStyle.parent); return standalone ? this.renderContainer(props, group) : group; } } export default addEvents(VictoryErrorBar);