source: node_modules/recharts/lib/chart/Treemap.js

Last change on this file was a762898, checked in by istevanoska <ilinastevanoska@…>, 5 months ago

Added visualizations

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