UNPKG

wix-style-react

Version:
562 lines (561 loc) • 18.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; 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")); var _jsxFileName = "/home/builduser/work/a9c1ac8876d5057c/packages/wix-style-react/dist/cjs/RadarChart/RadarChart.js"; function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } 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)(_ref => { var { scale, rScale } = _ref; return scale.map((_ref2, index) => { var { value } = _ref2; return /*#__PURE__*/_react.default.createElement("circle", { key: index, "data-hook": _constants.dataHooks.radarChartScaleLine, className: (0, _RadarChartSt.st)(_RadarChartSt.classes.circles, { isTransparent: index !== scale.length - 1 }), r: rScale(value), cx: 0, cy: 0, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 28, columnNumber: 7 } }); }).reverse(); }); var WebChartSVG = /*#__PURE__*/(0, _react.memo)(_ref3 => { var { disabled, dots } = _ref3; if (disabled || dots.length === 0) { return; } return /*#__PURE__*/_react.default.createElement("defs", { __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 48, columnNumber: 5 } }, /*#__PURE__*/_react.default.createElement("linearGradient", { id: "gradient", x1: "0", x2: "1", y1: "0", y2: "0", __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 49, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement("stop", { offset: "0", stopColor: dots[dots.length - 1].color, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 50, columnNumber: 9 } }), /*#__PURE__*/_react.default.createElement("stop", { offset: "1", stopColor: dots[0].color, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 51, columnNumber: 9 } }))); }); var OuterLabels = /*#__PURE__*/(0, _react.memo)(_ref4 => { var { data, maxScaleValue, angle, rScale, labelDistance, disabled, internalHoverIndex, width, setInternalHoverIndex } = _ref4; var outerCircleDots = data.map((_ref5, index) => { var { label } = _ref5; return { label, labelPoint: getXY(maxScaleValue, index, angle, rScale, labelDistance), linePoint: getXY(maxScaleValue, index, angle, rScale) }; }); return outerCircleDots.map((_ref6, index) => { var { label, labelPoint, linePoint } = _ref6; return /*#__PURE__*/_react.default.createElement("g", { key: index, "data-hook": _constants.dataHooks.radarChartDataItem, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 76, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement("line", { className: _RadarChartSt.classes.axis, x1: 0, y1: 0, x2: linePoint.x, y2: linePoint.y, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 77, columnNumber: 9 } }), /*#__PURE__*/_react.default.createElement("text", { className: (0, _RadarChartSt.st)(_RadarChartSt.classes.axisLabel, { hovered: index === internalHoverIndex, size: width < 360 ? 'small' : 'large', disabled }), "data-hook": "axisName".concat(index), x: labelPoint.x, y: labelPoint.y, dy: "".concat(LINE_DY, "em"), textAnchor: "middle", onMouseEnter: () => !disabled && setInternalHoverIndex(index), onMouseLeave: () => !disabled && setInternalHoverIndex(null), __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 84, columnNumber: 9 } }, label)); }); }); var ScaleValues = /*#__PURE__*/(0, _react.memo)(_ref7 => { var { scale, rScale } = _ref7; var scaleValues = scale.map(_ref8 => { var { value, label } = _ref8; return _objectSpread({ value, label }, getXY(value, 0, 0, rScale)); }); return scaleValues.map((_ref9, index) => { var { label, y } = _ref9; return /*#__PURE__*/_react.default.createElement("text", { key: index, className: _RadarChartSt.classes.scaleLabel, x: 0, y: y, dy: AXIS_LABEL_DY, textAnchor: "middle", __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 112, columnNumber: 5 } }, label); }); }); var DataPoints = /*#__PURE__*/(0, _react.memo)(_ref0 => { var { dots, disabled, internalHoverIndex, setInternalHoverIndex } = _ref0; return dots.map((dot, index) => /*#__PURE__*/_react.default.createElement("g", { key: index, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 128, columnNumber: 7 } }, /*#__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, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 129, columnNumber: 9 } }), /*#__PURE__*/_react.default.createElement("circle", (0, _extends2.default)({ className: (0, _RadarChartSt.st)(_RadarChartSt.classes.dataPoint, { disabled }), r: DOT_RADIUS * 4, cx: dot.x, cy: dot.y, fillOpacity: 0, onMouseEnter: () => !disabled && setInternalHoverIndex(index), onMouseLeave: () => !disabled && setInternalHoverIndex(null) }, !disabled && { focusable: true, tabIndex: 0, onFocus: () => !disabled && setInternalHoverIndex(index), onBlur: () => !disabled && setInternalHoverIndex(null) }, { __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 139, columnNumber: 9 } })))); }); var DataPointsTooltips = /*#__PURE__*/(0, _react.memo)(_ref1 => { var { dots, containerWidth, internalHoverIndex, disabled } = _ref1; return dots.map((_ref10, index) => { var { x, y, tooltipContent, value } = _ref10; return /*#__PURE__*/_react.default.createElement("div", { key: index, style: { position: 'absolute', left: x + containerWidth / 2, top: y + containerWidth / 2 - 7 }, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 161, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement(_Tooltip.default, { className: _RadarChartSt.classes.tooltip, shown: index === internalHoverIndex, content: tooltipContent !== null && tooltipContent !== void 0 ? tooltipContent : value, disabled: disabled, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 169, columnNumber: 9 } }, /*#__PURE__*/_react.default.createElement("div", { __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 175, columnNumber: 11 } }))); }); }); var WebChartLine = /*#__PURE__*/(0, _react.memo)(_ref11 => { var { disabled, data, angle, rScale } = _ref11; var ref = (0, _react.useRef)(null); (0, _react.useEffect)(() => { if (ref.current && data.length) { (0, _d3Selection.select)(ref.current).selectAll("[data-hook='curvePart']").remove(); var drawCurve = (0, _d3Shape.lineRadial)().curve(_d3Shape.curveCardinalClosed).radius(d => rScale(d.value)).angle((_d, i) => 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', d => 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, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 211, columnNumber: 10 } }); }); var RadarChart = _ref12 => { var { dataHook, data = [], scale = [{ value: 50, label: '50%' }, { value: 100, label: '100%' }], disabled, width = 150, labelDistance = 50, hoverIndex, labelWidth = 100, onDataPointHover = () => {} } = _ref12; var [internalHoverIndex, setInternalHoverIndex] = (0, _react.useState)(hoverIndex); var containerWidth = (0, _react.useMemo)(() => width + labelDistance * 4 + PADDING * 2, [width, labelDistance]); var maxScaleValue = (0, _react.useMemo)(() => Math.max(...scale.map(_ref13 => { var { value } = _ref13; return value; })), [scale]); var rScale = (0, _react.useMemo)(() => (0, _d3Scale.scaleLinear)().range([0, width / 2]).domain([0, maxScaleValue]), [width, maxScaleValue]); var angle = (0, _react.useMemo)(() => Math.PI * 2 / data.length, [data]); var dots = (0, _react.useMemo)(() => data.map((_ref14, index) => { var { value, label, color, tooltipContent } = _ref14; return _objectSpread({ value, label, color: _colorsSt.stVars[color] || color || _colorsSt.stVars['A1'], tooltipContent }, getXY(value, index, angle, rScale)); }), [data, angle, rScale]); (0, _react.useEffect)(() => setInternalHoverIndex(hoverIndex), [hoverIndex]); (0, _react.useEffect)(() => { if (internalHoverIndex === null) { return; } onDataPointHover(data[internalHoverIndex], internalHoverIndex); }, [internalHoverIndex, onDataPointHover, data]); (0, _react.useEffect)(() => { data.forEach((_ref15, index) => { var { label } = _ref15; 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, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 312, columnNumber: 5 } }, /*#__PURE__*/_react.default.createElement("svg", { width: containerWidth, height: containerWidth, ref: containerRef, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 319, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement("g", { transform: "translate(".concat(containerWidth / 2, ", ").concat(containerWidth / 2, ")"), __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 320, columnNumber: 9 } }, /*#__PURE__*/_react.default.createElement(WebChartSVG, { dots: dots, disabled: disabled, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 323, columnNumber: 11 } }), /*#__PURE__*/_react.default.createElement(CirclesSVG, { scale: scale, rScale: rScale, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 324, columnNumber: 11 } }), /*#__PURE__*/_react.default.createElement(OuterLabels, { data: data, maxScaleValue: maxScaleValue, angle: angle, rScale: rScale, labelDistance: labelDistance, disabled: disabled, internalHoverIndex: internalHoverIndex, width: width, setInternalHoverIndex: setInternalHoverIndex, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 325, columnNumber: 11 } }), /*#__PURE__*/_react.default.createElement(ScaleValues, { scale: scale, rScale: rScale, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 336, columnNumber: 11 } }), /*#__PURE__*/_react.default.createElement(WebChartLine, { disabled: disabled, data: data, angle: angle, rScale: rScale, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 337, columnNumber: 11 } }), /*#__PURE__*/_react.default.createElement(DataPoints, { dots: dots, disabled: disabled, internalHoverIndex: internalHoverIndex, setInternalHoverIndex: setInternalHoverIndex, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 343, columnNumber: 11 } }))), /*#__PURE__*/_react.default.createElement(DataPointsTooltips, { dots: dots, disabled: disabled, containerWidth: containerWidth, internalHoverIndex: internalHoverIndex, setInternalHoverIndex: setInternalHoverIndex, __self: void 0, __source: { fileName: _jsxFileName, lineNumber: 351, columnNumber: 7 } })); }; 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 }; var _default = exports.default = RadarChart; //# sourceMappingURL=RadarChart.js.map