UNPKG

wix-style-react

Version:
464 lines (404 loc) • 18.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _d3Scale = require("d3-scale"); var _d3Array = require("d3-array"); var _d3Shape = require("d3-shape"); var _d3Selection = require("d3-selection"); var _d3Ease = require("d3-ease"); var _ChartTooltip = require("./ChartTooltip"); var _constants = require("./constants"); var _colorsSt = require("../Foundation/stylable/colors.st.css"); require("d3-transition"); function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } var LINE_WIDTH = 2; var AREA_MASK_ID = 'areaMaskId'; var TOOLTIP_ELEMENT_RADIUS = 4; var DEFAULT_COLOR = _colorsSt.stVars.A1; /** SparklineChart */ var SparklineChart = /*#__PURE__*/function (_React$PureComponent) { (0, _inherits2["default"])(SparklineChart, _React$PureComponent); var _super = _createSuper(SparklineChart); function SparklineChart(props) { var _this; (0, _classCallCheck2["default"])(this, SparklineChart); _this = _super.call(this, props); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_shouldShowTooltip", function () { var hoveredLabel = _this.state.hoveredLabel; var getTooltipContent = _this.props.getTooltipContent; return getTooltipContent && typeof getTooltipContent === 'function' && hoveredLabel; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_useCreateContext", function () { var halfWidth = LINE_WIDTH / 2; var _this$props = _this.props, _this$props$width = _this$props.width, width = _this$props$width === void 0 ? 200 : _this$props$width, _this$props$height = _this$props.height, height = _this$props$height === void 0 ? 40 : _this$props$height, data = _this$props.data, _this$props$highlight = _this$props.highlightedStartingIndex, highlightedStartingIndex = _this$props$highlight === void 0 ? 0 : _this$props$highlight, _this$props$color = _this$props.color, color = _this$props$color === void 0 ? DEFAULT_COLOR : _this$props$color; var margin = { top: halfWidth + 2, right: halfWidth, bottom: halfWidth, left: halfWidth }; var innerTop = margin.top; var innerLeft = margin.left; var innerHeight = height - innerTop - margin.bottom; var innerWidth = width - innerLeft - margin.right; var maxValue = (0, _d3Array.max)(_this._getValues(data)); var firstLabel = _this._getLabelAt(data, 0); var lastLabel = _this._getLabelAt(data, data.length - 1); var xScale = (0, _d3Scale.scaleTime)().domain([firstLabel, lastLabel]).range([innerLeft, innerWidth]); var yScale = (0, _d3Scale.scaleLinear)().domain([0, maxValue]).range([innerHeight, innerTop]); var lineGenerator = (0, _d3Shape.line)().x(function (dataPoint, i) { return xScale(_this._getLabelAt(data, i)); }).y(function (dataPoint) { return yScale(dataPoint); }).curve(_d3Shape.curveMonotoneX); var areaGenerator = (0, _d3Shape.area)().x(function (dataPoint, i) { return xScale(_this._getLabelAt(data, i)); }).y0(function () { return innerHeight; }).y1(function (dataPoint) { return yScale(dataPoint); }).curve(_d3Shape.curveMonotoneX); return { margin: margin, width: width, height: height, innerTop: innerTop, innerLeft: innerLeft, innerBottom: margin.top + innerHeight, innerWidth: innerWidth, innerHeight: innerHeight, data: data, xScale: xScale, yScale: yScale, highlightedStartingIndex: highlightedStartingIndex, lineGenerator: lineGenerator, areaGenerator: areaGenerator, color: color }; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_getLabelAt", function (data, position) { return data[position] && data[position].label; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_getValues", function (data) { return data.map(function (pair) { return pair.value; }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_getLabels", function (data) { return data.map(function (pair) { return pair.label; }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_drawSparkline", function () { var _this$chartContext = _this.chartContext, width = _this$chartContext.width, height = _this$chartContext.height, data = _this$chartContext.data; var onHover = _this.props.onHover; var labels = _this._getLabels(data); var container = (0, _d3Selection.select)(_this.svgRef.current); container.attr('width', width).attr('height', height); var dataContainer = container.select("[data-hook=\"".concat(_constants.dataHooks.dataContainer, "\"]")); _this._drawLines(dataContainer); (0, _d3Selection.select)(_this.componentRef.current).on('mouseleave', function () { _this.setState({ hoveredLabel: null }); }).on('mousemove', function (d) { var dateUnderPointer = _this.chartContext.xScale.invert((0, _d3Selection.pointer)(d)[0]); var currentDateIndex = (0, _d3Array.bisector)(function (date) { return date; }).left(labels, dateUnderPointer, 1); var beforeDateIndex = currentDateIndex - 1; var beforeDate = labels[beforeDateIndex]; var afterDate = labels[currentDateIndex]; var closestDate = +dateUnderPointer - +beforeDate > +afterDate - +dateUnderPointer ? afterDate : beforeDate; if (typeof onHover === 'function' && !_this._areDatesEqual(closestDate, _this.state.hoveredLabel)) { var labelIndex = labels.indexOf(closestDate); onHover(labelIndex); } _this.setState({ hoveredLabel: closestDate }); }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_drawLines", function (dataContainer) { var _this$chartContext2 = _this.chartContext, data = _this$chartContext2.data, lineGenerator = _this$chartContext2.lineGenerator, areaGenerator = _this$chartContext2.areaGenerator, color = _this$chartContext2.color; var dataSets = [data]; dataContainer.selectAll('.chartLines').data(dataSets).join('g').attr('class', 'chartLines').selectAll('g').data(function (dataSet) { return [dataSet]; }).join(function (enter) { var group = enter.append('g'); group.append('path').attr('class', 'innerArea').attr('mask', "url(#".concat(_this._getAreaMaskId(_this.randomComponentId), ")")).attr('fill', function (dataSet) { return "url(#".concat(color, ")"); }).attr('d', function (dataSet) { return areaGenerator(dataSet.map(function () { return 0; })); }); group.append('path').attr('class', 'innerLineBack').attr('fill', 'none').attr('stroke-width', LINE_WIDTH + 4).attr('stroke-linecap', 'round').attr('stroke', 'white').attr('d', function (dataSet) { return lineGenerator(dataSet.map(function () { return 0; })); }); group.append('path').attr('class', 'innerLine').attr('fill', 'none').attr('stroke-width', LINE_WIDTH).attr('stroke-linecap', 'round').attr('stroke', function (dataSet) { return "url(#".concat(_this._getLineColorId(dataSet, _this.randomComponentId), ")"); }).attr('d', function (dataSet) { return lineGenerator(dataSet.map(function () { return 0; })); }); _this._updateLines(group); return group; }, function (update) { _this._updateLines(update); return update; }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_updateLines", function (container) { var _this$chartContext3 = _this.chartContext, lineGenerator = _this$chartContext3.lineGenerator, areaGenerator = _this$chartContext3.areaGenerator; _this._updateComponent(container, '.innerLine', function (set) { return lineGenerator(_this._getValues(set)); }); _this._updateComponent(container, '.innerLineBack', function (set) { return lineGenerator(_this._getValues(set)); }); _this._updateComponent(container, '.innerArea', function (set) { return areaGenerator(_this._getValues(set)); }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_updateComponent", function (container, className, fncUpdater) { var animationDuration = _this.props.animationDuration; container.select(className).transition().duration(animationDuration).ease(_d3Ease.easeQuadIn).attr('d', fncUpdater); }); _this.randomComponentId = Math.random().toString(); _this.chartContext = {}; _this.svgRef = /*#__PURE__*/_react["default"].createRef(null); _this.componentRef = /*#__PURE__*/_react["default"].createRef(null); _this.state = { hoveredLabel: null }; return _this; } (0, _createClass2["default"])(SparklineChart, [{ key: "_getValueAt", value: function _getValueAt(data, position) { return data[position] && data[position].value; } }, { key: "_areDatesEqual", value: function _areDatesEqual(date1, date2) { var date1Time = date1 && date1.getTime(); var date2Time = date2 && date2.getTime(); return date1Time === date2Time; } }, { key: "_getLineColorId", value: function _getLineColorId(dataSet, componentId) { return "".concat(componentId, "color"); } }, { key: "_getAreaMaskId", value: function _getAreaMaskId(componentId) { return "".concat(AREA_MASK_ID).concat(componentId); } }, { key: "componentDidMount", value: function componentDidMount() { this._drawSparkline(); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { if (prevProps.data !== this.props.data) { this._drawSparkline(); } } }, { key: "_updateContext", value: function _updateContext() { this.chartContext = this._useCreateContext(); } }, { key: "render", value: function render() { this._updateContext(); var _this$props2 = this.props, getTooltipContent = _this$props2.getTooltipContent, className = _this$props2.className, dataHook = _this$props2.dataHook; var hoveredLabel = this.state.hoveredLabel; var context = this.chartContext; var data = context.data, highlightedStartingIndex = context.highlightedStartingIndex, innerWidth = context.innerWidth, height = context.height, width = context.width, color = context.color; var highlightedStartBefore = context.xScale(this._getLabelAt(data, highlightedStartingIndex - 1)); var highlightedStart = context.xScale(this._getLabelAt(data, highlightedStartingIndex)); var highlightedRelativeLocation = highlightedStart / innerWidth; var inter = (highlightedStart - highlightedStartBefore) / 2 / innerWidth; var labels = this._getLabels(data); var hoveredLabelIndex = (0, _d3Array.bisector)(function (d) { return d; }).left(labels, hoveredLabel, 0); var currentHoveredLabel = this._getLabelAt(data, hoveredLabelIndex); var currentHoveredValue = this._getValueAt(data, hoveredLabelIndex); var dataPoint = { content: getTooltipContent && typeof getTooltipContent === 'function' && getTooltipContent(hoveredLabelIndex), xCoordinate: context.xScale(currentHoveredLabel), yCoordinate: context.yScale(currentHoveredValue) - TOOLTIP_ELEMENT_RADIUS / 2 }; var enableHighlightedAreaEffect = highlightedStartingIndex > 0; return /*#__PURE__*/_react["default"].createElement("div", { style: { width: width, height: height, position: 'relative' }, ref: this.componentRef, className: className, "data-hook": dataHook }, /*#__PURE__*/_react["default"].createElement("svg", { style: { overflow: 'visible', zIndex: 1 }, ref: this.svgRef }, /*#__PURE__*/_react["default"].createElement("defs", null, /*#__PURE__*/_react["default"].createElement("mask", { id: this._getAreaMaskId(this.randomComponentId) }, /*#__PURE__*/_react["default"].createElement("rect", { x: highlightedStart, y: "0", width: width, height: height, fill: "white" })), /*#__PURE__*/_react["default"].createElement("linearGradient", { gradientUnits: 'userSpaceOnUse', key: "".concat(this.randomComponentId, "a"), id: this._getLineColorId(data, this.randomComponentId), x1: "0px", y1: "0px", x2: "".concat(innerWidth, "px"), y2: '0px' }, enableHighlightedAreaEffect && [/*#__PURE__*/_react["default"].createElement("stop", { key: 0, offset: "0", style: { stopColor: '#dfe5eb', stopOpacity: 1 } }), /*#__PURE__*/_react["default"].createElement("stop", { key: 1, offset: highlightedRelativeLocation - inter, style: { stopColor: '#dfe5eb', stopOpacity: 1 } }), /*#__PURE__*/_react["default"].createElement("stop", { key: 2, offset: highlightedRelativeLocation, style: { stopColor: color, stopOpacity: 1 } })], /*#__PURE__*/_react["default"].createElement("stop", { offset: "1", style: { stopColor: color, stopOpacity: 1 } })), /*#__PURE__*/_react["default"].createElement("linearGradient", { gradientUnits: 'userSpaceOnUse', key: this.randomComponentId, id: color, x1: "0px", y1: "".concat(context.innerHeight, "px"), x2: "0px", y2: '0px' }, /*#__PURE__*/_react["default"].createElement("stop", { offset: "10%", style: { stopColor: color, stopOpacity: 0 } }), /*#__PURE__*/_react["default"].createElement("stop", { offset: "90%", style: { stopColor: color, stopOpacity: 0.5 } }))), /*#__PURE__*/_react["default"].createElement("g", null, /*#__PURE__*/_react["default"].createElement("g", { "data-hook": _constants.dataHooks.dataContainer }), this._shouldShowTooltip() && /*#__PURE__*/_react["default"].createElement("g", { transform: "translate(".concat(dataPoint.xCoordinate, ", ").concat(dataPoint.yCoordinate + TOOLTIP_ELEMENT_RADIUS / 2, ")") }, /*#__PURE__*/_react["default"].createElement("circle", { r: TOOLTIP_ELEMENT_RADIUS, fill: color })))), this._shouldShowTooltip() && /*#__PURE__*/_react["default"].createElement(_ChartTooltip.ChartTooltip, { dataPoint: dataPoint })); } }]); return SparklineChart; }(_react["default"].PureComponent); SparklineChart.displayName = 'SparklineChart'; SparklineChart.propTypes = { /** Applied as data-hook HTML attribute that can be used in the tests */ dataHook: _propTypes["default"].string, /** A css class to be applied to the component's root element */ className: _propTypes["default"].string, /** Sets the width of the sparkline (pixels) */ width: _propTypes["default"].number, /** Sets the height of the sparkline (pixels) */ height: _propTypes["default"].number, /** Chart data */ data: _propTypes["default"].arrayOf(_propTypes["default"].shape({ label: _propTypes["default"].instanceOf(Date), value: _propTypes["default"].number })).isRequired, /** Sets the color of the sparkline */ color: _propTypes["default"].string, /** Indicates the starting index of the highlighted area. Default is 0 */ highlightedStartingIndex: _propTypes["default"].number, /** Tooltip content (JSX) getter function. */ getTooltipContent: _propTypes["default"].func, /** callback when graph is hovered*/ onHover: _propTypes["default"].func, /** Sets the duration of the animation in milliseconds */ animationDuration: _propTypes["default"].number }; SparklineChart.defaultProps = { animationDuration: 300 }; var _default = SparklineChart; exports["default"] = _default;