| [a762898] | 1 | var _excluded = ["width", "height", "className", "style", "children", "type"];
|
|---|
| 2 | function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|---|
| 3 | function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|---|
| 4 | function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|---|
| 5 | 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; }
|
|---|
| 6 | 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) { _defineProperty(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; }
|
|---|
| 7 | function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|---|
| 8 | function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|---|
| 9 | function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|---|
| 10 | import * as React from 'react';
|
|---|
| 11 | import { PureComponent, useCallback, useState } from 'react';
|
|---|
| 12 | import omit from 'es-toolkit/compat/omit';
|
|---|
| 13 | import get from 'es-toolkit/compat/get';
|
|---|
| 14 | import { Layer } from '../container/Layer';
|
|---|
| 15 | import { Surface } from '../container/Surface';
|
|---|
| 16 | import { Polygon } from '../shape/Polygon';
|
|---|
| 17 | import { Rectangle } from '../shape/Rectangle';
|
|---|
| 18 | import { getValueByDataKey } from '../util/ChartUtils';
|
|---|
| 19 | import { COLOR_PANEL } from '../util/Constants';
|
|---|
| 20 | import { isNan, noop, uniqueId } from '../util/DataUtils';
|
|---|
| 21 | import { getStringSize } from '../util/DOMUtils';
|
|---|
| 22 | import { ReportChartMargin, useChartHeight, useChartWidth } from '../context/chartLayoutContext';
|
|---|
| 23 | import { TooltipPortalContext } from '../context/tooltipPortalContext';
|
|---|
| 24 | import { RechartsWrapper } from './RechartsWrapper';
|
|---|
| 25 | import { setActiveClickItemIndex, setActiveMouseOverItemIndex } from '../state/tooltipSlice';
|
|---|
| 26 | import { SetTooltipEntrySettings } from '../state/SetTooltipEntrySettings';
|
|---|
| 27 | import { RechartsStoreProvider } from '../state/RechartsStoreProvider';
|
|---|
| 28 | import { useAppDispatch } from '../state/hooks';
|
|---|
| 29 | import { isPositiveNumber } from '../util/isWellBehavedNumber';
|
|---|
| 30 | import { svgPropertiesNoEvents } from '../util/svgPropertiesNoEvents';
|
|---|
| 31 | import { CSSTransitionAnimate } from '../animation/CSSTransitionAnimate';
|
|---|
| 32 | import { resolveDefaultProps } from '../util/resolveDefaultProps';
|
|---|
| 33 | import { RegisterGraphicalItemId } from '../context/RegisterGraphicalItemId';
|
|---|
| 34 | var NODE_VALUE_KEY = 'value';
|
|---|
| 35 |
|
|---|
| 36 | /**
|
|---|
| 37 | * This is what end users defines as `data` on Treemap.
|
|---|
| 38 | */
|
|---|
| 39 |
|
|---|
| 40 | /**
|
|---|
| 41 | * This is what is returned from `squarify`, the final treemap data structure
|
|---|
| 42 | * that gets rendered and is stored in
|
|---|
| 43 | */
|
|---|
| 44 |
|
|---|
| 45 | function isTreemapNode(value) {
|
|---|
| 46 | return value != null && typeof value === 'object' && 'x' in value && 'y' in value && 'width' in value && 'height' in value && typeof value.x === 'number' && typeof value.y === 'number' && typeof value.width === 'number' && typeof value.height === 'number';
|
|---|
| 47 | }
|
|---|
| 48 | export var treemapPayloadSearcher = (data, activeIndex) => {
|
|---|
| 49 | if (!data || !activeIndex) {
|
|---|
| 50 | return undefined;
|
|---|
| 51 | }
|
|---|
| 52 | return get(data, activeIndex);
|
|---|
| 53 | };
|
|---|
| 54 | export var addToTreemapNodeIndex = function addToTreemapNodeIndex(indexInChildrenArr) {
|
|---|
| 55 | var activeTooltipIndexSoFar = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
|---|
| 56 | return "".concat(activeTooltipIndexSoFar, "children[").concat(indexInChildrenArr, "]");
|
|---|
| 57 | };
|
|---|
| 58 | var options = {
|
|---|
| 59 | chartName: 'Treemap',
|
|---|
| 60 | defaultTooltipEventType: 'item',
|
|---|
| 61 | validateTooltipEventTypes: ['item'],
|
|---|
| 62 | tooltipPayloadSearcher: treemapPayloadSearcher,
|
|---|
| 63 | eventEmitter: undefined
|
|---|
| 64 | };
|
|---|
| 65 | export var computeNode = _ref => {
|
|---|
| 66 | var {
|
|---|
| 67 | depth,
|
|---|
| 68 | node,
|
|---|
| 69 | index,
|
|---|
| 70 | dataKey,
|
|---|
| 71 | nameKey,
|
|---|
| 72 | nestedActiveTooltipIndex
|
|---|
| 73 | } = _ref;
|
|---|
| 74 | var currentTooltipIndex = depth === 0 ? '' : addToTreemapNodeIndex(index, nestedActiveTooltipIndex);
|
|---|
| 75 | var {
|
|---|
| 76 | children
|
|---|
| 77 | } = node;
|
|---|
| 78 | var childDepth = depth + 1;
|
|---|
| 79 | var computedChildren = children && children.length ? children.map((child, i) => computeNode({
|
|---|
| 80 | depth: childDepth,
|
|---|
| 81 | node: child,
|
|---|
| 82 | index: i,
|
|---|
| 83 | dataKey,
|
|---|
| 84 | nameKey,
|
|---|
| 85 | nestedActiveTooltipIndex: currentTooltipIndex
|
|---|
| 86 | })) : null;
|
|---|
| 87 | var nodeValue;
|
|---|
| 88 | if (computedChildren && computedChildren.length) {
|
|---|
| 89 | nodeValue = computedChildren.reduce((result, child) => result + child.value, 0);
|
|---|
| 90 | } else {
|
|---|
| 91 | // TODO need to verify dataKey
|
|---|
| 92 | var rawNodeValue = node[dataKey];
|
|---|
| 93 | var numericValue = typeof rawNodeValue === 'number' ? rawNodeValue : 0;
|
|---|
| 94 | nodeValue = isNan(numericValue) || numericValue <= 0 ? 0 : numericValue;
|
|---|
| 95 | }
|
|---|
| 96 | return _objectSpread(_objectSpread({}, node), {}, {
|
|---|
| 97 | children: computedChildren,
|
|---|
| 98 | // @ts-expect-error getValueByDataKey does not validate the output type
|
|---|
| 99 | name: getValueByDataKey(node, nameKey, ''),
|
|---|
| 100 | [NODE_VALUE_KEY]: nodeValue,
|
|---|
| 101 | depth,
|
|---|
| 102 | index,
|
|---|
| 103 | tooltipIndex: currentTooltipIndex
|
|---|
| 104 | });
|
|---|
| 105 | };
|
|---|
| 106 | var filterRect = node => ({
|
|---|
| 107 | x: node.x,
|
|---|
| 108 | y: node.y,
|
|---|
| 109 | width: node.width,
|
|---|
| 110 | height: node.height
|
|---|
| 111 | });
|
|---|
| 112 | // Compute the area for each child based on value & scale.
|
|---|
| 113 | var getAreaOfChildren = (children, areaValueRatio) => {
|
|---|
| 114 | var ratio = areaValueRatio < 0 ? 0 : areaValueRatio;
|
|---|
| 115 | return children.map(child => {
|
|---|
| 116 | var area = child[NODE_VALUE_KEY] * ratio;
|
|---|
| 117 | return _objectSpread(_objectSpread({}, child), {}, {
|
|---|
| 118 | area: isNan(area) || area <= 0 ? 0 : area
|
|---|
| 119 | });
|
|---|
| 120 | });
|
|---|
| 121 | };
|
|---|
| 122 |
|
|---|
| 123 | // Computes the score for the specified row, as the worst aspect ratio.
|
|---|
| 124 | var getWorstScore = (row, parentSize, aspectRatio) => {
|
|---|
| 125 | var parentArea = parentSize * parentSize;
|
|---|
| 126 | var rowArea = row.area * row.area;
|
|---|
| 127 | var {
|
|---|
| 128 | min,
|
|---|
| 129 | max
|
|---|
| 130 | } = row.reduce((result, child) => ({
|
|---|
| 131 | min: Math.min(result.min, child.area),
|
|---|
| 132 | max: Math.max(result.max, child.area)
|
|---|
| 133 | }), {
|
|---|
| 134 | min: Infinity,
|
|---|
| 135 | max: 0
|
|---|
| 136 | });
|
|---|
| 137 | return rowArea ? Math.max(parentArea * max * aspectRatio / rowArea, rowArea / (parentArea * min * aspectRatio)) : Infinity;
|
|---|
| 138 | };
|
|---|
| 139 | var horizontalPosition = (row, parentSize, parentRect, isFlush) => {
|
|---|
| 140 | var rowHeight = parentSize ? Math.round(row.area / parentSize) : 0;
|
|---|
| 141 | if (isFlush || rowHeight > parentRect.height) {
|
|---|
| 142 | rowHeight = parentRect.height;
|
|---|
| 143 | }
|
|---|
| 144 | var curX = parentRect.x;
|
|---|
| 145 | var child;
|
|---|
| 146 | for (var i = 0, len = row.length; i < len; i++) {
|
|---|
| 147 | child = row[i];
|
|---|
| 148 | if (child == null) {
|
|---|
| 149 | continue;
|
|---|
| 150 | }
|
|---|
| 151 | child.x = curX;
|
|---|
| 152 | child.y = parentRect.y;
|
|---|
| 153 | child.height = rowHeight;
|
|---|
| 154 | child.width = Math.min(rowHeight ? Math.round(child.area / rowHeight) : 0, parentRect.x + parentRect.width - curX);
|
|---|
| 155 | curX += child.width;
|
|---|
| 156 | }
|
|---|
| 157 | // add the remain x to the last one of row
|
|---|
| 158 | if (child != null) {
|
|---|
| 159 | child.width += parentRect.x + parentRect.width - curX;
|
|---|
| 160 | }
|
|---|
| 161 | return _objectSpread(_objectSpread({}, parentRect), {}, {
|
|---|
| 162 | y: parentRect.y + rowHeight,
|
|---|
| 163 | height: parentRect.height - rowHeight
|
|---|
| 164 | });
|
|---|
| 165 | };
|
|---|
| 166 | var verticalPosition = (row, parentSize, parentRect, isFlush) => {
|
|---|
| 167 | var rowWidth = parentSize ? Math.round(row.area / parentSize) : 0;
|
|---|
| 168 | if (isFlush || rowWidth > parentRect.width) {
|
|---|
| 169 | rowWidth = parentRect.width;
|
|---|
| 170 | }
|
|---|
| 171 | var curY = parentRect.y;
|
|---|
| 172 | var child;
|
|---|
| 173 | for (var i = 0, len = row.length; i < len; i++) {
|
|---|
| 174 | child = row[i];
|
|---|
| 175 | if (child == null) {
|
|---|
| 176 | continue;
|
|---|
| 177 | }
|
|---|
| 178 | child.x = parentRect.x;
|
|---|
| 179 | child.y = curY;
|
|---|
| 180 | child.width = rowWidth;
|
|---|
| 181 | child.height = Math.min(rowWidth ? Math.round(child.area / rowWidth) : 0, parentRect.y + parentRect.height - curY);
|
|---|
| 182 | curY += child.height;
|
|---|
| 183 | }
|
|---|
| 184 | if (child) {
|
|---|
| 185 | child.height += parentRect.y + parentRect.height - curY;
|
|---|
| 186 | }
|
|---|
| 187 | return _objectSpread(_objectSpread({}, parentRect), {}, {
|
|---|
| 188 | x: parentRect.x + rowWidth,
|
|---|
| 189 | width: parentRect.width - rowWidth
|
|---|
| 190 | });
|
|---|
| 191 | };
|
|---|
| 192 | var position = (row, parentSize, parentRect, isFlush) => {
|
|---|
| 193 | if (parentSize === parentRect.width) {
|
|---|
| 194 | return horizontalPosition(row, parentSize, parentRect, isFlush);
|
|---|
| 195 | }
|
|---|
| 196 | return verticalPosition(row, parentSize, parentRect, isFlush);
|
|---|
| 197 | };
|
|---|
| 198 | // Recursively arranges the specified node's children into squarified rows.
|
|---|
| 199 | var squarify = (node, aspectRatio) => {
|
|---|
| 200 | var {
|
|---|
| 201 | children
|
|---|
| 202 | } = node;
|
|---|
| 203 | if (children && children.length) {
|
|---|
| 204 | var rect = filterRect(node);
|
|---|
| 205 | // @ts-expect-error we can't create an array with static property on a single line so typescript will complain.
|
|---|
| 206 | var row = [];
|
|---|
| 207 | var best = Infinity; // the best row score so far
|
|---|
| 208 | var child, score; // the current row score
|
|---|
| 209 | var size = Math.min(rect.width, rect.height); // initial orientation
|
|---|
| 210 | var scaleChildren = getAreaOfChildren(children, rect.width * rect.height / node[NODE_VALUE_KEY]);
|
|---|
| 211 | var tempChildren = scaleChildren.slice();
|
|---|
| 212 |
|
|---|
| 213 | // why are we setting static properties on an array?
|
|---|
| 214 | row.area = 0;
|
|---|
| 215 | while (tempChildren.length > 0) {
|
|---|
| 216 | [child] = tempChildren;
|
|---|
| 217 | if (child == null) {
|
|---|
| 218 | continue;
|
|---|
| 219 | }
|
|---|
| 220 | // row first
|
|---|
| 221 | row.push(child);
|
|---|
| 222 | row.area += child.area;
|
|---|
| 223 | score = getWorstScore(row, size, aspectRatio);
|
|---|
| 224 | if (score <= best) {
|
|---|
| 225 | // continue with this orientation
|
|---|
| 226 | tempChildren.shift();
|
|---|
| 227 | best = score;
|
|---|
| 228 | } else {
|
|---|
| 229 | var _row$pop$area, _row$pop;
|
|---|
| 230 | // abort, and try a different orientation
|
|---|
| 231 | row.area -= (_row$pop$area = (_row$pop = row.pop()) === null || _row$pop === void 0 ? void 0 : _row$pop.area) !== null && _row$pop$area !== void 0 ? _row$pop$area : 0;
|
|---|
| 232 | rect = position(row, size, rect, false);
|
|---|
| 233 | size = Math.min(rect.width, rect.height);
|
|---|
| 234 | row.length = row.area = 0;
|
|---|
| 235 | best = Infinity;
|
|---|
| 236 | }
|
|---|
| 237 | }
|
|---|
| 238 | if (row.length) {
|
|---|
| 239 | rect = position(row, size, rect, true);
|
|---|
| 240 | row.length = row.area = 0;
|
|---|
| 241 | }
|
|---|
| 242 | return _objectSpread(_objectSpread({}, node), {}, {
|
|---|
| 243 | children: scaleChildren.map(c => squarify(c, aspectRatio))
|
|---|
| 244 | });
|
|---|
| 245 | }
|
|---|
| 246 | return node;
|
|---|
| 247 | };
|
|---|
| 248 | export var defaultTreeMapProps = {
|
|---|
| 249 | aspectRatio: 0.5 * (1 + Math.sqrt(5)),
|
|---|
| 250 | dataKey: 'value',
|
|---|
| 251 | nameKey: 'name',
|
|---|
| 252 | type: 'flat',
|
|---|
| 253 | isAnimationActive: 'auto',
|
|---|
| 254 | isUpdateAnimationActive: 'auto',
|
|---|
| 255 | animationBegin: 0,
|
|---|
| 256 | animationDuration: 1500,
|
|---|
| 257 | animationEasing: 'linear'
|
|---|
| 258 | };
|
|---|
| 259 | var defaultState = {
|
|---|
| 260 | isAnimationFinished: false,
|
|---|
| 261 | formatRoot: null,
|
|---|
| 262 | currentRoot: undefined,
|
|---|
| 263 | nestIndex: [],
|
|---|
| 264 | prevAspectRatio: defaultTreeMapProps.aspectRatio,
|
|---|
| 265 | prevDataKey: defaultTreeMapProps.dataKey
|
|---|
| 266 | };
|
|---|
| 267 | function ContentItem(_ref2) {
|
|---|
| 268 | var {
|
|---|
| 269 | content,
|
|---|
| 270 | nodeProps,
|
|---|
| 271 | type,
|
|---|
| 272 | colorPanel,
|
|---|
| 273 | onMouseEnter,
|
|---|
| 274 | onMouseLeave,
|
|---|
| 275 | onClick
|
|---|
| 276 | } = _ref2;
|
|---|
| 277 | if (/*#__PURE__*/React.isValidElement(content)) {
|
|---|
| 278 | return /*#__PURE__*/React.createElement(Layer, {
|
|---|
| 279 | onMouseEnter: onMouseEnter,
|
|---|
| 280 | onMouseLeave: onMouseLeave,
|
|---|
| 281 | onClick: onClick
|
|---|
| 282 | }, /*#__PURE__*/React.cloneElement(content, nodeProps));
|
|---|
| 283 | }
|
|---|
| 284 | if (typeof content === 'function') {
|
|---|
| 285 | return /*#__PURE__*/React.createElement(Layer, {
|
|---|
| 286 | onMouseEnter: onMouseEnter,
|
|---|
| 287 | onMouseLeave: onMouseLeave,
|
|---|
| 288 | onClick: onClick
|
|---|
| 289 | }, content(nodeProps));
|
|---|
| 290 | }
|
|---|
| 291 | // optimize default shape
|
|---|
| 292 | var {
|
|---|
| 293 | x,
|
|---|
| 294 | y,
|
|---|
| 295 | width,
|
|---|
| 296 | height,
|
|---|
| 297 | index
|
|---|
| 298 | } = nodeProps;
|
|---|
| 299 | var arrow = null;
|
|---|
| 300 | if (width > 10 && height > 10 && nodeProps.children && type === 'nest') {
|
|---|
| 301 | arrow = /*#__PURE__*/React.createElement(Polygon, {
|
|---|
| 302 | points: [{
|
|---|
| 303 | x: x + 2,
|
|---|
| 304 | y: y + height / 2
|
|---|
| 305 | }, {
|
|---|
| 306 | x: x + 6,
|
|---|
| 307 | y: y + height / 2 + 3
|
|---|
| 308 | }, {
|
|---|
| 309 | x: x + 2,
|
|---|
| 310 | y: y + height / 2 + 6
|
|---|
| 311 | }]
|
|---|
| 312 | });
|
|---|
| 313 | }
|
|---|
| 314 | var text = null;
|
|---|
| 315 | var nameSize = getStringSize(nodeProps.name);
|
|---|
| 316 | if (width > 20 && height > 20 && nameSize.width < width && nameSize.height < height) {
|
|---|
| 317 | text = /*#__PURE__*/React.createElement("text", {
|
|---|
| 318 | x: x + 8,
|
|---|
| 319 | y: y + height / 2 + 7,
|
|---|
| 320 | fontSize: 14
|
|---|
| 321 | }, nodeProps.name);
|
|---|
| 322 | }
|
|---|
| 323 | var colors = colorPanel || COLOR_PANEL;
|
|---|
| 324 | return /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement(Rectangle, _extends({
|
|---|
| 325 | fill: nodeProps.depth < 2 ? colors[index % colors.length] : 'rgba(255,255,255,0)',
|
|---|
| 326 | stroke: "#fff"
|
|---|
| 327 | }, omit(nodeProps, ['children']), {
|
|---|
| 328 | onMouseEnter: onMouseEnter,
|
|---|
| 329 | onMouseLeave: onMouseLeave,
|
|---|
| 330 | onClick: onClick,
|
|---|
| 331 | "data-recharts-item-index": nodeProps.tooltipIndex
|
|---|
| 332 | })), arrow, text);
|
|---|
| 333 | }
|
|---|
| 334 | function ContentItemWithEvents(props) {
|
|---|
| 335 | var dispatch = useAppDispatch();
|
|---|
| 336 | var activeCoordinate = {
|
|---|
| 337 | x: props.nodeProps.x + props.nodeProps.width / 2,
|
|---|
| 338 | y: props.nodeProps.y + props.nodeProps.height / 2
|
|---|
| 339 | };
|
|---|
| 340 | var onMouseEnter = () => {
|
|---|
| 341 | dispatch(setActiveMouseOverItemIndex({
|
|---|
| 342 | activeIndex: props.nodeProps.tooltipIndex,
|
|---|
| 343 | activeDataKey: props.dataKey,
|
|---|
| 344 | activeCoordinate,
|
|---|
| 345 | activeGraphicalItemId: props.id
|
|---|
| 346 | }));
|
|---|
| 347 | };
|
|---|
| 348 | var onMouseLeave = () => {
|
|---|
| 349 | // clearing state on mouseLeaveItem causes re-rendering issues
|
|---|
| 350 | // we don't actually want to do this for TreeMap - we clear state when we leave the entire chart instead
|
|---|
| 351 | };
|
|---|
| 352 | var onClick = () => {
|
|---|
| 353 | dispatch(setActiveClickItemIndex({
|
|---|
| 354 | activeIndex: props.nodeProps.tooltipIndex,
|
|---|
| 355 | activeDataKey: props.dataKey,
|
|---|
| 356 | activeCoordinate,
|
|---|
| 357 | activeGraphicalItemId: props.id
|
|---|
| 358 | }));
|
|---|
| 359 | };
|
|---|
| 360 | return /*#__PURE__*/React.createElement(ContentItem, _extends({}, props, {
|
|---|
| 361 | onMouseEnter: onMouseEnter,
|
|---|
| 362 | onMouseLeave: onMouseLeave,
|
|---|
| 363 | onClick: onClick
|
|---|
| 364 | }));
|
|---|
| 365 | }
|
|---|
| 366 | var SetTreemapTooltipEntrySettings = /*#__PURE__*/React.memo(_ref3 => {
|
|---|
| 367 | var {
|
|---|
| 368 | dataKey,
|
|---|
| 369 | nameKey,
|
|---|
| 370 | stroke,
|
|---|
| 371 | fill,
|
|---|
| 372 | currentRoot,
|
|---|
| 373 | id
|
|---|
| 374 | } = _ref3;
|
|---|
| 375 | var tooltipEntrySettings = {
|
|---|
| 376 | dataDefinedOnItem: currentRoot,
|
|---|
| 377 | getPosition: noop,
|
|---|
| 378 | // TODO I think Treemap has the capability of computing positions and supporting defaultIndex? Except it doesn't yet
|
|---|
| 379 | settings: {
|
|---|
| 380 | stroke,
|
|---|
| 381 | strokeWidth: undefined,
|
|---|
| 382 | fill,
|
|---|
| 383 | dataKey,
|
|---|
| 384 | nameKey,
|
|---|
| 385 | name: undefined,
|
|---|
| 386 | // Each TreemapNode has its own name
|
|---|
| 387 | hide: false,
|
|---|
| 388 | type: undefined,
|
|---|
| 389 | color: fill,
|
|---|
| 390 | unit: '',
|
|---|
| 391 | graphicalItemId: id
|
|---|
| 392 | }
|
|---|
| 393 | };
|
|---|
| 394 | return /*#__PURE__*/React.createElement(SetTooltipEntrySettings, {
|
|---|
| 395 | tooltipEntrySettings: tooltipEntrySettings
|
|---|
| 396 | });
|
|---|
| 397 | });
|
|---|
| 398 |
|
|---|
| 399 | // Why is margin not a treemap prop? No clue. Probably it should be
|
|---|
| 400 | var defaultTreemapMargin = {
|
|---|
| 401 | top: 0,
|
|---|
| 402 | right: 0,
|
|---|
| 403 | bottom: 0,
|
|---|
| 404 | left: 0
|
|---|
| 405 | };
|
|---|
| 406 | function TreemapItem(_ref4) {
|
|---|
| 407 | var {
|
|---|
| 408 | content,
|
|---|
| 409 | nodeProps,
|
|---|
| 410 | isLeaf,
|
|---|
| 411 | treemapProps,
|
|---|
| 412 | onNestClick
|
|---|
| 413 | } = _ref4;
|
|---|
| 414 | var {
|
|---|
| 415 | id,
|
|---|
| 416 | isAnimationActive,
|
|---|
| 417 | animationBegin,
|
|---|
| 418 | animationDuration,
|
|---|
| 419 | animationEasing,
|
|---|
| 420 | isUpdateAnimationActive,
|
|---|
| 421 | type,
|
|---|
| 422 | colorPanel,
|
|---|
| 423 | dataKey,
|
|---|
| 424 | onAnimationStart,
|
|---|
| 425 | onAnimationEnd,
|
|---|
| 426 | onMouseEnter: onMouseEnterFromProps,
|
|---|
| 427 | onClick: onItemClickFromProps,
|
|---|
| 428 | onMouseLeave: onMouseLeaveFromProps
|
|---|
| 429 | } = treemapProps;
|
|---|
| 430 | var {
|
|---|
| 431 | width,
|
|---|
| 432 | height,
|
|---|
| 433 | x,
|
|---|
| 434 | y
|
|---|
| 435 | } = nodeProps;
|
|---|
| 436 | var translateX = -x - width;
|
|---|
| 437 | var translateY = 0;
|
|---|
| 438 | var onMouseEnter = e => {
|
|---|
| 439 | if ((isLeaf || type === 'nest') && typeof onMouseEnterFromProps === 'function') {
|
|---|
| 440 | onMouseEnterFromProps(nodeProps, e);
|
|---|
| 441 | }
|
|---|
| 442 | };
|
|---|
| 443 | var onMouseLeave = e => {
|
|---|
| 444 | if ((isLeaf || type === 'nest') && typeof onMouseLeaveFromProps === 'function') {
|
|---|
| 445 | onMouseLeaveFromProps(nodeProps, e);
|
|---|
| 446 | }
|
|---|
| 447 | };
|
|---|
| 448 | var onClick = () => {
|
|---|
| 449 | if (type === 'nest') {
|
|---|
| 450 | onNestClick(nodeProps);
|
|---|
| 451 | }
|
|---|
| 452 | if ((isLeaf || type === 'nest') && typeof onItemClickFromProps === 'function') {
|
|---|
| 453 | onItemClickFromProps(nodeProps);
|
|---|
| 454 | }
|
|---|
| 455 | };
|
|---|
| 456 | var handleAnimationEnd = useCallback(() => {
|
|---|
| 457 | if (typeof onAnimationEnd === 'function') {
|
|---|
| 458 | onAnimationEnd();
|
|---|
| 459 | }
|
|---|
| 460 | }, [onAnimationEnd]);
|
|---|
| 461 | var handleAnimationStart = useCallback(() => {
|
|---|
| 462 | if (typeof onAnimationStart === 'function') {
|
|---|
| 463 | onAnimationStart();
|
|---|
| 464 | }
|
|---|
| 465 | }, [onAnimationStart]);
|
|---|
| 466 | return /*#__PURE__*/React.createElement(CSSTransitionAnimate, {
|
|---|
| 467 | animationId: "treemap-".concat(nodeProps.tooltipIndex),
|
|---|
| 468 | from: "translate(".concat(translateX, "px, ").concat(translateY, "px)"),
|
|---|
| 469 | to: "translate(0, 0)",
|
|---|
| 470 | attributeName: "transform",
|
|---|
| 471 | begin: animationBegin,
|
|---|
| 472 | easing: animationEasing,
|
|---|
| 473 | isActive: isAnimationActive,
|
|---|
| 474 | duration: animationDuration,
|
|---|
| 475 | onAnimationStart: handleAnimationStart,
|
|---|
| 476 | onAnimationEnd: handleAnimationEnd
|
|---|
| 477 | }, style => /*#__PURE__*/React.createElement(Layer, {
|
|---|
| 478 | onMouseEnter: onMouseEnter,
|
|---|
| 479 | onMouseLeave: onMouseLeave,
|
|---|
| 480 | onClick: onClick,
|
|---|
| 481 | style: _objectSpread(_objectSpread({}, style), {}, {
|
|---|
| 482 | transformOrigin: "".concat(x, " ").concat(y)
|
|---|
| 483 | })
|
|---|
| 484 | }, /*#__PURE__*/React.createElement(ContentItemWithEvents, {
|
|---|
| 485 | id: id,
|
|---|
| 486 | content: content,
|
|---|
| 487 | dataKey: dataKey,
|
|---|
| 488 | nodeProps: _objectSpread(_objectSpread({}, nodeProps), {}, {
|
|---|
| 489 | isAnimationActive,
|
|---|
| 490 | isUpdateAnimationActive: !isUpdateAnimationActive,
|
|---|
| 491 | width,
|
|---|
| 492 | height,
|
|---|
| 493 | x,
|
|---|
| 494 | y
|
|---|
| 495 | }),
|
|---|
| 496 | type: type,
|
|---|
| 497 | colorPanel: colorPanel
|
|---|
| 498 | })));
|
|---|
| 499 | }
|
|---|
| 500 | class TreemapWithState extends PureComponent {
|
|---|
| 501 | constructor() {
|
|---|
| 502 | super(...arguments);
|
|---|
| 503 | _defineProperty(this, "state", _objectSpread({}, defaultState));
|
|---|
| 504 | _defineProperty(this, "handleClick", node => {
|
|---|
| 505 | var {
|
|---|
| 506 | onClick,
|
|---|
| 507 | type
|
|---|
| 508 | } = this.props;
|
|---|
| 509 | if (type === 'nest' && node.children) {
|
|---|
| 510 | var {
|
|---|
| 511 | width,
|
|---|
| 512 | height,
|
|---|
| 513 | dataKey,
|
|---|
| 514 | nameKey,
|
|---|
| 515 | aspectRatio
|
|---|
| 516 | } = this.props;
|
|---|
| 517 | var root = computeNode({
|
|---|
| 518 | depth: 0,
|
|---|
| 519 | node: _objectSpread(_objectSpread({}, node), {}, {
|
|---|
| 520 | x: 0,
|
|---|
| 521 | y: 0,
|
|---|
| 522 | width,
|
|---|
| 523 | height
|
|---|
| 524 | }),
|
|---|
| 525 | index: 0,
|
|---|
| 526 | dataKey,
|
|---|
| 527 | nameKey,
|
|---|
| 528 | // with Treemap nesting, should this continue nesting the index or start from empty string?
|
|---|
| 529 | nestedActiveTooltipIndex: node.tooltipIndex
|
|---|
| 530 | });
|
|---|
| 531 | var formatRoot = squarify(root, aspectRatio);
|
|---|
| 532 | var {
|
|---|
| 533 | nestIndex
|
|---|
| 534 | } = this.state;
|
|---|
| 535 | nestIndex.push(node);
|
|---|
| 536 | this.setState({
|
|---|
| 537 | formatRoot,
|
|---|
| 538 | currentRoot: root,
|
|---|
| 539 | nestIndex
|
|---|
| 540 | });
|
|---|
| 541 | }
|
|---|
| 542 | if (onClick) {
|
|---|
| 543 | onClick(node);
|
|---|
| 544 | }
|
|---|
| 545 | });
|
|---|
| 546 | _defineProperty(this, "handleTouchMove", e => {
|
|---|
| 547 | var touchEvent = e.touches[0];
|
|---|
| 548 | if (touchEvent == null) {
|
|---|
| 549 | return;
|
|---|
| 550 | }
|
|---|
| 551 | var target = document.elementFromPoint(touchEvent.clientX, touchEvent.clientY);
|
|---|
| 552 | if (!target || !target.getAttribute || this.state.formatRoot == null) {
|
|---|
| 553 | return;
|
|---|
| 554 | }
|
|---|
| 555 | var itemIndex = target.getAttribute('data-recharts-item-index');
|
|---|
| 556 | var activeNode = treemapPayloadSearcher(this.state.formatRoot, itemIndex);
|
|---|
| 557 | if (!isTreemapNode(activeNode)) {
|
|---|
| 558 | return;
|
|---|
| 559 | }
|
|---|
| 560 | var {
|
|---|
| 561 | dataKey,
|
|---|
| 562 | dispatch
|
|---|
| 563 | } = this.props;
|
|---|
| 564 | var activeCoordinate = {
|
|---|
| 565 | x: activeNode.x + activeNode.width / 2,
|
|---|
| 566 | y: activeNode.y + activeNode.height / 2
|
|---|
| 567 | };
|
|---|
| 568 |
|
|---|
| 569 | // Treemap does not support onTouchMove prop, but it could
|
|---|
| 570 | // onTouchMove?.(activeNode, Number(itemIndex), e);
|
|---|
| 571 | dispatch(setActiveMouseOverItemIndex({
|
|---|
| 572 | activeIndex: itemIndex,
|
|---|
| 573 | activeDataKey: dataKey,
|
|---|
| 574 | activeCoordinate,
|
|---|
| 575 | activeGraphicalItemId: this.props.id
|
|---|
| 576 | }));
|
|---|
| 577 | });
|
|---|
| 578 | }
|
|---|
| 579 | static getDerivedStateFromProps(nextProps, prevState) {
|
|---|
| 580 | if (nextProps.data !== prevState.prevData || nextProps.type !== prevState.prevType || nextProps.width !== prevState.prevWidth || nextProps.height !== prevState.prevHeight || nextProps.dataKey !== prevState.prevDataKey || nextProps.aspectRatio !== prevState.prevAspectRatio) {
|
|---|
| 581 | var root = computeNode({
|
|---|
| 582 | depth: 0,
|
|---|
| 583 | // @ts-expect-error missing properties
|
|---|
| 584 | node: {
|
|---|
| 585 | children: nextProps.data,
|
|---|
| 586 | x: 0,
|
|---|
| 587 | y: 0,
|
|---|
| 588 | width: nextProps.width,
|
|---|
| 589 | height: nextProps.height
|
|---|
| 590 | },
|
|---|
| 591 | index: 0,
|
|---|
| 592 | dataKey: nextProps.dataKey,
|
|---|
| 593 | nameKey: nextProps.nameKey
|
|---|
| 594 | });
|
|---|
| 595 | var formatRoot = squarify(root, nextProps.aspectRatio);
|
|---|
| 596 | return _objectSpread(_objectSpread({}, prevState), {}, {
|
|---|
| 597 | formatRoot,
|
|---|
| 598 | currentRoot: root,
|
|---|
| 599 | nestIndex: [root],
|
|---|
| 600 | prevAspectRatio: nextProps.aspectRatio,
|
|---|
| 601 | prevData: nextProps.data,
|
|---|
| 602 | prevWidth: nextProps.width,
|
|---|
| 603 | prevHeight: nextProps.height,
|
|---|
| 604 | prevDataKey: nextProps.dataKey,
|
|---|
| 605 | prevType: nextProps.type
|
|---|
| 606 | });
|
|---|
| 607 | }
|
|---|
| 608 | return null;
|
|---|
| 609 | }
|
|---|
| 610 | handleNestIndex(node, i) {
|
|---|
| 611 | var {
|
|---|
| 612 | nestIndex
|
|---|
| 613 | } = this.state;
|
|---|
| 614 | var {
|
|---|
| 615 | width,
|
|---|
| 616 | height,
|
|---|
| 617 | dataKey,
|
|---|
| 618 | nameKey,
|
|---|
| 619 | aspectRatio
|
|---|
| 620 | } = this.props;
|
|---|
| 621 | var root = computeNode({
|
|---|
| 622 | depth: 0,
|
|---|
| 623 | node: _objectSpread(_objectSpread({}, node), {}, {
|
|---|
| 624 | x: 0,
|
|---|
| 625 | y: 0,
|
|---|
| 626 | width,
|
|---|
| 627 | height
|
|---|
| 628 | }),
|
|---|
| 629 | index: 0,
|
|---|
| 630 | dataKey,
|
|---|
| 631 | nameKey,
|
|---|
| 632 | // with Treemap nesting, should this continue nesting the index or start from empty string?
|
|---|
| 633 | nestedActiveTooltipIndex: node.tooltipIndex
|
|---|
| 634 | });
|
|---|
| 635 | var formatRoot = squarify(root, aspectRatio);
|
|---|
| 636 | nestIndex = nestIndex.slice(0, i + 1);
|
|---|
| 637 | this.setState({
|
|---|
| 638 | formatRoot,
|
|---|
| 639 | currentRoot: node,
|
|---|
| 640 | nestIndex
|
|---|
| 641 | });
|
|---|
| 642 | }
|
|---|
| 643 | renderNode(root, node) {
|
|---|
| 644 | var {
|
|---|
| 645 | content,
|
|---|
| 646 | type
|
|---|
| 647 | } = this.props;
|
|---|
| 648 | var nodeProps = _objectSpread(_objectSpread(_objectSpread({}, svgPropertiesNoEvents(this.props)), node), {}, {
|
|---|
| 649 | root
|
|---|
| 650 | });
|
|---|
| 651 | var isLeaf = !node.children || !node.children.length;
|
|---|
| 652 | var {
|
|---|
| 653 | currentRoot
|
|---|
| 654 | } = this.state;
|
|---|
| 655 | var isCurrentRootChild = ((currentRoot === null || currentRoot === void 0 ? void 0 : currentRoot.children) || []).filter(item => item.depth === node.depth && item.name === node.name);
|
|---|
| 656 | if (!isCurrentRootChild.length && root.depth && type === 'nest') {
|
|---|
| 657 | return null;
|
|---|
| 658 | }
|
|---|
| 659 | return /*#__PURE__*/React.createElement(Layer, {
|
|---|
| 660 | key: "recharts-treemap-node-".concat(nodeProps.x, "-").concat(nodeProps.y, "-").concat(nodeProps.name),
|
|---|
| 661 | className: "recharts-treemap-depth-".concat(node.depth)
|
|---|
| 662 | }, /*#__PURE__*/React.createElement(TreemapItem, {
|
|---|
| 663 | isLeaf: isLeaf,
|
|---|
| 664 | content: content,
|
|---|
| 665 | nodeProps: nodeProps,
|
|---|
| 666 | treemapProps: this.props,
|
|---|
| 667 | onNestClick: this.handleClick
|
|---|
| 668 | }), node.children && node.children.length ? node.children.map(child => this.renderNode(node, child)) : null);
|
|---|
| 669 | }
|
|---|
| 670 | renderAllNodes() {
|
|---|
| 671 | var {
|
|---|
| 672 | formatRoot
|
|---|
| 673 | } = this.state;
|
|---|
| 674 | if (!formatRoot) {
|
|---|
| 675 | return null;
|
|---|
| 676 | }
|
|---|
| 677 | return this.renderNode(formatRoot, formatRoot);
|
|---|
| 678 | }
|
|---|
| 679 |
|
|---|
| 680 | // render nest treemap
|
|---|
| 681 | renderNestIndex() {
|
|---|
| 682 | var {
|
|---|
| 683 | nameKey,
|
|---|
| 684 | nestIndexContent
|
|---|
| 685 | } = this.props;
|
|---|
| 686 | var {
|
|---|
| 687 | nestIndex
|
|---|
| 688 | } = this.state;
|
|---|
| 689 | return /*#__PURE__*/React.createElement("div", {
|
|---|
| 690 | className: "recharts-treemap-nest-index-wrapper",
|
|---|
| 691 | style: {
|
|---|
| 692 | marginTop: '8px',
|
|---|
| 693 | textAlign: 'center'
|
|---|
| 694 | }
|
|---|
| 695 | }, nestIndex.map((item, i) => {
|
|---|
| 696 | // TODO need to verify nameKey type
|
|---|
| 697 | var rawName = get(item, nameKey, 'root');
|
|---|
| 698 | var name = typeof rawName === 'string' ? rawName : 'root';
|
|---|
| 699 | var content;
|
|---|
| 700 | if (/*#__PURE__*/React.isValidElement(nestIndexContent)) {
|
|---|
| 701 | // the cloned content is ignored at all times - let's remove it?
|
|---|
| 702 | content = /*#__PURE__*/React.cloneElement(nestIndexContent, item, i);
|
|---|
| 703 | }
|
|---|
| 704 | if (typeof nestIndexContent === 'function') {
|
|---|
| 705 | content = nestIndexContent(item, i);
|
|---|
| 706 | } else {
|
|---|
| 707 | content = name;
|
|---|
| 708 | }
|
|---|
| 709 | return (
|
|---|
| 710 | /*#__PURE__*/
|
|---|
| 711 | // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|---|
| 712 | React.createElement("div", {
|
|---|
| 713 | onClick: this.handleNestIndex.bind(this, item, i),
|
|---|
| 714 | key: "nest-index-".concat(uniqueId()),
|
|---|
| 715 | className: "recharts-treemap-nest-index-box",
|
|---|
| 716 | style: {
|
|---|
| 717 | cursor: 'pointer',
|
|---|
| 718 | display: 'inline-block',
|
|---|
| 719 | padding: '0 7px',
|
|---|
| 720 | background: '#000',
|
|---|
| 721 | color: '#fff',
|
|---|
| 722 | marginRight: '3px'
|
|---|
| 723 | }
|
|---|
| 724 | }, content)
|
|---|
| 725 | );
|
|---|
| 726 | }));
|
|---|
| 727 | }
|
|---|
| 728 | render() {
|
|---|
| 729 | var _this$props = this.props,
|
|---|
| 730 | {
|
|---|
| 731 | width,
|
|---|
| 732 | height,
|
|---|
| 733 | className,
|
|---|
| 734 | style,
|
|---|
| 735 | children,
|
|---|
| 736 | type
|
|---|
| 737 | } = _this$props,
|
|---|
| 738 | others = _objectWithoutProperties(_this$props, _excluded);
|
|---|
| 739 | var attrs = svgPropertiesNoEvents(others);
|
|---|
| 740 | return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SetTreemapTooltipEntrySettings, {
|
|---|
| 741 | dataKey: this.props.dataKey,
|
|---|
| 742 | nameKey: this.props.nameKey,
|
|---|
| 743 | stroke: this.props.stroke,
|
|---|
| 744 | fill: this.props.fill,
|
|---|
| 745 | currentRoot: this.state.currentRoot,
|
|---|
| 746 | id: this.props.id
|
|---|
| 747 | }), /*#__PURE__*/React.createElement(Surface, _extends({}, attrs, {
|
|---|
| 748 | width: width,
|
|---|
| 749 | height: type === 'nest' ? height - 30 : height,
|
|---|
| 750 | onTouchMove: this.handleTouchMove
|
|---|
| 751 | }), this.renderAllNodes(), children), type === 'nest' && this.renderNestIndex());
|
|---|
| 752 | }
|
|---|
| 753 | }
|
|---|
| 754 | _defineProperty(TreemapWithState, "displayName", 'Treemap');
|
|---|
| 755 | function TreemapDispatchInject(props) {
|
|---|
| 756 | var dispatch = useAppDispatch();
|
|---|
| 757 | var width = useChartWidth();
|
|---|
| 758 | var height = useChartHeight();
|
|---|
| 759 | if (!isPositiveNumber(width) || !isPositiveNumber(height)) {
|
|---|
| 760 | return null;
|
|---|
| 761 | }
|
|---|
| 762 | var {
|
|---|
| 763 | id: externalId
|
|---|
| 764 | } = props;
|
|---|
| 765 | return /*#__PURE__*/React.createElement(RegisterGraphicalItemId, {
|
|---|
| 766 | id: externalId,
|
|---|
| 767 | type: "treemap"
|
|---|
| 768 | }, id => /*#__PURE__*/React.createElement(TreemapWithState, _extends({}, props, {
|
|---|
| 769 | id: id,
|
|---|
| 770 | width: width,
|
|---|
| 771 | height: height,
|
|---|
| 772 | dispatch: dispatch
|
|---|
| 773 | })));
|
|---|
| 774 | }
|
|---|
| 775 |
|
|---|
| 776 | /**
|
|---|
| 777 | * The Treemap chart is used to visualize hierarchical data using nested rectangles.
|
|---|
| 778 | *
|
|---|
| 779 | * @consumes ResponsiveContainerContext
|
|---|
| 780 | * @provides TooltipEntrySettings
|
|---|
| 781 | */
|
|---|
| 782 | export function Treemap(outsideProps) {
|
|---|
| 783 | var _props$className;
|
|---|
| 784 | var props = resolveDefaultProps(outsideProps, defaultTreeMapProps);
|
|---|
| 785 | var {
|
|---|
| 786 | className,
|
|---|
| 787 | style,
|
|---|
| 788 | width,
|
|---|
| 789 | height
|
|---|
| 790 | } = props;
|
|---|
| 791 | var [tooltipPortal, setTooltipPortal] = useState(null);
|
|---|
| 792 | return /*#__PURE__*/React.createElement(RechartsStoreProvider, {
|
|---|
| 793 | preloadedState: {
|
|---|
| 794 | options
|
|---|
| 795 | },
|
|---|
| 796 | reduxStoreName: (_props$className = props.className) !== null && _props$className !== void 0 ? _props$className : 'Treemap'
|
|---|
| 797 | }, /*#__PURE__*/React.createElement(ReportChartMargin, {
|
|---|
| 798 | margin: defaultTreemapMargin
|
|---|
| 799 | }), /*#__PURE__*/React.createElement(RechartsWrapper, {
|
|---|
| 800 | dispatchTouchEvents: false,
|
|---|
| 801 | className: className,
|
|---|
| 802 | style: style,
|
|---|
| 803 | width: width,
|
|---|
| 804 | height: height
|
|---|
| 805 | /*
|
|---|
| 806 | * Treemap has a bug where it doesn't include strokeWidth in its dimension calculation
|
|---|
| 807 | * which makes the actual chart exactly {strokeWidth} larger than asked for.
|
|---|
| 808 | * It's not a huge deal usually, but it makes the responsive option cycle infinitely.
|
|---|
| 809 | */,
|
|---|
| 810 | responsive: false,
|
|---|
| 811 | ref: node => {
|
|---|
| 812 | if (tooltipPortal == null && node != null) {
|
|---|
| 813 | setTooltipPortal(node);
|
|---|
| 814 | }
|
|---|
| 815 | },
|
|---|
| 816 | onMouseEnter: undefined,
|
|---|
| 817 | onMouseLeave: undefined,
|
|---|
| 818 | onClick: undefined,
|
|---|
| 819 | onMouseMove: undefined,
|
|---|
| 820 | onMouseDown: undefined,
|
|---|
| 821 | onMouseUp: undefined,
|
|---|
| 822 | onContextMenu: undefined,
|
|---|
| 823 | onDoubleClick: undefined,
|
|---|
| 824 | onTouchStart: undefined,
|
|---|
| 825 | onTouchMove: undefined,
|
|---|
| 826 | onTouchEnd: undefined
|
|---|
| 827 | }, /*#__PURE__*/React.createElement(TooltipPortalContext.Provider, {
|
|---|
| 828 | value: tooltipPortal
|
|---|
| 829 | }, /*#__PURE__*/React.createElement(TreemapDispatchInject, props))));
|
|---|
| 830 | } |
|---|