wix-style-react
Version:
454 lines (414 loc) • 17.9 kB
JavaScript
"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 />
 - `value` - a number that represents value in chart<br />
 - `label` - a label that represents value description around the chart<br />
 - `color` - data point color.<br />
 - `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 />
 - `value` - a number representing scale<br />
 - `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;