UNPKG

wix-style-react

Version:
454 lines (414 loc) • 17.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _d3Scale = require("d3-scale"); var _d3Selection = require("d3-selection"); var _d3Shape = require("d3-shape"); var _constants = require("./constants"); var _RadarChartSt = require("./RadarChart.st.css"); var _colorsSt = require("../Foundation/stylable/colors.st.css"); var _Tooltip = _interopRequireDefault(require("../Tooltip")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var BLUE_COLOR = '#3899ec'; var DISABLED_COLOR = '#879cae'; var DOT_RADIUS = 2; var LINE_DY = 0.35; var LINE_HEIGHT = 1.4; var PADDING = 12; var AXIS_LABEL_DY = 12; var getXY = function getXY(value, index, angle, rScale) { var shift = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; return { x: (rScale(value) + shift) * Math.cos(angle * index - Math.PI / 2), y: (rScale(value) + shift) * Math.sin(angle * index - Math.PI / 2) }; }; var CirclesSVG = /*#__PURE__*/(0, _react.memo)(function (_ref) { var scale = _ref.scale, rScale = _ref.rScale; return scale.map(function (_ref2, index) { var value = _ref2.value; return /*#__PURE__*/_react["default"].createElement("circle", { key: index, "data-hook": _constants.dataHooks.radarChartScaleLine, className: _RadarChartSt.classes.circles, r: rScale(value), cx: 0, cy: 0 }); }).reverse(); }); var WebChartSVG = /*#__PURE__*/(0, _react.memo)(function (_ref3) { var disabled = _ref3.disabled, dots = _ref3.dots; if (disabled || dots.length === 0) { return; } return /*#__PURE__*/_react["default"].createElement("defs", null, /*#__PURE__*/_react["default"].createElement("linearGradient", { id: "gradient", x1: "0", x2: "1", y1: "0", y2: "0" }, /*#__PURE__*/_react["default"].createElement("stop", { offset: "0", stopColor: dots[dots.length - 1].color }), /*#__PURE__*/_react["default"].createElement("stop", { offset: "1", stopColor: dots[0].color }))); }); var OuterLabels = /*#__PURE__*/(0, _react.memo)(function (_ref4) { var data = _ref4.data, maxScaleValue = _ref4.maxScaleValue, angle = _ref4.angle, rScale = _ref4.rScale, labelDistance = _ref4.labelDistance, disabled = _ref4.disabled, internalHoverIndex = _ref4.internalHoverIndex, width = _ref4.width, setInternalHoverIndex = _ref4.setInternalHoverIndex; var outerCircleDots = data.map(function (_ref5, index) { var label = _ref5.label; return { label: label, labelPoint: getXY(maxScaleValue, index, angle, rScale, labelDistance), linePoint: getXY(maxScaleValue, index, angle, rScale) }; }); return outerCircleDots.map(function (_ref6, index) { var label = _ref6.label, labelPoint = _ref6.labelPoint, linePoint = _ref6.linePoint; return /*#__PURE__*/_react["default"].createElement("g", { key: index, "data-hook": _constants.dataHooks.radarChartDataItem }, /*#__PURE__*/_react["default"].createElement("line", { className: _RadarChartSt.classes.axis, x1: 0, y1: 0, x2: linePoint.x, y2: linePoint.y }), /*#__PURE__*/_react["default"].createElement("text", { className: (0, _RadarChartSt.st)(_RadarChartSt.classes.axisLabel, { hovered: index === internalHoverIndex, size: width < 360 ? 'small' : 'large', disabled: disabled }), "data-hook": "axisName".concat(index), x: labelPoint.x, y: labelPoint.y, dy: "".concat(LINE_DY, "em"), textAnchor: "middle", onMouseEnter: function onMouseEnter() { return !disabled && setInternalHoverIndex(index); }, onMouseLeave: function onMouseLeave() { return !disabled && setInternalHoverIndex(null); } }, label)); }); }); var ScaleValues = /*#__PURE__*/(0, _react.memo)(function (_ref7) { var scale = _ref7.scale, rScale = _ref7.rScale; var scaleValues = scale.map(function (_ref8) { var value = _ref8.value, label = _ref8.label; return _objectSpread({ value: value, label: label }, getXY(value, 0, 0, rScale)); }); return scaleValues.map(function (_ref9, index) { var label = _ref9.label, y = _ref9.y; return /*#__PURE__*/_react["default"].createElement("text", { key: index, className: _RadarChartSt.classes.scaleLabel, x: 0, y: y, dy: AXIS_LABEL_DY, textAnchor: "middle" }, label); }); }); var DataPoints = /*#__PURE__*/(0, _react.memo)(function (_ref10) { var dots = _ref10.dots, disabled = _ref10.disabled, internalHoverIndex = _ref10.internalHoverIndex, setInternalHoverIndex = _ref10.setInternalHoverIndex; return dots.map(function (dot, index) { return /*#__PURE__*/_react["default"].createElement("g", { key: index }, /*#__PURE__*/_react["default"].createElement("circle", { r: !disabled && index === internalHoverIndex ? DOT_RADIUS * 2 : DOT_RADIUS, cx: dot.x, cy: dot.y, fill: disabled ? DISABLED_COLOR : dots[index].color }), /*#__PURE__*/_react["default"].createElement("circle", (0, _extends2["default"])({ className: (0, _RadarChartSt.st)(_RadarChartSt.classes.dataPoint, { disabled: disabled }), r: DOT_RADIUS * 4, cx: dot.x, cy: dot.y, fillOpacity: 0, onMouseEnter: function onMouseEnter() { return !disabled && setInternalHoverIndex(index); }, onMouseLeave: function onMouseLeave() { return !disabled && setInternalHoverIndex(null); } }, !disabled && { focusable: true, tabIndex: 0, onFocus: function onFocus() { return !disabled && setInternalHoverIndex(index); }, onBlur: function onBlur() { return !disabled && setInternalHoverIndex(null); } }))); }); }); var DataPointsTooltips = /*#__PURE__*/(0, _react.memo)(function (_ref11) { var dots = _ref11.dots, containerWidth = _ref11.containerWidth, internalHoverIndex = _ref11.internalHoverIndex, disabled = _ref11.disabled; return dots.map(function (_ref12, index) { var x = _ref12.x, y = _ref12.y, tooltipContent = _ref12.tooltipContent, value = _ref12.value; return /*#__PURE__*/_react["default"].createElement("div", { key: index, style: { position: 'absolute', left: x + containerWidth / 2, top: y + containerWidth / 2 - 7 } }, /*#__PURE__*/_react["default"].createElement(_Tooltip["default"], { className: _RadarChartSt.classes.tooltip, shown: index === internalHoverIndex, content: tooltipContent !== null && tooltipContent !== void 0 ? tooltipContent : value, disabled: disabled }, /*#__PURE__*/_react["default"].createElement("div", null))); }); }); var WebChartLine = /*#__PURE__*/(0, _react.memo)(function (_ref13) { var disabled = _ref13.disabled, data = _ref13.data, angle = _ref13.angle, rScale = _ref13.rScale; var ref = (0, _react.useRef)(null); (0, _react.useEffect)(function () { if (ref.current && data.length) { (0, _d3Selection.select)(ref.current).selectAll("[data-hook='curvePart']").remove(); var drawCurve = (0, _d3Shape.lineRadial)().curve(_d3Shape.curveCardinalClosed).radius(function (d) { return rScale(d.value); }).angle(function (_d, i) { return i * angle; }); var blob = (0, _d3Selection.select)(ref.current).selectAll("[data-hook='curvePart']").data([data]).enter().append('g').attr('data-hook', 'curvePart'); blob.append('path').attr('d', function (d) { return drawCurve(d); }).style('stroke', BLUE_COLOR).style('stroke-width', '1px').style('stroke', disabled ? DISABLED_COLOR : 'url(#gradient)').style('fill', disabled ? DISABLED_COLOR : 'url(#gradient)').style('stroke-dasharray', disabled ? 6 : null).style('fill-opacity', 0.3); } }, [ref, data, disabled, rScale, angle]); return /*#__PURE__*/_react["default"].createElement("g", { ref: ref }); }); var RadarChart = function RadarChart(_ref14) { var dataHook = _ref14.dataHook, data = _ref14.data, scale = _ref14.scale, disabled = _ref14.disabled, width = _ref14.width, labelDistance = _ref14.labelDistance, hoverIndex = _ref14.hoverIndex, labelWidth = _ref14.labelWidth, onDataPointHover = _ref14.onDataPointHover; var _useState = (0, _react.useState)(hoverIndex), _useState2 = (0, _slicedToArray2["default"])(_useState, 2), internalHoverIndex = _useState2[0], setInternalHoverIndex = _useState2[1]; var containerWidth = (0, _react.useMemo)(function () { return width + labelDistance * 4 + PADDING * 2; }, [width, labelDistance]); var maxScaleValue = (0, _react.useMemo)(function () { return Math.max.apply(Math, (0, _toConsumableArray2["default"])(scale.map(function (_ref15) { var value = _ref15.value; return value; }))); }, [scale]); var rScale = (0, _react.useMemo)(function () { return (0, _d3Scale.scaleLinear)().range([0, width / 2]).domain([0, maxScaleValue]); }, [width, maxScaleValue]); var angle = (0, _react.useMemo)(function () { return Math.PI * 2 / data.length; }, [data]); var dots = (0, _react.useMemo)(function () { return data.map(function (_ref16, index) { var value = _ref16.value, label = _ref16.label, color = _ref16.color, tooltipContent = _ref16.tooltipContent; return _objectSpread({ value: value, label: label, color: _colorsSt.stVars[color] || color || _colorsSt.stVars['A1'], tooltipContent: tooltipContent }, getXY(value, index, angle, rScale)); }); }, [data, angle, rScale]); (0, _react.useEffect)(function () { return setInternalHoverIndex(hoverIndex); }, [hoverIndex]); (0, _react.useEffect)(function () { if (internalHoverIndex === null) { return; } onDataPointHover(data[internalHoverIndex], internalHoverIndex); }, [internalHoverIndex, onDataPointHover, data]); (0, _react.useEffect)(function () { data.forEach(function (_ref17, index) { var label = _ref17.label; var text = (0, _d3Selection.select)(containerRef.current).select("[data-hook='axisName".concat(index, "']")); var words = label.split(/\s+/); var word; var line = []; var lineNumber = 0; var tspan = text.text(null).append('tspan').attr('x', text.attr('x')).attr('y', text.attr('y')).attr('dy', "".concat(LINE_DY, "em")); while (words.length) { word = words.shift(); line.push(word); tspan.text(line.join(' ')); if (tspan.node && tspan.node().getComputedTextLength && tspan.node().getComputedTextLength() > labelWidth) { line.pop(); tspan.text(line.join(' ')); line = [word]; tspan = text.append('tspan').attr('x', text.attr('x')).attr('y', text.attr('y')).attr('dy', "".concat(++lineNumber * LINE_HEIGHT + LINE_DY, "em")).text(word); } } }); }); var containerRef = (0, _react.useRef)(null); return /*#__PURE__*/_react["default"].createElement("div", { "data-hook": dataHook, className: _RadarChartSt.classes.root, style: { width: containerWidth, height: containerWidth }, "data-disabled": disabled, "data-hover-index": internalHoverIndex }, /*#__PURE__*/_react["default"].createElement("svg", { width: containerWidth, height: containerWidth, ref: containerRef }, /*#__PURE__*/_react["default"].createElement("g", { transform: "translate(".concat(containerWidth / 2, ", ").concat(containerWidth / 2, ")") }, /*#__PURE__*/_react["default"].createElement(WebChartSVG, { dots: dots, disabled: disabled }), /*#__PURE__*/_react["default"].createElement(CirclesSVG, { scale: scale, rScale: rScale }), /*#__PURE__*/_react["default"].createElement(OuterLabels, { data: data, maxScaleValue: maxScaleValue, angle: angle, rScale: rScale, labelDistance: labelDistance, disabled: disabled, internalHoverIndex: internalHoverIndex, width: width, setInternalHoverIndex: setInternalHoverIndex }), /*#__PURE__*/_react["default"].createElement(ScaleValues, { scale: scale, rScale: rScale }), /*#__PURE__*/_react["default"].createElement(WebChartLine, { disabled: disabled, data: data, angle: angle, rScale: rScale }), /*#__PURE__*/_react["default"].createElement(DataPoints, { dots: dots, disabled: disabled, internalHoverIndex: internalHoverIndex, setInternalHoverIndex: setInternalHoverIndex }))), /*#__PURE__*/_react["default"].createElement(DataPointsTooltips, { dots: dots, disabled: disabled, containerWidth: containerWidth, internalHoverIndex: internalHoverIndex, setInternalHoverIndex: setInternalHoverIndex })); }; RadarChart.displayName = 'RadarChart'; RadarChart.propTypes = { /** Applies a data-hook HTML attribute that can be used in tests */ dataHook: _propTypes["default"].string, /** Defines data points that construct spider web-like charts. Available properties for array items:<br /> &emsp;- `value` - a number that represents value in chart<br /> &emsp;- `label` - a label that represents value description around the chart<br /> &emsp;- `color` - data point color.<br /> &emsp;- `tooltipContent` - data point tooltip content */ data: _propTypes["default"].arrayOf(_propTypes["default"].shape({ value: _propTypes["default"].number, label: _propTypes["default"].string, color: _propTypes["default"].string, tooltipContent: _propTypes["default"].node })), /** Defines a number of scale circles in the chart. Available properties for each scale:<br /> &emsp;- `value` - a number representing scale<br /> &emsp;- `suffix` - a string that represents value meaning (i.e. % or $) */ scale: _propTypes["default"].arrayOf(_propTypes["default"].shape({ value: _propTypes["default"].number, label: _propTypes["default"].string })), /** Specifies whether graph is disabled */ disabled: _propTypes["default"].bool, /** Controls the width of a graph. Minimum width is 150 pixels. */ width: _propTypes["default"].number, /** Controls label distance from a chart */ labelDistance: _propTypes["default"].number, /** Defines the index of a data point in hover state */ hoverIndex: _propTypes["default"].number, /** Defines maximum width of data labels */ labelWidth: _propTypes["default"].number, /** Defines a callback function which is called every time user hovers over a data point. Includes all data point data as first argument and index as second. */ onDataPointHover: _propTypes["default"].func }; RadarChart.defaultProps = { data: [], scale: [{ value: 50, label: '50%' }, { value: 100, label: '100%' }], width: 150, labelDistance: 50, labelWidth: 100, onDataPointHover: function onDataPointHover() {} }; var _default = RadarChart; exports["default"] = _default;