UNPKG

@semcore/chart

Version:
434 lines (432 loc) 19.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); 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 _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _core = require("@semcore/core"); var _react = _interopRequireDefault(require("react")); var _recharts = require("recharts"); var _ReactUtils = require("recharts/lib/util/ReactUtils"); var _venn = require("@upsetjs/venn.js"); var _Tooltip = require("../../Tooltip"); var _VennArea = _interopRequireDefault(require("./VennArea")); var _VennIntersection = _interopRequireDefault(require("./VennIntersection")); var _fire = _interopRequireDefault(require("@semcore/utils/lib/fire")); var _assignProps = _interopRequireDefault(require("@semcore/utils/lib/assignProps")); var _classnames = _interopRequireDefault(require("classnames")); var _excluded = ["className", "width", "height", "style"]; /*__reshadow-styles__:"./style/venn-tooltip-label.shadow.css"*/ var styles = ( /*__reshadow_css_start__*/_core.sstyled.insert( /*__inner_css_start__*/".___STooltipLabel_1te07_gg_{display:inline-flex;justify-content:space-between;width:100%;padding-bottom:var(--intergalactic-spacing-2x, 8px);border-bottom:1px solid var(--intergalactic-border-primary, #c4c7cf);color:var(--intergalactic-text-primary, #191b23);font-size:var(--intergalactic-fs-100, 12px);line-height:var(--intergalactic-lh-100, 133%)}.___STooltipLabelTitle_1te07_gg_{margin-right:var(--intergalactic-spacing-4x, 16px)}.___STooltipLabelPercentage_1te07_gg_{margin-right:var(--intergalactic-spacing-3x, 12px);color:var(--intergalactic-text-secondary, #6c6e79)}.___STooltipLabelValue_1te07_gg_{font-weight:var(--intergalactic-bold, Bold)}" /*__inner_css_end__*/, "1te07_gg_") /*__reshadow_css_end__*/, { "__STooltipLabel": "___STooltipLabel_1te07_gg_", "__STooltipLabelTitle": "___STooltipLabelTitle_1te07_gg_", "__STooltipLabelPercentage": "___STooltipLabelPercentage_1te07_gg_", "__STooltipLabelValue": "___STooltipLabelValue_1te07_gg_" }); /*__reshadow-styles__:"../../style/chart.shadow.css"*/ var chartStyles = ( /*__reshadow_css_start__*/_core.sstyled.insert( /*__inner_css_start__*/".___SChart_z2wr8_gg_ .recharts-label{text-anchor:middle;fill:var(--intergalactic-text-hint, #6c6e79)}.___SChart_z2wr8_gg_ .recharts-cartesian-axis-tick-value{fill:var(--intergalactic-chart-grid-text-label, #6c6e79);font-size:12px;line-height:1.1}.___SChart_z2wr8_gg_ .recharts-default-tooltip{padding:12px;margin:0;background-color:var(--intergalactic-bg-primary-neutral, #ffffff);white-space:nowrap;border:1px solid var(--intergalactic-border-secondary, #e0e1e9);box-shadow:var(--intergalactic-box-shadow-popper, 0px 1px 12px 0px rgba(25, 27, 35, 0.15));border-radius:var(--intergalactic-popper-rounded, 6px)}.___SChart_z2wr8_gg_ .recharts-tooltip-item{display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--intergalactic-text-primary, #191b23);padding:4px 0}.___SChart_z2wr8_gg_ .recharts-tooltip-label{font-size:12px;color:var(--intergalactic-text-secondary, #6c6e79);margin-top:0;margin-bottom:var(--intergalactic-spacing-2x, 8px)}.___SChart_z2wr8_gg_ .recharts-tooltip-label:empty{margin-bottom:0}.___SChart_z2wr8_gg_ .recharts-tooltip-item-value-wrapper{margin-left:var(--intergalactic-spacing-3x, 12px)}.___SChart_z2wr8_gg_ .recharts-tooltip-item-value{font-weight:var(--intergalactic-bold, Bold)}.___SChart_z2wr8_gg_ .recharts-tooltip-item-color{display:inline-block;margin-right:var(--intergalactic-spacing-2x, 8px);width:8px;height:8px;border-radius:50%}.___SChart_z2wr8_gg_ .recharts-area-dot{fill-opacity:1}" /*__inner_css_end__*/, "z2wr8_gg_") /*__reshadow_css_end__*/, { "__SChart": "___SChart_z2wr8_gg_" }); /** * @deprecated Please, use package `@semcore/ui/d3-chart` instead. Package `@semcore/chart` is deprecated. */ var VennChart = /*#__PURE__*/function (_React$PureComponent) { (0, _inherits2["default"])(VennChart, _React$PureComponent); var _super = (0, _createSuper2["default"])(VennChart); function VennChart(props) { var _this; (0, _classCallCheck2["default"])(this, VennChart); _this = _super.call(this, props); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "circles", void 0); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "circlesLayout", void 0); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleMouseEnter", function (nodeProps) { return function (e) { var children = _this.state.children; var tooltip = (0, _ReactUtils.findChildByType)(children, _Tooltip.Tooltip); _this.setState({ activeNode: nodeProps, isTooltipActive: !!tooltip }, function () { return (0, _fire["default"])((0, _assertThisInitialized2["default"])(_this), 'onMouseEnter', e, _this.generatePayload()); }); }; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleMouseLeave", function (e) { _this.setState({ activeNode: null, isTooltipActive: false }, function () { (0, _fire["default"])((0, _assertThisInitialized2["default"])(_this), 'onMouseLeave', e, _this.generatePayload()); }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleClick", function (e) { (0, _fire["default"])((0, _assertThisInitialized2["default"])(_this), 'onClick', e, _this.generatePayload()); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "dataToCirclesLayoutObj", function () { var actualData = _this.state.actualData; var _this$props = _this.props, width = _this$props.width, height = _this$props.height, padding = _this$props.padding, orientation = _this$props.orientation, orientationOrder = _this$props.orientationOrder, minAreaRadius = _this$props.minAreaRadius; if (actualData.length === 0) { _this.circles = {}; return null; } var circles = (0, _venn.venn)(actualData); var normalisedCircles = (0, _venn.normalizeSolution)(circles, orientation, orientationOrder); var scaledCircles = (0, _venn.scaleSolution)(normalisedCircles, width, height, padding); Object.keys(scaledCircles).forEach(function (key) { var circleRadius = scaledCircles[key].radius; scaledCircles[key].radius = Math.max(minAreaRadius, circleRadius); //@ts-ignore scaledCircles[key].data = getElementDataByKey(actualData, key); }); //@ts-ignore _this.circles = scaledCircles; }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "renderCircle", function (circleProps) { var activeNode = _this.state.activeNode; var x = circleProps.x, y = circleProps.y, radius = circleProps.radius, data = circleProps.data, name = circleProps.name, node = circleProps.node; var isNodeActive = activeNode && name === activeNode.name; var nodeProps = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, node.props), {}, { cx: x, cy: y, r: radius, key: "venn-area-".concat(name), size: data.size, active: isNodeActive, data: data }); var nodeHandlers = { onMouseEnter: _this.handleMouseEnter(nodeProps), onMouseLeave: _this.handleMouseLeave, onClick: _this.handleClick }; return /*#__PURE__*/_react["default"].cloneElement(node, (0, _assignProps["default"])(nodeProps, nodeHandlers)); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "renderIntersection", function (intersectionProps) { var sets = intersectionProps.sets; var activeNode = _this.state.activeNode; var isNodeActive = (activeNode === null || activeNode === void 0 ? void 0 : activeNode.sets) && stringArrayIsEqual(sets, activeNode.sets); var nodeHandlers = { onMouseEnter: _this.handleMouseEnter(intersectionProps), onMouseLeave: _this.handleMouseLeave, onClick: _this.handleClick }; var nodeProps = (0, _objectSpread2["default"])({ active: isNodeActive, key: "venn-intersection-".concat(sets.join('-')) }, (0, _assignProps["default"])(intersectionProps, nodeHandlers)); return /*#__PURE__*/_react["default"].createElement(_VennIntersection["default"], nodeProps); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "formatTooltipLabel", function (label, payload) { var _ref; var tooltipLabelIntersectionSizeFormatter = _this.props.tooltipLabelIntersectionSizeFormatter; if (!payload || payload.length < 2) { return null; } var totalValue = payload.reduce(function (acc, item) { return acc + item.payload.size; }, 0); var sets = payload.reduce(function (acc, item) { return acc.concat(item.payload.sets); }, []); var _payload$0$data$find = payload[0].data.find(function (dataItem) { return sets.every(function (set) { return dataItem.sets.includes(set); }); }), size = _payload$0$data$find.size; var percent = size / (totalValue / 100); var finalPercentage = percent < 1 ? '< 1' : percent.toFixed(0); var STooltipLabel = 'span'; var STooltipLabelTitle = 'span'; var STooltipLabelPercentage = 'span'; var STooltipLabelValue = 'span'; return _ref = (0, _core.sstyled)(styles), /*#__PURE__*/_react["default"].createElement(STooltipLabel, _ref.cn("STooltipLabel", {}), /*#__PURE__*/_react["default"].createElement(STooltipLabelTitle, _ref.cn("STooltipLabelTitle", {}), label), /*#__PURE__*/_react["default"].createElement(STooltipLabelPercentage, _ref.cn("STooltipLabelPercentage", {}), finalPercentage, "%"), /*#__PURE__*/_react["default"].createElement(STooltipLabelValue, _ref.cn("STooltipLabelValue", {}), tooltipLabelIntersectionSizeFormatter(size))); }); var _data = props.data, _children = props.children; _this.state = { data: _data, children: _children, actualData: VennChart.getActualData(props), activeNode: null, isTooltipActive: false }; return _this; } (0, _createClass2["default"])(VennChart, [{ key: "getCirclesLayout", value: function getCirclesLayout() { var children = this.state.children; // tslint:disable-next-line:no-this-assignment var circles = this.circles; var circleItems = (0, _ReactUtils.findAllByType)(children, _VennArea["default"]); this.circlesLayout = Object.keys(circles).map(function (circle) { var circleName = circles[circle].data.name; var circleNode = circleItems.find(function (_ref3) { var props = _ref3.props; return circleName === props.name; }); return (0, _objectSpread2["default"])({ name: circleName, node: circleNode }, circles[circle]); }); } }, { key: "renderCircles", value: function renderCircles() { return this.circlesLayout.map(this.renderCircle); } }, { key: "getIntersectionsLayout", value: function getIntersectionsLayout() { var _this2 = this; var actualData = this.state.actualData; var circlesWithIntersections = actualData.filter(function (item) { return item.sets.length > 1; }); return circlesWithIntersections.map(function (intersection) { var sets = intersection.sets, name = intersection.name, size = intersection.size; var circleNodes = sets.map(function (set) { return _this2.circlesLayout.find(function (circle) { return circle.data.sets[0] === set; }); }); var path = (0, _venn.intersectionAreaPath)(circleNodes); return { d: path, circles: circleNodes, name: name, size: size, sets: sets }; }); } }, { key: "renderIntersections", value: function renderIntersections() { var intersections = this.getIntersectionsLayout(); return intersections.map(this.renderIntersection); } }, { key: "getAreaTooltipCoordinate", value: function getAreaTooltipCoordinate(activeNode) { if (!activeNode || !activeNode.cx || !activeNode.cy) { return null; } return { x: activeNode.cx + activeNode.r, y: activeNode.cy + activeNode.r / 2 }; } }, { key: "getIntersectionTooltipCoordinate", value: function getIntersectionTooltipCoordinate(activeNode) { if (!activeNode || !activeNode.circles) { return null; } var stats = {}; (0, _venn.intersectionArea)(activeNode.circles, stats); // @ts-ignore var innerPoints = stats.innerPoints; return innerPoints.reduce(function (acc, _ref4) { var x = _ref4.x, y = _ref4.y; if (x > acc.x) { acc.x = x; } if (y > acc.y) { acc.y = y; } return acc; }, { x: 0, y: 0 }); } }, { key: "generatePayload", value: function generatePayload() { var data = this.props.data; var activeNode = this.state.activeNode; if (!activeNode) { return []; } return activeNode.name ? [{ payload: activeNode.data, name: activeNode.name, value: activeNode.size, fill: activeNode.fill, data: data }] : activeNode.circles.map(function (circle) { return { payload: circle.data, // @ts-ignore name: circle.name, value: circle.data.size, // @ts-ignore fill: circle.node.props.fill, data: data }; }); } }, { key: "renderTooltip", value: function renderTooltip() { var children = this.props.children; var tooltipItem = (0, _ReactUtils.findChildByType)(children, _Tooltip.Tooltip); if (!tooltipItem) { return null; } var _this$props2 = this.props, width = _this$props2.width, height = _this$props2.height; var _this$state = this.state, isTooltipActive = _this$state.isTooltipActive, activeNode = _this$state.activeNode; var viewBox = { x: 0, y: 0, width: width, height: height }; var coordinate = this.getAreaTooltipCoordinate(activeNode) || this.getIntersectionTooltipCoordinate(activeNode); var payload = isTooltipActive ? this.generatePayload() : []; return /*#__PURE__*/_react["default"].cloneElement(tooltipItem, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({ label: 'Overlap', labelFormatter: this.formatTooltipLabel }, tooltipItem.props), {}, { viewBox: viewBox, active: isTooltipActive, coordinate: coordinate, payload: payload })); } }, { key: "render", value: function render() { var _ref2; if (!(0, _ReactUtils.validateWidthHeight)(this)) { return null; } this.dataToCirclesLayoutObj(); // elegant crutch 🤷‍ this.getCirclesLayout(); var _this$props3 = this.props, className = _this$props3.className, width = _this$props3.width, height = _this$props3.height, style = _this$props3.style, other = (0, _objectWithoutProperties2["default"])(_this$props3, _excluded); var attrs = (0, _ReactUtils.getPresentationAttributes)(other); var SChart = 'div'; return _ref2 = (0, _core.sstyled)(chartStyles), /*#__PURE__*/_react["default"].createElement(SChart, _ref2.cn("SChart", { "className": (0, _classnames["default"])('recharts-wrapper', className), "style": (0, _objectSpread2["default"])({ position: 'relative', cursor: 'default', width: width, height: height }, style) }), /*#__PURE__*/_react["default"].createElement(_recharts.Surface, _ref2.cn("Surface", (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, attrs), {}, { "width": width, "height": height })), this.renderCircles(), this.renderIntersections()), this.renderTooltip()); } }], [{ key: "getActualData", value: function getActualData(props) { var data = props.data, children = props.children; var circleItems = (0, _ReactUtils.findAllByType)(children, _VennArea["default"]); // Mapping data to children to define actual sets var actualSets = circleItems.reduce(function (acc, circle) { if (circle.props.hidden) { return acc; } var name = circle.props.name; var circleDataItem = data.find(function (item) { return item.name === name; }); if (!circleDataItem || circleDataItem.sets.length > 1) { return acc; } return [].concat((0, _toConsumableArray2["default"])(acc), (0, _toConsumableArray2["default"])(circleDataItem.sets)); }, []); // filtering data by actual sets return data.filter(function (item) { return item.sets.every(function (set) { return actualSets.includes(set); }); }); } }, { key: "getDerivedStateFromProps", value: function getDerivedStateFromProps(props, state) { var children = props.children, data = props.data; var activeNode = state.activeNode, isTooltipActive = state.isTooltipActive; if (data !== state.data || !(0, _ReactUtils.isChildrenEqual)(children, state.children)) { var actualData = VennChart.getActualData(props); return { data: data, children: children, actualData: actualData, activeNode: activeNode, isTooltipActive: isTooltipActive }; } return null; } }]); return VennChart; }(_react["default"].PureComponent); exports["default"] = VennChart; (0, _defineProperty2["default"])(VennChart, "displayName", 'VennChart'); (0, _defineProperty2["default"])(VennChart, "defaultProps", { padding: 2, orientation: Math.PI / 2, orientationOrder: function orientationOrder(c1, c2) { return c2.radius - c1.radius; }, minAreaRadius: 6, tooltipLabelIntersectionSizeFormatter: function tooltipLabelIntersectionSizeFormatter(v) { return v; } }); function stringArrayIsEqual(arr1, arr2) { if (arr1.length !== arr2.length) { return false; } return arr1.every(function (item) { return arr2.includes(item); }); } function getElementDataByKey(data, key) { return data.find(function (el) { return el.sets.length === 1 && el.sets[0] === key; }); } //# sourceMappingURL=VennChart.js.map