UNPKG

@data-ui/sparkline

Version:

React + d3 library for creating sparklines

224 lines (199 loc) 6.83 kB
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 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); } /* eslint react/no-unused-prop-types: 0 */ import PropTypes from 'prop-types'; import React from 'react'; import { extent } from 'd3-array'; import Group from '@vx/group/build/Group'; import scaleLinear from '@vx/scale/build/scales/linear'; import BarSeries from '../series/BarSeries'; import { componentName, isBandLine, isReferenceLine, isSeries } from '../utils/componentIsX'; import isDefined from '../utils/defined'; var propTypes = { ariaLabel: PropTypes.string.isRequired, children: PropTypes.node.isRequired, className: PropTypes.string, // number or objects (with accessors) data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.object])), height: PropTypes.number.isRequired, margin: PropTypes.shape({ top: PropTypes.number, right: PropTypes.number, bottom: PropTypes.number, left: PropTypes.number }), max: PropTypes.number, min: PropTypes.number, onMouseMove: PropTypes.func, onMouseLeave: PropTypes.func, preserveAspectRatio: PropTypes.string, styles: PropTypes.object, // eslint-disable-line react/forbid-prop-types width: PropTypes.number.isRequired, valueAccessor: PropTypes.func, viewBox: PropTypes.string }; var defaultProps = { className: null, data: [], margin: { top: 16, right: 16, bottom: 16, left: 16 }, max: null, min: null, onMouseMove: null, onMouseLeave: null, preserveAspectRatio: null, styles: null, valueAccessor: function valueAccessor(d) { return d; }, viewBox: null }; var getX = function getX(d) { return d.i; }; var getY = function getY(d) { return d.y; }; var parsedDatumThunk = function parsedDatumThunk(valueAccessor) { return function (d, i) { var y = valueAccessor(d); return _extends({ i: i, y: y, id: y }, d); }; }; var Sparkline = /*#__PURE__*/ function (_React$PureComponent) { _inheritsLoose(Sparkline, _React$PureComponent); function Sparkline(props) { var _this; _this = _React$PureComponent.call(this, props) || this; _this.getMaxY = _this.getMaxY.bind(_assertThisInitialized(_assertThisInitialized(_this))); _this.state = _this.getStateFromProps(props); return _this; } var _proto = Sparkline.prototype; _proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { var _this2 = this; if ([// recompute scales if any of the following change 'data', 'height', 'margin', 'max', 'min', 'valueAccessor', 'width'].some(function (prop) { return _this2.props[prop] !== nextProps[prop]; }) // eslint-disable-line react/destructuring-assignment ) { this.setState(this.getStateFromProps(nextProps)); } }; _proto.getStateFromProps = function getStateFromProps(props) { var dimensions = this.getDimmensions(props); var scales = this.getScales(props, dimensions); return _extends({}, dimensions, scales); }; _proto.getScales = function getScales(props, _ref) { var innerHeight = _ref.innerHeight, innerWidth = _ref.innerWidth; var _ref2 = props || this.props, rawData = _ref2.data, min = _ref2.min, max = _ref2.max, valueAccessor = _ref2.valueAccessor; var data = rawData.map(parsedDatumThunk(valueAccessor)); var yExtent = extent(data, getY); var xScale = scaleLinear({ domain: [0, data.length - 1], range: [0, innerWidth] }); var yScale = scaleLinear({ domain: [isDefined(min) ? min : yExtent[0], isDefined(max) ? max : yExtent[1]], range: [innerHeight, 0] }); return { xScale: xScale, yScale: yScale, data: data }; }; _proto.getMaxY = function getMaxY() { var yScale = this.state.yScale; return Math.max.apply(Math, yScale.domain()); }; _proto.getDimmensions = function getDimmensions(props) { var _ref3 = props || this.props, margin = _ref3.margin, width = _ref3.width, height = _ref3.height; var completeMargin = _extends({}, defaultProps.margin, margin); return { margin: completeMargin, innerHeight: height - completeMargin.top - completeMargin.bottom, innerWidth: width - completeMargin.left - completeMargin.right }; }; _proto.render = function render() { var _this$props = this.props, ariaLabel = _this$props.ariaLabel, children = _this$props.children, className = _this$props.className, height = _this$props.height, onMouseMove = _this$props.onMouseMove, onMouseLeave = _this$props.onMouseLeave, preserveAspectRatio = _this$props.preserveAspectRatio, styles = _this$props.styles, width = _this$props.width, viewBox = _this$props.viewBox; var _this$state = this.state, data = _this$state.data, margin = _this$state.margin, xScale = _this$state.xScale, yScale = _this$state.yScale; var seriesProps = { xScale: xScale, yScale: yScale, data: data, getX: getX, getY: getY, margin: margin }; return React.createElement("svg", { "aria-label": ariaLabel, className: className, height: height, role: "img", preserveAspectRatio: preserveAspectRatio, style: styles, width: width, viewBox: viewBox }, React.createElement(Group, { left: margin.left, top: margin.top }, React.Children.map(children, function (Child) { var name = componentName(Child); if (isSeries(name) || isReferenceLine(name) || isBandLine(name)) { return React.cloneElement(Child, seriesProps); } return Child; }), (onMouseMove || onMouseLeave) && React.createElement(BarSeries, _extends({ fill: "transparent", fillOpacity: 0, stroke: "transparent", strokeWidth: 1 }, seriesProps, { getY: this.getMaxY, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave })))); }; return Sparkline; }(React.PureComponent); Sparkline.propTypes = propTypes; Sparkline.defaultProps = defaultProps; Sparkline.displayName = 'Sparkline'; export default Sparkline;