zmp-react
Version:
Build full featured iOS & Android apps using ZMP & React
399 lines (345 loc) • 14.4 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _react = _interopRequireWildcard(require("react"));
var _utils = require("../shared/utils");
var _zmp = require("../shared/zmp");
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; }
var AreaChart = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
var className = props.className,
id = props.id,
style = props.style,
_props$lineChart = props.lineChart,
lineChart = _props$lineChart === void 0 ? false : _props$lineChart,
_props$datasets = props.datasets,
datasets = _props$datasets === void 0 ? [] : _props$datasets,
_props$axis = props.axis,
axis = _props$axis === void 0 ? false : _props$axis,
_props$axisLabels = props.axisLabels,
axisLabels = _props$axisLabels === void 0 ? [] : _props$axisLabels,
_props$tooltip = props.tooltip,
tooltip = _props$tooltip === void 0 ? false : _props$tooltip,
_props$legend = props.legend,
legend = _props$legend === void 0 ? false : _props$legend,
_props$toggleDatasets = props.toggleDatasets,
toggleDatasets = _props$toggleDatasets === void 0 ? false : _props$toggleDatasets,
_props$width = props.width,
width = _props$width === void 0 ? 640 : _props$width,
_props$height = props.height,
height = _props$height === void 0 ? 320 : _props$height,
_props$maxAxisLabels = props.maxAxisLabels,
maxAxisLabels = _props$maxAxisLabels === void 0 ? 8 : _props$maxAxisLabels,
formatAxisLabelProp = props.formatAxisLabel,
formatLegendLabelProp = props.formatLegendLabel,
formatTooltipProp = props.formatTooltip,
formatTooltipAxisLabel = props.formatTooltipAxisLabel,
formatTooltipTotal = props.formatTooltipTotal,
formatTooltipDataset = props.formatTooltipDataset,
children = props.children;
var _useState = (0, _react.useState)(null),
currentIndex = _useState[0],
setCurrentIndex = _useState[1];
var previousIndex = (0, _react.useRef)(null);
var _useState2 = (0, _react.useState)([]),
hiddenDatasets = _useState2[0],
setHiddenDatasets = _useState2[1];
var extraAttrs = (0, _utils.getExtraAttrs)(props);
var elRef = (0, _react.useRef)(null);
var svgElRef = (0, _react.useRef)(null);
var zmpTooltip = (0, _react.useRef)(null);
var linesOffsets = (0, _react.useRef)(null);
(0, _react.useImperativeHandle)(ref, function () {
return {
el: elRef.current
};
});
var getVisibleLegends = function getVisibleLegends() {
if (!maxAxisLabels || axisLabels.length <= maxAxisLabels) return axisLabels;
var skipStep = Math.ceil(axisLabels.length / maxAxisLabels);
var filtered = axisLabels.filter(function (label, index) {
return index % skipStep === 0;
});
return filtered;
};
var getSummValues = function getSummValues() {
var summValues = [];
datasets.filter(function (dataset, index) {
return !hiddenDatasets.includes(index);
}).forEach(function (_ref) {
var values = _ref.values;
values.forEach(function (value, valueIndex) {
if (!summValues[valueIndex]) summValues[valueIndex] = 0;
summValues[valueIndex] += value;
});
});
return summValues;
};
var getChartData = function getChartData() {
var data = [];
if (!datasets.length) {
return data;
}
var lastValues = datasets[0].values.map(function () {
return 0;
});
var maxValue = 0;
if (lineChart) {
datasets.forEach(function (_ref2) {
var values = _ref2.values;
var datasetMaxValue = Math.max.apply(Math, values);
if (datasetMaxValue > maxValue) maxValue = datasetMaxValue;
});
} else {
maxValue = Math.max.apply(Math, getSummValues());
}
datasets.filter(function (dataset, index) {
return !hiddenDatasets.includes(index);
}).forEach(function (_ref3) {
var label = _ref3.label,
values = _ref3.values,
color = _ref3.color;
var points = values.map(function (originalValue, valueIndex) {
lastValues[valueIndex] += originalValue;
var value = lineChart ? originalValue : lastValues[valueIndex];
var x = valueIndex / (values.length - 1) * width;
var y = height - value / maxValue * height;
if (lineChart) {
return "" + (valueIndex === 0 ? 'M' : 'L') + x + "," + y;
}
return x + " " + y;
});
if (!lineChart) {
points.push(width + " " + height + " 0 " + height);
}
data.push({
label: label,
points: points.join(' '),
color: color
});
});
return data.reverse();
};
var getVerticalLines = function getVerticalLines() {
var lines = [];
if (!datasets.length) {
return lines;
}
var values = datasets[0].values;
values.forEach(function (value, valueIndex) {
var x = valueIndex / (values.length - 1) * width;
lines.push(x);
});
return lines;
};
var toggleDataset = function toggleDataset(index) {
if (!toggleDatasets) return;
if (hiddenDatasets.includes(index)) {
hiddenDatasets.splice(hiddenDatasets.indexOf(index), 1);
} else {
hiddenDatasets.push(index);
}
setHiddenDatasets([].concat(hiddenDatasets));
};
var formatAxisLabel = function formatAxisLabel(label) {
if (formatAxisLabelProp) return formatAxisLabelProp(label);
return label;
};
var formatLegendLabel = function formatLegendLabel(label) {
if (formatLegendLabelProp) return formatLegendLabelProp(label);
return label;
};
var calcLinesOffsets = function calcLinesOffsets() {
var lines = svgElRef.current.querySelectorAll('line');
linesOffsets.current = [];
for (var i = 0; i < lines.length; i += 1) {
linesOffsets.current.push(lines[i].getBoundingClientRect().left);
}
};
var formatTooltip = function formatTooltip() {
if (currentIndex === null) return '';
var total = 0;
var currentValues = datasets.filter(function (dataset, index) {
return !hiddenDatasets.includes(index);
}).map(function (dataset) {
return {
color: dataset.color,
label: dataset.label,
value: dataset.values[currentIndex]
};
});
currentValues.forEach(function (dataset) {
total += dataset.value;
});
if (formatTooltipProp) {
return formatTooltipProp({
index: currentIndex,
total: total,
datasets: currentValues
});
}
var labelText = formatTooltipAxisLabel ? formatTooltipAxisLabel(axisLabels[currentIndex]) : formatAxisLabel(axisLabels[currentIndex]);
if (!labelText) labelText = '';
var totalText = formatTooltipTotal ? formatTooltipTotal(total) : total; // prettier-ignore
var datasetsText = currentValues.length > 0 ? "\n <ul class=\"area-chart-tooltip-list\">\n " + currentValues.map(function (_ref4) {
var label = _ref4.label,
color = _ref4.color,
value = _ref4.value;
var valueText = formatTooltipDataset ? formatTooltipDataset(label, value, color) : label + ": " + value;
return "\n <li><span style=\"background-color: " + color + ";\"></span>" + valueText + "</li>\n ";
}).join('') + "\n </ul>" : ''; // prettier-ignore
return "\n <div class=\"area-chart-tooltip-label\">" + labelText + "</div>\n <div class=\"area-chart-tooltip-total\">" + totalText + "</div>\n " + datasetsText + "\n ";
};
var setTooltip = function setTooltip() {
if (!tooltip) return;
var hasVisibleDataSets = datasets.filter(function (dataset, index) {
return !hiddenDatasets.includes(index);
}).length > 0;
if (!hasVisibleDataSets) {
if (zmpTooltip.current && zmpTooltip.current.hide) zmpTooltip.current.hide();
return;
}
if (currentIndex !== null && !zmpTooltip.current) {
zmpTooltip.current = _zmp.zmp.tooltip.create({
trigger: 'manual',
containerEl: elRef.current,
targetEl: svgElRef.current.querySelector("line[data-index=\"" + currentIndex + "\"]"),
text: formatTooltip(),
cssClass: 'area-chart-tooltip'
});
if (zmpTooltip.current && zmpTooltip.current.show) {
zmpTooltip.current.show();
}
return;
}
if (!zmpTooltip.current || !zmpTooltip.current.hide || !zmpTooltip.current.show) {
return;
}
if (currentIndex !== null) {
zmpTooltip.current.setText(formatTooltip());
zmpTooltip.current.setTargetEl(svgElRef.current.querySelector("line[data-index=\"" + currentIndex + "\"]"));
zmpTooltip.current.show();
} else {
zmpTooltip.current.hide();
}
};
var onMouseEnter = function onMouseEnter() {
calcLinesOffsets();
};
var onMouseMove = function onMouseMove(e) {
if (!linesOffsets.current) {
calcLinesOffsets();
}
var currentLeft = e.pageX;
if (typeof currentLeft === 'undefined') currentLeft = 0;
var distances = linesOffsets.current.map(function (left) {
return Math.abs(currentLeft - left);
});
var minDistance = Math.min.apply(Math, distances);
var closestIndex = distances.indexOf(minDistance);
setCurrentIndex(closestIndex);
};
var onMouseLeave = function onMouseLeave() {
setCurrentIndex(null);
};
var attachEvents = function attachEvents() {
if (!svgElRef.current) return;
svgElRef.current.addEventListener('mouseenter', onMouseEnter);
svgElRef.current.addEventListener('mousemove', onMouseMove);
svgElRef.current.addEventListener('mouseleave', onMouseLeave);
};
var detachEvents = function detachEvents() {
if (!svgElRef.current) return;
svgElRef.current.removeEventListener('mouseenter', onMouseEnter);
svgElRef.current.removeEventListener('mousemove', onMouseMove);
svgElRef.current.removeEventListener('mouseleave', onMouseLeave);
};
(0, _react.useEffect)(function () {
if (previousIndex.current === currentIndex) return;
previousIndex.current = currentIndex;
(0, _utils.emit)(props, 'select', currentIndex);
setTooltip();
}, [currentIndex]);
(0, _react.useEffect)(function () {
attachEvents();
return detachEvents;
});
(0, _react.useEffect)(function () {
return function () {
if (zmpTooltip.current && zmpTooltip.current.destroy) {
zmpTooltip.current.destroy();
}
zmpTooltip.current = null;
};
}, []);
var classes = (0, _utils.classNames)('area-chart', className);
var chartData = getChartData();
var verticalLines = getVerticalLines();
var visibleLegends = getVisibleLegends();
var LegendItemTag = toggleDatasets ? 'button' : 'span';
var ChartTag = lineChart ? 'path' : 'polygon';
return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({
id: id,
style: style,
className: classes,
ref: elRef
}, extraAttrs), /*#__PURE__*/_react.default.createElement("svg", {
xmlns: "http://www.w3.org/2000/svg",
width: width,
height: height,
viewBox: "0 0 " + width + " " + height,
preserveAspectRatio: "none",
ref: svgElRef
}, chartData.map(function (data, index) {
return /*#__PURE__*/_react.default.createElement(ChartTag, {
key: ChartTag + "-" + index,
fill: lineChart ? undefined : data.color,
stroke: lineChart ? data.color : undefined,
fillRule: "evenodd",
points: lineChart ? undefined : data.points,
d: lineChart ? data.points : undefined
});
}), verticalLines.map(function (line, index) {
return /*#__PURE__*/_react.default.createElement("line", {
key: "line-" + index,
"data-index": index,
fill: "#000",
x1: line,
y1: 0,
x2: line,
y2: height,
className: (0, _utils.classNames)({
'area-chart-current-line': currentIndex === index
})
});
})), axis && /*#__PURE__*/_react.default.createElement("div", {
className: "area-chart-axis"
}, axisLabels.map(function (label, index) {
return /*#__PURE__*/_react.default.createElement("span", {
key: index
}, visibleLegends.includes(label) && /*#__PURE__*/_react.default.createElement("span", null, formatAxisLabel(label)));
})), legend && /*#__PURE__*/_react.default.createElement("div", {
className: "area-chart-legend"
}, datasets.map(function (dataset, index) {
return /*#__PURE__*/_react.default.createElement(LegendItemTag, {
key: index,
className: (0, _utils.classNames)('area-chart-legend-item', {
'area-chart-legend-item-hidden': hiddenDatasets.includes(index),
'area-chart-legend-button': toggleDatasets
}),
type: toggleDatasets ? 'button' : undefined,
onClick: function onClick() {
return toggleDataset(index);
}
}, /*#__PURE__*/_react.default.createElement("span", {
style: {
backgroundColor: dataset.color
}
}), formatLegendLabel(dataset.label));
})), children);
});
AreaChart.displayName = 'zmp-area-chart';
var _default = AreaChart;
exports.default = _default;