chartjs-chart-treemap 5.0.0-next.6 → 5.0.0-next.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v5.0.0-next.
|
|
2
|
+
* chartjs-chart-treemap v5.0.0-next.8
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2026 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
@@ -10,7 +10,7 @@ typeof define === 'function' && define.amd ? define(['exports', 'chart.js', 'cha
|
|
|
10
10
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["chartjs-chart-treemap"] = {}, global.Chart, global.Chart.helpers));
|
|
11
11
|
})(this, (function (exports, chart_js, helpers) { 'use strict';
|
|
12
12
|
|
|
13
|
-
var version = "5.0.0-next.
|
|
13
|
+
var version = "5.0.0-next.8";
|
|
14
14
|
|
|
15
15
|
function scaleRect(sq, xScale, yScale, sp) {
|
|
16
16
|
const sp2 = sp * 2;
|
|
@@ -486,6 +486,7 @@ function compareAspectRatio(oldStat, newStat, args) {
|
|
|
486
486
|
}
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
+
const WIDTH_CACHE_LIMIT = 4096;
|
|
489
490
|
const widthCache = new Map();
|
|
490
491
|
function shouldDrawCaption(displayMode, rect, options) {
|
|
491
492
|
if (!options || options.display === false) {
|
|
@@ -535,15 +536,17 @@ function drawText(ctx, rect, options, item, element, layout) {
|
|
|
535
536
|
ctx.clip();
|
|
536
537
|
}
|
|
537
538
|
function drawTextBlock(ctx, rect, block) {
|
|
538
|
-
const { align, colors, fonts, lines, padding, top } = block;
|
|
539
|
-
const
|
|
540
|
-
|
|
539
|
+
const { align, colors, fonts, lines, padding, styles, textAlign, top, width } = block;
|
|
540
|
+
const lineAlign = textAlign || align;
|
|
541
|
+
const x = calculateLineX(rect, align, lineAlign, padding, width);
|
|
542
|
+
ctx.textAlign = lineAlign;
|
|
541
543
|
ctx.textBaseline = 'middle';
|
|
542
544
|
let offset = 0;
|
|
543
545
|
lines.forEach((line, i)=>{
|
|
544
|
-
const
|
|
546
|
+
const style = styles[i];
|
|
547
|
+
const font = fontFor(fonts, style);
|
|
545
548
|
ctx.font = font.string;
|
|
546
|
-
ctx.fillStyle = colors[Math.min(
|
|
549
|
+
ctx.fillStyle = colors[Math.min(style, colors.length - 1)];
|
|
547
550
|
ctx.fillText(line, x, top + offset + font.lineHeight / 2);
|
|
548
551
|
offset += font.lineHeight;
|
|
549
552
|
});
|
|
@@ -572,10 +575,17 @@ function resolveCaptionText(captions, element, item) {
|
|
|
572
575
|
const padding = captions.padding;
|
|
573
576
|
if (measureLabelSize(ctx, [
|
|
574
577
|
text
|
|
575
|
-
], fonts).width + 2 * padding
|
|
576
|
-
return
|
|
578
|
+
], fonts).width + 2 * padding <= rect.w) {
|
|
579
|
+
return text;
|
|
577
580
|
}
|
|
578
|
-
|
|
581
|
+
const overflow = captions.overflow || 'ellipsis';
|
|
582
|
+
if (overflow === 'hidden') {
|
|
583
|
+
return undefined;
|
|
584
|
+
}
|
|
585
|
+
if (overflow === 'cut') {
|
|
586
|
+
return text;
|
|
587
|
+
}
|
|
588
|
+
return sliceTextToFitWidth(ctx, text, rect.w - 2 * padding, fonts);
|
|
579
589
|
}
|
|
580
590
|
function captionBlock(ctx, rect, options, item, element, layout) {
|
|
581
591
|
const { displayMode, rtl, spacing } = layout;
|
|
@@ -607,7 +617,14 @@ function captionBlock(ctx, rect, options, item, element, layout) {
|
|
|
607
617
|
text
|
|
608
618
|
],
|
|
609
619
|
padding,
|
|
610
|
-
|
|
620
|
+
styles: [
|
|
621
|
+
0
|
|
622
|
+
],
|
|
623
|
+
textAlign: captions.textAlign,
|
|
624
|
+
top,
|
|
625
|
+
width: measureLabelSize(ctx, [
|
|
626
|
+
text
|
|
627
|
+
], fonts).width
|
|
611
628
|
};
|
|
612
629
|
}
|
|
613
630
|
function labelBlock(ctx, rect, options, item, element) {
|
|
@@ -616,23 +633,36 @@ function labelBlock(ctx, rect, options, item, element) {
|
|
|
616
633
|
if (!content) {
|
|
617
634
|
return;
|
|
618
635
|
}
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
636
|
+
const { align, color, hoverColor, overflow, padding, wrap } = labels;
|
|
637
|
+
const maxWidth = rect.w - padding * 2;
|
|
638
|
+
const maxHeight = rect.h - padding * 2;
|
|
622
639
|
let fonts = getFontFromOptions(rect, labels);
|
|
623
|
-
let
|
|
640
|
+
let { lines, styles } = toLines(ctx, content, fonts, maxWidth, !!wrap);
|
|
641
|
+
let labelSize = measureLines(ctx, lines, styles, fonts);
|
|
624
642
|
const lblToDraw = labelToDraw(rect, labels, labelSize);
|
|
625
643
|
if (!lblToDraw) {
|
|
626
644
|
return;
|
|
627
645
|
}
|
|
628
646
|
if (helpers.isNumber(lblToDraw)) {
|
|
629
|
-
labelSize = {
|
|
630
|
-
height: labelSize.height * lblToDraw,
|
|
631
|
-
width: labelSize.width * lblToDraw
|
|
632
|
-
};
|
|
633
647
|
fonts = toFonts(fonts, lblToDraw);
|
|
648
|
+
if (wrap) {
|
|
649
|
+
const rewrapped = toLines(ctx, content, fonts, maxWidth, true);
|
|
650
|
+
lines = rewrapped.lines;
|
|
651
|
+
styles = rewrapped.styles;
|
|
652
|
+
labelSize = measureLines(ctx, lines, styles, fonts);
|
|
653
|
+
} else {
|
|
654
|
+
labelSize = {
|
|
655
|
+
height: labelSize.height * lblToDraw,
|
|
656
|
+
width: labelSize.width * lblToDraw
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (overflow === 'ellipsis') {
|
|
661
|
+
const trimmed = applyEllipsis(ctx, lines, styles, fonts, maxWidth, maxHeight);
|
|
662
|
+
lines = trimmed.lines;
|
|
663
|
+
styles = trimmed.styles;
|
|
664
|
+
labelSize = measureLines(ctx, lines, styles, fonts);
|
|
634
665
|
}
|
|
635
|
-
const { color, hoverColor, align, padding } = labels;
|
|
636
666
|
const optColor = (rect.active ? hoverColor : color) || color;
|
|
637
667
|
return {
|
|
638
668
|
align,
|
|
@@ -643,7 +673,10 @@ function labelBlock(ctx, rect, options, item, element) {
|
|
|
643
673
|
fonts,
|
|
644
674
|
lines,
|
|
645
675
|
padding,
|
|
646
|
-
|
|
676
|
+
styles,
|
|
677
|
+
textAlign: labels.textAlign,
|
|
678
|
+
top: calculateBlockTop(rect, labels, labelSize),
|
|
679
|
+
width: labelSize.width
|
|
647
680
|
};
|
|
648
681
|
}
|
|
649
682
|
function sliceTextToFitWidth(ctx, text, width, fonts) {
|
|
@@ -672,6 +705,126 @@ function sliceTextToFitWidth(ctx, text, width, fonts) {
|
|
|
672
705
|
const slicedText = text.slice(0, Math.max(0, lowerBoundLen - 1));
|
|
673
706
|
return slicedText ? slicedText + ellipsis : '';
|
|
674
707
|
}
|
|
708
|
+
const fontFor = (fonts, index)=>fonts[Math.min(index, fonts.length - 1)];
|
|
709
|
+
function wrapToWidth(ctx, text, font, width) {
|
|
710
|
+
if (width <= 0) {
|
|
711
|
+
return [
|
|
712
|
+
text
|
|
713
|
+
];
|
|
714
|
+
}
|
|
715
|
+
const fits = (value)=>measureLabelSize(ctx, [
|
|
716
|
+
value
|
|
717
|
+
], [
|
|
718
|
+
font
|
|
719
|
+
]).width <= width;
|
|
720
|
+
const lines = [];
|
|
721
|
+
let line = '';
|
|
722
|
+
const pushWord = (word)=>{
|
|
723
|
+
if (fits(word)) {
|
|
724
|
+
line = word;
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
let chunk = '';
|
|
728
|
+
for (const char of word){
|
|
729
|
+
if (chunk && !fits(chunk + char)) {
|
|
730
|
+
lines.push(chunk);
|
|
731
|
+
chunk = '';
|
|
732
|
+
}
|
|
733
|
+
chunk += char;
|
|
734
|
+
}
|
|
735
|
+
line = chunk;
|
|
736
|
+
};
|
|
737
|
+
for (const word of text.split(' ')){
|
|
738
|
+
const candidate = line ? `${line} ${word}` : word;
|
|
739
|
+
if (fits(candidate)) {
|
|
740
|
+
line = candidate;
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
if (line) {
|
|
744
|
+
lines.push(line);
|
|
745
|
+
line = '';
|
|
746
|
+
}
|
|
747
|
+
pushWord(word);
|
|
748
|
+
}
|
|
749
|
+
if (line) {
|
|
750
|
+
lines.push(line);
|
|
751
|
+
}
|
|
752
|
+
return lines.length ? lines : [
|
|
753
|
+
''
|
|
754
|
+
];
|
|
755
|
+
}
|
|
756
|
+
function toLines(ctx, content, fonts, width, wrap) {
|
|
757
|
+
const paragraphs = (helpers.isArray(content) ? content : [
|
|
758
|
+
content
|
|
759
|
+
]).map((entry)=>`${entry}`);
|
|
760
|
+
const lines = [];
|
|
761
|
+
const styles = [];
|
|
762
|
+
paragraphs.forEach((paragraph, index)=>{
|
|
763
|
+
const font = fontFor(fonts, index);
|
|
764
|
+
for (const piece of paragraph.split('\n')){
|
|
765
|
+
for (const line of wrap ? wrapToWidth(ctx, piece, font, width) : [
|
|
766
|
+
piece
|
|
767
|
+
]){
|
|
768
|
+
lines.push(line);
|
|
769
|
+
styles.push(index);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
return {
|
|
774
|
+
lines,
|
|
775
|
+
styles
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function measureLines(ctx, lines, styles, fonts) {
|
|
779
|
+
let width = 0;
|
|
780
|
+
let height = 0;
|
|
781
|
+
lines.forEach((line, i)=>{
|
|
782
|
+
const font = fontFor(fonts, styles[i]);
|
|
783
|
+
width = Math.max(width, measureLabelSize(ctx, [
|
|
784
|
+
line
|
|
785
|
+
], [
|
|
786
|
+
font
|
|
787
|
+
]).width);
|
|
788
|
+
height += font.lineHeight;
|
|
789
|
+
});
|
|
790
|
+
return {
|
|
791
|
+
height,
|
|
792
|
+
width
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
function applyEllipsis(ctx, lines, styles, fonts, maxWidth, maxHeight) {
|
|
796
|
+
const keptLines = [];
|
|
797
|
+
const keptStyles = [];
|
|
798
|
+
let used = 0;
|
|
799
|
+
for(let i = 0; i < lines.length; i++){
|
|
800
|
+
const font = fontFor(fonts, styles[i]);
|
|
801
|
+
if (keptLines.length && used + font.lineHeight > maxHeight) {
|
|
802
|
+
break;
|
|
803
|
+
}
|
|
804
|
+
used += font.lineHeight;
|
|
805
|
+
keptLines.push(lines[i]);
|
|
806
|
+
keptStyles.push(styles[i]);
|
|
807
|
+
}
|
|
808
|
+
const dropped = keptLines.length < lines.length;
|
|
809
|
+
const last = keptLines.length - 1;
|
|
810
|
+
for(let i = 0; i < keptLines.length; i++){
|
|
811
|
+
const font = fontFor(fonts, keptStyles[i]);
|
|
812
|
+
const tooWide = measureLabelSize(ctx, [
|
|
813
|
+
keptLines[i]
|
|
814
|
+
], [
|
|
815
|
+
font
|
|
816
|
+
]).width > maxWidth;
|
|
817
|
+
if (tooWide || dropped && i === last) {
|
|
818
|
+
keptLines[i] = sliceTextToFitWidth(ctx, keptLines[i], maxWidth, [
|
|
819
|
+
font
|
|
820
|
+
]);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
return {
|
|
824
|
+
lines: keptLines,
|
|
825
|
+
styles: keptStyles
|
|
826
|
+
};
|
|
827
|
+
}
|
|
675
828
|
function measureLabelSize(ctx, lines, fonts) {
|
|
676
829
|
const fontsKey = fonts.reduce((prev, item)=>{
|
|
677
830
|
prev += item.string;
|
|
@@ -696,6 +849,9 @@ function measureLabelSize(ctx, lines, fonts) {
|
|
|
696
849
|
height,
|
|
697
850
|
width
|
|
698
851
|
};
|
|
852
|
+
if (widthCache.size >= WIDTH_CACHE_LIMIT) {
|
|
853
|
+
widthCache.clear();
|
|
854
|
+
}
|
|
699
855
|
widthCache.set(mapKey, size);
|
|
700
856
|
}
|
|
701
857
|
return size;
|
|
@@ -739,13 +895,33 @@ function calculateBlockTop(rect, options, labelSize) {
|
|
|
739
895
|
}
|
|
740
896
|
return rect.y + (rect.h - labelSize.height) / 2 + padding;
|
|
741
897
|
}
|
|
742
|
-
function
|
|
898
|
+
function calculateBlockLeft(rect, align, padding, width) {
|
|
743
899
|
if (align === 'left') {
|
|
744
900
|
return rect.x + padding;
|
|
745
|
-
} else if (align === 'right') {
|
|
746
|
-
return rect.x + rect.w - padding;
|
|
747
901
|
}
|
|
748
|
-
|
|
902
|
+
if (align === 'right') {
|
|
903
|
+
return rect.x + rect.w - padding - width;
|
|
904
|
+
}
|
|
905
|
+
return rect.x + (rect.w - width) / 2;
|
|
906
|
+
}
|
|
907
|
+
function calculateLineX(rect, align, lineAlign, padding, width) {
|
|
908
|
+
if (align === lineAlign) {
|
|
909
|
+
if (align === 'left') {
|
|
910
|
+
return rect.x + padding;
|
|
911
|
+
}
|
|
912
|
+
if (align === 'right') {
|
|
913
|
+
return rect.x + rect.w - padding;
|
|
914
|
+
}
|
|
915
|
+
return rect.x + rect.w / 2;
|
|
916
|
+
}
|
|
917
|
+
const left = calculateBlockLeft(rect, align, padding, width);
|
|
918
|
+
if (lineAlign === 'left') {
|
|
919
|
+
return left;
|
|
920
|
+
}
|
|
921
|
+
if (lineAlign === 'right') {
|
|
922
|
+
return left + width;
|
|
923
|
+
}
|
|
924
|
+
return left + width / 2;
|
|
749
925
|
}
|
|
750
926
|
|
|
751
927
|
function buildHierarchy(values, gidx, keys, layout, parentGroupValue) {
|
|
@@ -1256,7 +1432,9 @@ TreemapElement.defaults = {
|
|
|
1256
1432
|
const label = ctx.raw._data?.label;
|
|
1257
1433
|
return ctx.raw.g || (typeof label === 'string' ? label : '');
|
|
1258
1434
|
},
|
|
1259
|
-
|
|
1435
|
+
overflow: 'ellipsis',
|
|
1436
|
+
padding: 3,
|
|
1437
|
+
textAlign: undefined
|
|
1260
1438
|
},
|
|
1261
1439
|
labels: {
|
|
1262
1440
|
align: 'center',
|
|
@@ -1278,7 +1456,9 @@ TreemapElement.defaults = {
|
|
|
1278
1456
|
},
|
|
1279
1457
|
overflow: 'cut',
|
|
1280
1458
|
padding: 3,
|
|
1281
|
-
position: 'middle'
|
|
1459
|
+
position: 'middle',
|
|
1460
|
+
textAlign: undefined,
|
|
1461
|
+
wrap: false
|
|
1282
1462
|
}
|
|
1283
1463
|
};
|
|
1284
1464
|
TreemapElement.descriptors = {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v5.0.0-next.
|
|
2
|
+
* chartjs-chart-treemap v5.0.0-next.8
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2026 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
6
6
|
*/
|
|
7
7
|
import { DatasetController, registry, Chart, Element } from 'chart.js';
|
|
8
|
-
import { toTRBL, toTRBLCorners, isObject, defined,
|
|
8
|
+
import { toTRBL, toTRBLCorners, isObject, defined, isNumber, isArray, toFont, valueOrDefault, clipArea, unclipArea, addRoundedRectPath } from 'chart.js/helpers';
|
|
9
9
|
|
|
10
|
-
var version = "5.0.0-next.
|
|
10
|
+
var version = "5.0.0-next.8";
|
|
11
11
|
|
|
12
12
|
function scaleRect(sq, xScale, yScale, sp) {
|
|
13
13
|
const sp2 = sp * 2;
|
|
@@ -460,6 +460,7 @@ function compareAspectRatio(oldStat, newStat, args) {
|
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
+
const WIDTH_CACHE_LIMIT = 4096;
|
|
463
464
|
const widthCache = new Map();
|
|
464
465
|
function shouldDrawCaption(displayMode, rect, options) {
|
|
465
466
|
if (!options || options.display === false) {
|
|
@@ -509,15 +510,17 @@ function drawText(ctx, rect, options, item, element, layout) {
|
|
|
509
510
|
ctx.clip();
|
|
510
511
|
}
|
|
511
512
|
function drawTextBlock(ctx, rect, block) {
|
|
512
|
-
const { align, colors, fonts, lines, padding, top } = block;
|
|
513
|
-
const
|
|
514
|
-
|
|
513
|
+
const { align, colors, fonts, lines, padding, styles, textAlign, top, width } = block;
|
|
514
|
+
const lineAlign = textAlign || align;
|
|
515
|
+
const x = calculateLineX(rect, align, lineAlign, padding, width);
|
|
516
|
+
ctx.textAlign = lineAlign;
|
|
515
517
|
ctx.textBaseline = 'middle';
|
|
516
518
|
let offset = 0;
|
|
517
519
|
lines.forEach((line, i)=>{
|
|
518
|
-
const
|
|
520
|
+
const style = styles[i];
|
|
521
|
+
const font = fontFor(fonts, style);
|
|
519
522
|
ctx.font = font.string;
|
|
520
|
-
ctx.fillStyle = colors[Math.min(
|
|
523
|
+
ctx.fillStyle = colors[Math.min(style, colors.length - 1)];
|
|
521
524
|
ctx.fillText(line, x, top + offset + font.lineHeight / 2);
|
|
522
525
|
offset += font.lineHeight;
|
|
523
526
|
});
|
|
@@ -546,10 +549,17 @@ function resolveCaptionText(captions, element, item) {
|
|
|
546
549
|
const padding = captions.padding;
|
|
547
550
|
if (measureLabelSize(ctx, [
|
|
548
551
|
text
|
|
549
|
-
], fonts).width + 2 * padding
|
|
550
|
-
return
|
|
552
|
+
], fonts).width + 2 * padding <= rect.w) {
|
|
553
|
+
return text;
|
|
551
554
|
}
|
|
552
|
-
|
|
555
|
+
const overflow = captions.overflow || 'ellipsis';
|
|
556
|
+
if (overflow === 'hidden') {
|
|
557
|
+
return undefined;
|
|
558
|
+
}
|
|
559
|
+
if (overflow === 'cut') {
|
|
560
|
+
return text;
|
|
561
|
+
}
|
|
562
|
+
return sliceTextToFitWidth(ctx, text, rect.w - 2 * padding, fonts);
|
|
553
563
|
}
|
|
554
564
|
function captionBlock(ctx, rect, options, item, element, layout) {
|
|
555
565
|
const { displayMode, rtl, spacing } = layout;
|
|
@@ -581,7 +591,14 @@ function captionBlock(ctx, rect, options, item, element, layout) {
|
|
|
581
591
|
text
|
|
582
592
|
],
|
|
583
593
|
padding,
|
|
584
|
-
|
|
594
|
+
styles: [
|
|
595
|
+
0
|
|
596
|
+
],
|
|
597
|
+
textAlign: captions.textAlign,
|
|
598
|
+
top,
|
|
599
|
+
width: measureLabelSize(ctx, [
|
|
600
|
+
text
|
|
601
|
+
], fonts).width
|
|
585
602
|
};
|
|
586
603
|
}
|
|
587
604
|
function labelBlock(ctx, rect, options, item, element) {
|
|
@@ -590,23 +607,36 @@ function labelBlock(ctx, rect, options, item, element) {
|
|
|
590
607
|
if (!content) {
|
|
591
608
|
return;
|
|
592
609
|
}
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
610
|
+
const { align, color, hoverColor, overflow, padding, wrap } = labels;
|
|
611
|
+
const maxWidth = rect.w - padding * 2;
|
|
612
|
+
const maxHeight = rect.h - padding * 2;
|
|
596
613
|
let fonts = getFontFromOptions(rect, labels);
|
|
597
|
-
let
|
|
614
|
+
let { lines, styles } = toLines(ctx, content, fonts, maxWidth, !!wrap);
|
|
615
|
+
let labelSize = measureLines(ctx, lines, styles, fonts);
|
|
598
616
|
const lblToDraw = labelToDraw(rect, labels, labelSize);
|
|
599
617
|
if (!lblToDraw) {
|
|
600
618
|
return;
|
|
601
619
|
}
|
|
602
620
|
if (isNumber(lblToDraw)) {
|
|
603
|
-
labelSize = {
|
|
604
|
-
height: labelSize.height * lblToDraw,
|
|
605
|
-
width: labelSize.width * lblToDraw
|
|
606
|
-
};
|
|
607
621
|
fonts = toFonts(fonts, lblToDraw);
|
|
622
|
+
if (wrap) {
|
|
623
|
+
const rewrapped = toLines(ctx, content, fonts, maxWidth, true);
|
|
624
|
+
lines = rewrapped.lines;
|
|
625
|
+
styles = rewrapped.styles;
|
|
626
|
+
labelSize = measureLines(ctx, lines, styles, fonts);
|
|
627
|
+
} else {
|
|
628
|
+
labelSize = {
|
|
629
|
+
height: labelSize.height * lblToDraw,
|
|
630
|
+
width: labelSize.width * lblToDraw
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (overflow === 'ellipsis') {
|
|
635
|
+
const trimmed = applyEllipsis(ctx, lines, styles, fonts, maxWidth, maxHeight);
|
|
636
|
+
lines = trimmed.lines;
|
|
637
|
+
styles = trimmed.styles;
|
|
638
|
+
labelSize = measureLines(ctx, lines, styles, fonts);
|
|
608
639
|
}
|
|
609
|
-
const { color, hoverColor, align, padding } = labels;
|
|
610
640
|
const optColor = (rect.active ? hoverColor : color) || color;
|
|
611
641
|
return {
|
|
612
642
|
align,
|
|
@@ -617,7 +647,10 @@ function labelBlock(ctx, rect, options, item, element) {
|
|
|
617
647
|
fonts,
|
|
618
648
|
lines,
|
|
619
649
|
padding,
|
|
620
|
-
|
|
650
|
+
styles,
|
|
651
|
+
textAlign: labels.textAlign,
|
|
652
|
+
top: calculateBlockTop(rect, labels, labelSize),
|
|
653
|
+
width: labelSize.width
|
|
621
654
|
};
|
|
622
655
|
}
|
|
623
656
|
function sliceTextToFitWidth(ctx, text, width, fonts) {
|
|
@@ -646,6 +679,126 @@ function sliceTextToFitWidth(ctx, text, width, fonts) {
|
|
|
646
679
|
const slicedText = text.slice(0, Math.max(0, lowerBoundLen - 1));
|
|
647
680
|
return slicedText ? slicedText + ellipsis : '';
|
|
648
681
|
}
|
|
682
|
+
const fontFor = (fonts, index)=>fonts[Math.min(index, fonts.length - 1)];
|
|
683
|
+
function wrapToWidth(ctx, text, font, width) {
|
|
684
|
+
if (width <= 0) {
|
|
685
|
+
return [
|
|
686
|
+
text
|
|
687
|
+
];
|
|
688
|
+
}
|
|
689
|
+
const fits = (value)=>measureLabelSize(ctx, [
|
|
690
|
+
value
|
|
691
|
+
], [
|
|
692
|
+
font
|
|
693
|
+
]).width <= width;
|
|
694
|
+
const lines = [];
|
|
695
|
+
let line = '';
|
|
696
|
+
const pushWord = (word)=>{
|
|
697
|
+
if (fits(word)) {
|
|
698
|
+
line = word;
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
let chunk = '';
|
|
702
|
+
for (const char of word){
|
|
703
|
+
if (chunk && !fits(chunk + char)) {
|
|
704
|
+
lines.push(chunk);
|
|
705
|
+
chunk = '';
|
|
706
|
+
}
|
|
707
|
+
chunk += char;
|
|
708
|
+
}
|
|
709
|
+
line = chunk;
|
|
710
|
+
};
|
|
711
|
+
for (const word of text.split(' ')){
|
|
712
|
+
const candidate = line ? `${line} ${word}` : word;
|
|
713
|
+
if (fits(candidate)) {
|
|
714
|
+
line = candidate;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
if (line) {
|
|
718
|
+
lines.push(line);
|
|
719
|
+
line = '';
|
|
720
|
+
}
|
|
721
|
+
pushWord(word);
|
|
722
|
+
}
|
|
723
|
+
if (line) {
|
|
724
|
+
lines.push(line);
|
|
725
|
+
}
|
|
726
|
+
return lines.length ? lines : [
|
|
727
|
+
''
|
|
728
|
+
];
|
|
729
|
+
}
|
|
730
|
+
function toLines(ctx, content, fonts, width, wrap) {
|
|
731
|
+
const paragraphs = (isArray(content) ? content : [
|
|
732
|
+
content
|
|
733
|
+
]).map((entry)=>`${entry}`);
|
|
734
|
+
const lines = [];
|
|
735
|
+
const styles = [];
|
|
736
|
+
paragraphs.forEach((paragraph, index)=>{
|
|
737
|
+
const font = fontFor(fonts, index);
|
|
738
|
+
for (const piece of paragraph.split('\n')){
|
|
739
|
+
for (const line of wrap ? wrapToWidth(ctx, piece, font, width) : [
|
|
740
|
+
piece
|
|
741
|
+
]){
|
|
742
|
+
lines.push(line);
|
|
743
|
+
styles.push(index);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
return {
|
|
748
|
+
lines,
|
|
749
|
+
styles
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function measureLines(ctx, lines, styles, fonts) {
|
|
753
|
+
let width = 0;
|
|
754
|
+
let height = 0;
|
|
755
|
+
lines.forEach((line, i)=>{
|
|
756
|
+
const font = fontFor(fonts, styles[i]);
|
|
757
|
+
width = Math.max(width, measureLabelSize(ctx, [
|
|
758
|
+
line
|
|
759
|
+
], [
|
|
760
|
+
font
|
|
761
|
+
]).width);
|
|
762
|
+
height += font.lineHeight;
|
|
763
|
+
});
|
|
764
|
+
return {
|
|
765
|
+
height,
|
|
766
|
+
width
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
function applyEllipsis(ctx, lines, styles, fonts, maxWidth, maxHeight) {
|
|
770
|
+
const keptLines = [];
|
|
771
|
+
const keptStyles = [];
|
|
772
|
+
let used = 0;
|
|
773
|
+
for(let i = 0; i < lines.length; i++){
|
|
774
|
+
const font = fontFor(fonts, styles[i]);
|
|
775
|
+
if (keptLines.length && used + font.lineHeight > maxHeight) {
|
|
776
|
+
break;
|
|
777
|
+
}
|
|
778
|
+
used += font.lineHeight;
|
|
779
|
+
keptLines.push(lines[i]);
|
|
780
|
+
keptStyles.push(styles[i]);
|
|
781
|
+
}
|
|
782
|
+
const dropped = keptLines.length < lines.length;
|
|
783
|
+
const last = keptLines.length - 1;
|
|
784
|
+
for(let i = 0; i < keptLines.length; i++){
|
|
785
|
+
const font = fontFor(fonts, keptStyles[i]);
|
|
786
|
+
const tooWide = measureLabelSize(ctx, [
|
|
787
|
+
keptLines[i]
|
|
788
|
+
], [
|
|
789
|
+
font
|
|
790
|
+
]).width > maxWidth;
|
|
791
|
+
if (tooWide || dropped && i === last) {
|
|
792
|
+
keptLines[i] = sliceTextToFitWidth(ctx, keptLines[i], maxWidth, [
|
|
793
|
+
font
|
|
794
|
+
]);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
lines: keptLines,
|
|
799
|
+
styles: keptStyles
|
|
800
|
+
};
|
|
801
|
+
}
|
|
649
802
|
function measureLabelSize(ctx, lines, fonts) {
|
|
650
803
|
const fontsKey = fonts.reduce((prev, item)=>{
|
|
651
804
|
prev += item.string;
|
|
@@ -670,6 +823,9 @@ function measureLabelSize(ctx, lines, fonts) {
|
|
|
670
823
|
height,
|
|
671
824
|
width
|
|
672
825
|
};
|
|
826
|
+
if (widthCache.size >= WIDTH_CACHE_LIMIT) {
|
|
827
|
+
widthCache.clear();
|
|
828
|
+
}
|
|
673
829
|
widthCache.set(mapKey, size);
|
|
674
830
|
}
|
|
675
831
|
return size;
|
|
@@ -713,13 +869,33 @@ function calculateBlockTop(rect, options, labelSize) {
|
|
|
713
869
|
}
|
|
714
870
|
return rect.y + (rect.h - labelSize.height) / 2 + padding;
|
|
715
871
|
}
|
|
716
|
-
function
|
|
872
|
+
function calculateBlockLeft(rect, align, padding, width) {
|
|
717
873
|
if (align === 'left') {
|
|
718
874
|
return rect.x + padding;
|
|
719
|
-
} else if (align === 'right') {
|
|
720
|
-
return rect.x + rect.w - padding;
|
|
721
875
|
}
|
|
722
|
-
|
|
876
|
+
if (align === 'right') {
|
|
877
|
+
return rect.x + rect.w - padding - width;
|
|
878
|
+
}
|
|
879
|
+
return rect.x + (rect.w - width) / 2;
|
|
880
|
+
}
|
|
881
|
+
function calculateLineX(rect, align, lineAlign, padding, width) {
|
|
882
|
+
if (align === lineAlign) {
|
|
883
|
+
if (align === 'left') {
|
|
884
|
+
return rect.x + padding;
|
|
885
|
+
}
|
|
886
|
+
if (align === 'right') {
|
|
887
|
+
return rect.x + rect.w - padding;
|
|
888
|
+
}
|
|
889
|
+
return rect.x + rect.w / 2;
|
|
890
|
+
}
|
|
891
|
+
const left = calculateBlockLeft(rect, align, padding, width);
|
|
892
|
+
if (lineAlign === 'left') {
|
|
893
|
+
return left;
|
|
894
|
+
}
|
|
895
|
+
if (lineAlign === 'right') {
|
|
896
|
+
return left + width;
|
|
897
|
+
}
|
|
898
|
+
return left + width / 2;
|
|
723
899
|
}
|
|
724
900
|
|
|
725
901
|
function buildHierarchy(values, gidx, keys, layout, parentGroupValue) {
|
|
@@ -1230,7 +1406,9 @@ TreemapElement.defaults = {
|
|
|
1230
1406
|
const label = ctx.raw._data?.label;
|
|
1231
1407
|
return ctx.raw.g || (typeof label === 'string' ? label : '');
|
|
1232
1408
|
},
|
|
1233
|
-
|
|
1409
|
+
overflow: 'ellipsis',
|
|
1410
|
+
padding: 3,
|
|
1411
|
+
textAlign: undefined
|
|
1234
1412
|
},
|
|
1235
1413
|
labels: {
|
|
1236
1414
|
align: 'center',
|
|
@@ -1252,7 +1430,9 @@ TreemapElement.defaults = {
|
|
|
1252
1430
|
},
|
|
1253
1431
|
overflow: 'cut',
|
|
1254
1432
|
padding: 3,
|
|
1255
|
-
position: 'middle'
|
|
1433
|
+
position: 'middle',
|
|
1434
|
+
textAlign: undefined,
|
|
1435
|
+
wrap: false
|
|
1256
1436
|
}
|
|
1257
1437
|
};
|
|
1258
1438
|
TreemapElement.descriptors = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v5.0.0-next.
|
|
2
|
+
* chartjs-chart-treemap v5.0.0-next.8
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2026 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
6
6
|
*/
|
|
7
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-chart-treemap"]={},t.Chart,t.Chart.helpers)}(this,function(t,e,n){"use strict";function i(t,e,n,i){const r=2*i,o=e.getPixelForValue(t.x),s=n.getPixelForValue(t.y),a=e.getPixelForValue(t.x+t.w)-o,h=n.getPixelForValue(t.y+t.h)-s;return{height:h-r,hidden:r>a||r>h,width:a-r,x:o+i,y:s+i}}const r={displayMode:"containerBoxes",rtl:!1,spacing:.5};function o(t,e,n){return Math.max(Math.min(t,n),e)}function s(t,e,i){const r=n.toTRBL(t);return{b:o(r.bottom,0,i),l:o(r.left,0,e),r:o(r.right,0,e),t:o(r.top,0,i)}}function a(t,e,n,i){const r=t._normalized,o=e*r/n,s=Math.sqrt(r*o),a=r/s;return{d1:s,d2:a,h:"_ix"===i?a:s,w:"_ix"===i?s:a}}function h(t,e,n,i){e.a=e._normalized,e.h=n.h,e.s=i,e.w=n.w,e.x=((t,e)=>t.rtl?t.x+t.iw-e:t.x+t._ix)(t,n.w),e.y=t.y+t._iy,delete e._normalized}class l{get area(){return this.w*this.h}get iw(){return this.w-this._ix}get ih(){return this.h-this._iy}get dir(){const t=this.ih;return t<=this.iw&&t>0?"y":"x"}get side(){return"x"===this.dir?this.iw:this.ih}map(t){const{dir:e,side:n}=this,i="x"===e?"_ix":"_iy",r=t.nsum,o=t.get(),s=n*n,l=r*r;let c=0,u=0;for(const e of o){const n=a(e,s,l,i);u+=n.d1,c=Math.max(c,n.d2),h(this,e,n,t.sum),this[i]+=n.d1}this["x"===e?"_iy":"_ix"]+=c,this[i]-=u}constructor(t){t=t||{h:1,w:1},this.rtl=!!t.rtl,this.unsorted=!!t.unsorted,this.x=t.x||t.left||0,this.y=t.y||t.top||0,this._ix=0,this._iy=0,this.w=t.w||t.width||t.right-t.left,this.h=t.h||t.height||t.bottom-t.top}}const c=Math.min,u=Math.max;function d(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{max:u(t.max,n),min:c(t.min,n),nmax:u(t.nmax,i),nmin:c(t.nmin,i),nsum:t.nsum+i,sum:t.sum+n}}function p(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class f{get length(){return this._arr.length}reset(){this._arr=[],this._hist=[],this.sum=0,this.nsum=0,this.min=1/0,this.max=-1/0,this.nmin=1/0,this.nmax=-1/0}push(t){p(this,t,d(this,t))}pushIf(t,e,...n){const i=d(this,t);if(!e((r=this,{max:r.max,min:r.min,nmax:r.nmax,nmin:r.nmin,nsum:r.nsum,sum:r.sum}),i,n))return t;var r;p(this,t,i)}get(){return this._arr}constructor(t,e){this._arr=[],this._hist=[],this.sum=0,this.nsum=0,this.min=1/0,this.max=-1/0,this.nmin=1/0,this.nmax=-1/0,this.key=t,this.ratio=e,this.reset()}}const g=(t,e)=>e>t||t.length>e.length&&t.startsWith(e),m=t=>String(t),x=t=>null!=t&&""!==t;function y(t,e,i,r=[],o=0,s=[]){const a=o-1;if(t[0]in i&&o>0){const n=r.reduce((t,e,n)=>(n!==a&&(t[m(n)]=e),t),{});n[e]=r[a],t.forEach(t=>{n[t]=i[t]}),s.push(n)}else for(const a of Object.keys(i)){const h=i[a];n.isObject(h)&&(r.push(a),y(t,e,h,r,o+1,s))}return r.splice(a,1),s}function b(t,e,n){const i=y(t,e,n);if(!i.length)return i;const r=i.reduce((t,e)=>{const n=Object.keys(e).length-2;return Math.max(t,n)},0);return i.forEach(t=>{for(let e=0;e<r;e++){const n=m(e);t[n]||(t[n]="")}}),i}function v(t,e,n){const i=[];for(const n of t){const t=e[n];x(t)&&i.push(t)}return i.length?i.join("."):n}function w(t,e,n,i){for(let e=i;e<n.length;e++){const i=m(n[e]);if(x(t[i]))return{group:i,groupIndex:e,value:t[i]}}if(x(t[e]))return{group:e,groupIndex:i,value:t[e]}}function _(t,e,n,i){if(n in t)return;t[n]={value:0};const r=t[n];i.forEach(t=>{r[t]=0}),e[n]=[]}function M(t,e,n,i,r,o,s=[],a=s,h=s.length-1){const l=n[0],c=n.slice(1),u=Object.create(null),d=Object.create(null),p=[],f=a.length?a:[e],g=a.length?h:0;let m,x;for(m=0,x=t.length;m<x;++m){const e=t[m];if(r&&e[r]!==o)continue;const n=w(e,i,f,g);if(!n)return[];const s=n.value;_(u,d,s,c),u[s].value+=+e[l],u[s].label=s,u[s].group=n.group,u[s].groupIndex=n.groupIndex;const a=u[s];c.forEach(t=>{a[t]+=e[t]}),u[s].path=v(f.slice(0,n.groupIndex+1),e,s),d[s].push(e)}return Object.keys(u).forEach(t=>{const n={children:d[t]};n[l]=+u[t].value,c.forEach(e=>{n[e]=+u[t][e]}),n[e]=u[t].label,n.group=u[t].group,n.groupIndex=u[t].groupIndex,n.label=t,n.path=u[t].path,r&&(n[r]=o),p.push(n)}),p}function C(t,e){let i,r=t.length;if(!r)return e;const o=n.isObject(t[0]);for(e=o?e:"v",i=0,r=t.length;i<r;++i)o?t[i]._idx=i:t[i]={_idx:i,v:t[i]};return e}function O(t,e){e?t.sort((t,n)=>+n[e]-+t[e]):t.sort((t,e)=>+e-+t)}function j(t,e){let n,i,r;for(n=0,i=0,r=t.length;i<r;++i)n+=e?+t[i][e]:+t[i];return n}function R(t,e,n,i=!0){const r=n.split(".");let o=0;for(const s of e.split(".")){const a=r[o++];if(Number.parseInt(s,10)<Number.parseInt(a,10))break;if(g(a,s)){if(i)throw new Error(`${t} v${n} is not supported. v${e} or newer is required.`);return!1}}return!0}function P(t,e,n){if(0===t.sum)return!0;const[i]=n,r=t.nsum*t.nsum,o=e.nsum*e.nsum,s=i*i,a=Math.max(s*t.nmax/r,r/(s*t.nmin));return Math.max(s*e.nmax/o,o/(s*e.nmin))<=a}function k(t,e,n,i){const r=t?t.slice():[],o=C(r,e[0]);return r.map(r=>{const s={_data:t[r._idx],v:o?+r[o]:+r,vs:void 0};return n&&(s.g=r[n],s.gs=void 0,s.l=r.groupIndex??i,s.vs=e.reduce((t,e)=>(t[e]=+r[e],t),{})),s})}function E(t){O(t,"v")}const L=new Map;function T(t,e,i){if(!i||!1===i.display)return!1;if("headerBoxes"===t)return!0;const{w:r,h:o}=e,s=n.toFont(i.font||{}).lineHeight,a=Math.max(Math.min(2*n.valueOrDefault(i.padding,3),Math.min(r,o)),0);return r-a>s&&o-a>s}function D(t,e,n,i){if("headerBoxes"!==t)return n.lineHeight+2*i;const r=n.lineHeight+2*i;return e.h<2*r?e.h/3:r}function I(t,e,i,r,o,s){const{captions:a,labels:h}=i,{displayMode:l}=s;let c;r&&(!n.defined(r.l)||r.isLeaf)?h.display&&(c=function(t,e,i,r,o){const s=i.labels,a=$(s.formatter,F(o,r));if(!a)return;const h=n.isArray(a)?a:[a];let l=function(t,e){const{font:i,hoverFont:r}=e,o=(t.active?r:i)||i;return Array.isArray(o)?o.map(t=>n.toFont(t)):[n.toFont(o)]}(e,s),c=A(t,h,l);const u=function(t,e,n){const{overflow:i,padding:r}=e,{width:o,height:s}=n;if("hidden"===i)return!(o+2*r>t.w||s+2*r>t.h);if("fit"===i){const e=Math.min(t.w/(o+2*r),t.h/(s+2*r));if(e<1)return e}return!0}(e,s,c);if(!u)return;n.isNumber(u)&&(c={height:c.height*u,width:c.width*u},l=function(t,e){return t.map(t=>{const{lineHeight:i,...r}=t;return n.toFont({...r,size:Math.floor(t.size*e)})})}(l,u));const{color:d,hoverColor:p,align:f,padding:g}=s,m=(e.active?p:d)||d;return{align:f,clipY:g,colors:n.isArray(m)?m:[m],fonts:l,lines:h,padding:g,top:S(e,s,c)}}(t,e,i,r,o)):T(l,e,a)&&(c=function(t,e,i,r,o,s){const{displayMode:a,rtl:h,spacing:l}=s,{captions:c}=i,{color:u,hoverColor:d,font:p,hoverFont:f,padding:g,align:m}=c,x=(e.active?f:p)||p,y=n.toFont(x);if(y.lineHeight>e.h)return;const b=function(t,e,n,i,r,o){const s=function(t,e,n){return $(t.formatter,F(e,n))||n.g||""}(n,i,r);if(!s)return;const a=n.padding;if(A(t,[s],o).width+2*a>e.w)return function(t,e,n,i){const r="...",o=A(t,[r],i).width;if(o>=n)return"";let s,a=1,h=e.length;for(;a<=h;){const r=Math.floor((a+h)/2);s=A(t,[e.slice(0,r)],i).width,s+o>n?h=r-1:a=r+1}const l=e.slice(0,Math.max(0,a-1));return l?l+r:""}(t,s,e.w-2*a,o);return s}(t,e,c,o,r,[y]);if(void 0===b)return;const v=[y],w="headerBoxes"===a?e.y+(e.h-y.lineHeight)/2:e.y+g+l;return{align:m||(h?"right":"left"),clipY:"headerBoxes"===a?0:g,colors:[(e.active?d:u)||u],fonts:v,lines:[b],padding:g,top:w}}(t,e,i,r,o,s)),c&&(t.save(),function(t,e,n,i){const r=Math.max(0,n),o=Math.max(0,i);t.beginPath(),t.rect(e.x+r,e.y+o,Math.max(0,e.w-2*r),Math.max(0,e.h-2*o)),t.clip()}(t,e,c.padding,c.clipY),function(t,e,n){const{align:i,colors:r,fonts:o,lines:s,padding:a,top:h}=n,l=function(t,e,n){if("left"===e)return t.x+n;if("right"===e)return t.x+t.w-n;return t.x+t.w/2}(e,i,a);t.textAlign=i,t.textBaseline="middle";let c=0;s.forEach((e,n)=>{const i=o[Math.min(n,o.length-1)];t.font=i.string,t.fillStyle=r[Math.min(n,r.length-1)],t.fillText(e,l,h+c+i.lineHeight/2),c+=i.lineHeight})}(t,e,c),t.restore())}function F(t,e){const n=t.$context||{active:!!t.active,raw:e,type:"data"};return n.active=!!t.active,n.raw=e,n}function $(t,e){return"function"==typeof t?t(e):t}function A(t,e,n){const i=n.reduce((t,e)=>t+=e.string,""),r=e.join()+i+(t._measureText?"-spriting":"");let o=L.get(r);if(!o){t.save();const i=e.length;let s=0,a=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const o=e[r];s=Math.max(s,t.measureText(o).width),a+=i.lineHeight}t.restore(),o={height:a,width:s},L.set(r,o)}return o}function S(t,e,n){const{position:i,padding:r}=e;return"top"===i?t.y+r:"bottom"===i?t.y+t.h-r-n.height:t.y+(t.h-n.height)/2+r}function B(t,e,n,i,r){const{groups:o,leafKey:s,unsorted:a}=i,h=o.length,l=m(o[e]),c=M(t,l,n,s,void 0,r,o.filter((t,n)=>n<=e),o,e),u=k(c,n,l,e);a||E(u);for(const t of u){const r=t._data,o=r.groupIndex+1,s=e<h-1&&o<h?B(r.children,o,n,i,t.g):[];Object.defineProperty(t,"_children",{configurable:!0,value:s,writable:!0}),t.isLeaf=!s.length}return u}function z(t){const e=t.slice();for(const n of t)n._children?.length&&e.push(...z(n._children));return e}function H(t,e,n,i){if(void 0!==i)for(const e of t)e.gs=i;!function(t,e){const n=t.length;if(!n)return;const i=new l(e),r=new f("v",i.area/j(t,"v"));let o,s=i.side;for(let e=0;e<n;++e)o=r.pushIf(t[e],P,s),o&&(i.map(r),s=i.side,r.reset(),r.push(o));r.length&&i.map(r)}(t,e);for(const i of t)i._children?.length&&H(i._children,V(i,e,n),n,i.s)}function K(t,e,i){H(t,e,i),function(t,e){const{captions:i,displayMode:r}=e;if("headerBoxes"!==r)return;const o=n.toFont(i.font),s=n.valueOrDefault(i.padding,3);for(const e of t)e.isLeaf||(T(r,e,i)?(e.h=D(r,e,o,s),e.hidden=!1):e.hidden=!0)}(z(t),i)}function V(t,e,i){const{borderWidth:r,captions:o,displayMode:a}=i,h="headerBoxes"===a?0:i.spacing,l="headerBoxes"===a?{b:0,l:0,r:0,t:0}:s(r,t.w/2,t.h/2),c={...e,h:t.h-2*h-l.t-l.b,w:t.w-2*h-l.l-l.r,x:t.x+h+l.l,y:t.y+h+l.t};if(T(a,c,o)){const t=D(a,c,n.toFont(o.font),n.valueOrDefault(o.padding,3));c.y+=t,c.h-=t}return c}function W(t,e,i){const{groups:r,leafKey:o,unsorted:s}=i,a=n.isObject(t)?b(e,o,t):t;if(r.length)return B(a,0,e,i);const h=k(a||[],e);return s||E(h),h}function q(){const t=e.registry.plugins.get("tooltip");t&&!t.positioners.treemap&&(t.positioners.treemap=t=>{if(!t.length)return!1;return t.at(-1).element.tooltipPosition()})}class Y extends e.DatasetController{initialize(){q(),this.enableOptionSharing=!0,super.initialize()}getMinMax(t){return{max:"x"===t.axis?t.right-t.left:t.bottom-t.top,min:0}}configure(){super.configure();const{xScale:t,yScale:e}=this.getMeta();if(!t||!e)return;const n=t.right-t.left,i=e.bottom-e.top,r={h:i,rtl:!!this.options.rtl,unsorted:!!this.options.unsorted,w:n,x:0,y:0};var o,s;o=this._rect,s=r,o&&s&&o.x===s.x&&o.y===s.y&&o.w===s.w&&o.h===s.h&&o.rtl===s.rtl&&o.unsorted===s.unsorted||(this._rect=r,this._rectChanged=!0),this._rectChanged&&(t.max=n,t.configure(),e.max=i,e.configure())}_layoutOptions(){const t=this.getDataset(),e=this.options;return{borderWidth:t.borderWidth,captions:t.captions||{},displayMode:e.displayMode,groups:e.groups||[],leafKey:e.leafKey,spacing:n.valueOrDefault(t.spacing,0),unsorted:!!e.unsorted}}buildOrUpdateElements(t){this.parse(0,0);const e=this.getMeta(),n=e._parsed.length,i=e.data;for(i.length>n&&i.splice(n,i.length-n);i.length<n;)i.push(new this.dataElementType)}parse(t,e){const n=this.getDataset();if(void 0!==n.tree)throw new Error('chartjs-chart-treemap v5: the "tree" option was renamed to "data". See https://chartjs-chart-treemap.pages.dev/usage/');const i=this.options,r=[i.key||""].concat(i.sumKeys||[]),o=W(n.data||[],r,this._layoutOptions()),s=z(o),a=s.map(t=>`${t.v}\0${t.g}\0${t.l}`).join("");this._fingerprint!==a&&(this._fingerprint=a,this._nodes=o,this.getMeta()._parsed=s,this._layoutDirty=!0)}getContext(t,n,i){const r=e.DatasetController.prototype.getContext.call(this,t,n,i),o="number"==typeof t?this.getParsed(t):void 0;return o&&(r.raw=o,r.parsed=o),r}getLabelAndValue(t){const e=this.getParsed(t);if(!e)return{label:"",value:""};const n=this.getDataset(),i=e.g??e._data?.label??n.label;return{label:void 0===i?"":`${i}`,value:`${e.v}`}}update(t){const{data:e}=this.getMeta();"reset"===t&&this.configure(),(this._layoutDirty||this._rectChanged)&&(K(this._nodes,this._rect,this._layoutOptions()),this._layoutDirty=!1,this._rectChanged=!1),this.updateElements(e,0,e.length,t)}updateElements(t,e,n,r){const o="reset"===r,s=this.resolveDataElementOptions(e,r);this._rect.options=s;const a=this.getSharedOptions(s),h=this.includeOptions(r,a||{}),{xScale:l,yScale:c}=this.getMeta(),u=this.options.spacing;for(let s=e;s<e+n;s++){const e=a||this.resolveDataElementOptions(s,r),n=this.getParsed(s),d=i(n,l,c,u);d.hidden=d.hidden||!!n.hidden,o&&(d.width=0,d.height=0),h&&(d.options=e),this.updateElement(t[s],s,d,r)}this.updateSharedOptions(a||{},r,s)}draw(){const{ctx:t,chartArea:e}=this.chart,i=this.getMeta().data||[],{displayMode:r,rtl:o,spacing:s}=this.options,a={displayMode:r,rtl:o,spacing:s};n.clipArea(t,e);for(let e=0,n=i.length;e<n;++e){const n=i[e];n.hidden||n.draw(t,this.getParsed(e),a)}n.unclipArea(t)}constructor(t,e){super(t,e),this._rect=void 0,this._rectChanged=!0,this._nodes=[],this._layoutDirty=!0,this._fingerprint=void 0}}function N(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{bottom:i+o,left:n,right:n+r,top:i}}function U(t){const e=N(t),i=e.right-e.left,r=e.bottom-e.top,a=s(t.options.borderWidth,i/2,r/2),h=function(t,e,i){const r=n.toTRBLCorners(t),s=Math.min(e,i);return{bottomLeft:o(r.bottomLeft,0,s),bottomRight:o(r.bottomRight,0,s),topLeft:o(r.topLeft,0,s),topRight:o(r.topRight,0,s)}}(t.options.borderRadius,i/2,r/2),l={active:t.active,h:r,radius:h,w:i,x:e.left,y:e.top};return{inner:{active:t.active,h:l.h-a.t-a.b,radius:{bottomLeft:Math.max(0,h.bottomLeft-Math.max(a.b,a.l)),bottomRight:Math.max(0,h.bottomRight-Math.max(a.b,a.r)),topLeft:Math.max(0,h.topLeft-Math.max(a.t,a.l)),topRight:Math.max(0,h.topRight-Math.max(a.t,a.r))},w:l.w-a.l-a.r,x:l.x+a.l,y:l.y+a.t},outer:l}}function G(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&N(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function X(t,e){t.rect(e.x,e.y,e.w,e.h)}Y.id="treemap",Y.version="5.0.0-next.6",Y.defaults={animations:{numbers:{properties:["x","y","width","height"],type:"number"}},dataElementType:"treemap",displayMode:r.displayMode,groups:[],key:"",leafKey:"_leaf",rtl:r.rtl,spacing:r.spacing,sumKeys:[],unsorted:!1},Y.descriptors={_indexable:!1,_scriptable:!0,captions:{_fallback:!0,_scriptable:t=>"formatter"!==t},labels:{_fallback:!0,_scriptable:t=>"formatter"!==t}},Y.overrides={hover:{},interaction:{includeInvisible:!0,intersect:!0,mode:"point"},plugins:{tooltip:{callbacks:{label(t){const e=t.parsed,n=e.g||e._data?.label||t.dataset.label;return(n?`${n}: `:"")+e.v},title(t){if(t.length){return t[0].dataset.key||""}return""}},intersect:!0,position:"treemap"}},scales:{x:{alignToPixels:!0,bounds:"data",display:!1,type:"linear"},y:{alignToPixels:!0,bounds:"data",display:!1,reverse:!0,type:"linear"}}},Y.beforeRegister=()=>{R("chart.js","4.0",e.Chart.version)},Y.afterRegister=()=>{q()},Y.afterUnregister=()=>{const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap};class J extends e.Element{draw(t,e,i=r){if(!e)return;const o=this.options,{inner:s,outer:a}=U(this),h=(l=a.radius).topLeft||l.topRight||l.bottomLeft||l.bottomRight?n.addRoundedRectPath:X;var l;t.save(),a.w===s.w&&a.h===s.h||(t.beginPath(),h(t,a),t.clip(),h(t,s),t.fillStyle=o.borderColor,t.fill("evenodd")),t.beginPath(),h(t,s),t.fillStyle=o.backgroundColor,t.fill(),I(t,s,o,e,this,i),t.restore()}inRange(t,e,n){return G(this,t,e,n)}inXRange(t,e){return G(this,t,null,e)}inYRange(t,e){return G(this,null,t,e)}getCenterPoint(t){const{x:e,y:n,width:i,height:r}=this.getProps(["x","y","width","height"],t);return{x:e+i/2,y:n+r/2}}tooltipPosition(){return this.getCenterPoint()}constructor(t){super(),this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}}J.id="treemap",J.defaults={borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>{const e=t.raw._data?.label;return t.raw.g||("string"==typeof e?e:"")},padding:3},labels:{align:"center",color:"black",display:!1,font:{},formatter(t){const e=t.raw._data?.label;return t.raw.g?[t.raw.g,`${t.raw.v}`]:"string"==typeof e?[e,`${t.raw.v}`]:`${t.raw.v}`},overflow:"cut",padding:3,position:"middle"}},J.descriptors={_indexable:!1,_scriptable:!0,captions:{_fallback:!0,_scriptable:t=>"formatter"!==t},labels:{_fallback:!0,_scriptable:t=>"formatter"!==t}},J.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},e.Chart.register(Y,J),t.TreemapController=Y,t.TreemapElement=J,t.flatten=function(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()},t.flattenTree=function(t,e,n){return b(e,n,t)},t.getGroupKey=m,t.group=M,t.index=C,t.normalizeTreeToArray=b,t.requireVersion=R,t.sort=O,t.sum=j});
|
|
7
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-chart-treemap"]={},t.Chart,t.Chart.helpers)}(this,function(t,e,n){"use strict";function i(t,e,n,i){const r=2*i,o=e.getPixelForValue(t.x),s=n.getPixelForValue(t.y),a=e.getPixelForValue(t.x+t.w)-o,h=n.getPixelForValue(t.y+t.h)-s;return{height:h-r,hidden:r>a||r>h,width:a-r,x:o+i,y:s+i}}const r={displayMode:"containerBoxes",rtl:!1,spacing:.5};function o(t,e,n){return Math.max(Math.min(t,n),e)}function s(t,e,i){const r=n.toTRBL(t);return{b:o(r.bottom,0,i),l:o(r.left,0,e),r:o(r.right,0,e),t:o(r.top,0,i)}}function a(t,e,n,i){const r=t._normalized,o=e*r/n,s=Math.sqrt(r*o),a=r/s;return{d1:s,d2:a,h:"_ix"===i?a:s,w:"_ix"===i?s:a}}function h(t,e,n,i){e.a=e._normalized,e.h=n.h,e.s=i,e.w=n.w,e.x=((t,e)=>t.rtl?t.x+t.iw-e:t.x+t._ix)(t,n.w),e.y=t.y+t._iy,delete e._normalized}class l{get area(){return this.w*this.h}get iw(){return this.w-this._ix}get ih(){return this.h-this._iy}get dir(){const t=this.ih;return t<=this.iw&&t>0?"y":"x"}get side(){return"x"===this.dir?this.iw:this.ih}map(t){const{dir:e,side:n}=this,i="x"===e?"_ix":"_iy",r=t.nsum,o=t.get(),s=n*n,l=r*r;let c=0,u=0;for(const e of o){const n=a(e,s,l,i);u+=n.d1,c=Math.max(c,n.d2),h(this,e,n,t.sum),this[i]+=n.d1}this["x"===e?"_iy":"_ix"]+=c,this[i]-=u}constructor(t){t=t||{h:1,w:1},this.rtl=!!t.rtl,this.unsorted=!!t.unsorted,this.x=t.x||t.left||0,this.y=t.y||t.top||0,this._ix=0,this._iy=0,this.w=t.w||t.width||t.right-t.left,this.h=t.h||t.height||t.bottom-t.top}}const c=Math.min,u=Math.max;function d(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{max:u(t.max,n),min:c(t.min,n),nmax:u(t.nmax,i),nmin:c(t.nmin,i),nsum:t.nsum+i,sum:t.sum+n}}function f(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class p{get length(){return this._arr.length}reset(){this._arr=[],this._hist=[],this.sum=0,this.nsum=0,this.min=1/0,this.max=-1/0,this.nmin=1/0,this.nmax=-1/0}push(t){f(this,t,d(this,t))}pushIf(t,e,...n){const i=d(this,t);if(!e((r=this,{max:r.max,min:r.min,nmax:r.nmax,nmin:r.nmin,nsum:r.nsum,sum:r.sum}),i,n))return t;var r;f(this,t,i)}get(){return this._arr}constructor(t,e){this._arr=[],this._hist=[],this.sum=0,this.nsum=0,this.min=1/0,this.max=-1/0,this.nmin=1/0,this.nmax=-1/0,this.key=t,this.ratio=e,this.reset()}}const g=(t,e)=>e>t||t.length>e.length&&t.startsWith(e),m=t=>String(t),x=t=>null!=t&&""!==t;function y(t,e,i,r=[],o=0,s=[]){const a=o-1;if(t[0]in i&&o>0){const n=r.reduce((t,e,n)=>(n!==a&&(t[m(n)]=e),t),{});n[e]=r[a],t.forEach(t=>{n[t]=i[t]}),s.push(n)}else for(const a of Object.keys(i)){const h=i[a];n.isObject(h)&&(r.push(a),y(t,e,h,r,o+1,s))}return r.splice(a,1),s}function b(t,e,n){const i=y(t,e,n);if(!i.length)return i;const r=i.reduce((t,e)=>{const n=Object.keys(e).length-2;return Math.max(t,n)},0);return i.forEach(t=>{for(let e=0;e<r;e++){const n=m(e);t[n]||(t[n]="")}}),i}function w(t,e,n){const i=[];for(const n of t){const t=e[n];x(t)&&i.push(t)}return i.length?i.join("."):n}function v(t,e,n,i){for(let e=i;e<n.length;e++){const i=m(n[e]);if(x(t[i]))return{group:i,groupIndex:e,value:t[i]}}if(x(t[e]))return{group:e,groupIndex:i,value:t[e]}}function _(t,e,n,i){if(n in t)return;t[n]={value:0};const r=t[n];i.forEach(t=>{r[t]=0}),e[n]=[]}function M(t,e,n,i,r,o,s=[],a=s,h=s.length-1){const l=n[0],c=n.slice(1),u=Object.create(null),d=Object.create(null),f=[],p=a.length?a:[e],g=a.length?h:0;let m,x;for(m=0,x=t.length;m<x;++m){const e=t[m];if(r&&e[r]!==o)continue;const n=v(e,i,p,g);if(!n)return[];const s=n.value;_(u,d,s,c),u[s].value+=+e[l],u[s].label=s,u[s].group=n.group,u[s].groupIndex=n.groupIndex;const a=u[s];c.forEach(t=>{a[t]+=e[t]}),u[s].path=w(p.slice(0,n.groupIndex+1),e,s),d[s].push(e)}return Object.keys(u).forEach(t=>{const n={children:d[t]};n[l]=+u[t].value,c.forEach(e=>{n[e]=+u[t][e]}),n[e]=u[t].label,n.group=u[t].group,n.groupIndex=u[t].groupIndex,n.label=t,n.path=u[t].path,r&&(n[r]=o),f.push(n)}),f}function C(t,e){let i,r=t.length;if(!r)return e;const o=n.isObject(t[0]);for(e=o?e:"v",i=0,r=t.length;i<r;++i)o?t[i]._idx=i:t[i]={_idx:i,v:t[i]};return e}function O(t,e){e?t.sort((t,n)=>+n[e]-+t[e]):t.sort((t,e)=>+e-+t)}function j(t,e){let n,i,r;for(n=0,i=0,r=t.length;i<r;++i)n+=e?+t[i][e]:+t[i];return n}function R(t,e,n,i=!0){const r=n.split(".");let o=0;for(const s of e.split(".")){const a=r[o++];if(Number.parseInt(s,10)<Number.parseInt(a,10))break;if(g(a,s)){if(i)throw new Error(`${t} v${n} is not supported. v${e} or newer is required.`);return!1}}return!0}function E(t,e,n){if(0===t.sum)return!0;const[i]=n,r=t.nsum*t.nsum,o=e.nsum*e.nsum,s=i*i,a=Math.max(s*t.nmax/r,r/(s*t.nmin));return Math.max(s*e.nmax/o,o/(s*e.nmin))<=a}function P(t,e,n,i){const r=t?t.slice():[],o=C(r,e[0]);return r.map(r=>{const s={_data:t[r._idx],v:o?+r[o]:+r,vs:void 0};return n&&(s.g=r[n],s.gs=void 0,s.l=r.groupIndex??i,s.vs=e.reduce((t,e)=>(t[e]=+r[e],t),{})),s})}function k(t){O(t,"v")}const A=new Map;function L(t,e,i){if(!i||!1===i.display)return!1;if("headerBoxes"===t)return!0;const{w:r,h:o}=e,s=n.toFont(i.font||{}).lineHeight,a=Math.max(Math.min(2*n.valueOrDefault(i.padding,3),Math.min(r,o)),0);return r-a>s&&o-a>s}function T(t,e,n,i){if("headerBoxes"!==t)return n.lineHeight+2*i;const r=n.lineHeight+2*i;return e.h<2*r?e.h/3:r}function $(t,e,i,r,o,s){const{captions:a,labels:h}=i,{displayMode:l}=s;let c;r&&(!n.defined(r.l)||r.isLeaf)?h.display&&(c=function(t,e,i,r,o){const s=i.labels,a=I(s.formatter,D(o,r));if(!a)return;const{align:h,color:l,hoverColor:c,overflow:u,padding:d,wrap:f}=s,p=e.w-2*d,g=e.h-2*d;let m=function(t,e){const{font:i,hoverFont:r}=e,o=(t.active?r:i)||i;return Array.isArray(o)?o.map(t=>n.toFont(t)):[n.toFont(o)]}(e,s),{lines:x,styles:y}=B(t,a,m,p,!!f),b=z(t,x,y,m);const w=function(t,e,n){const{overflow:i,padding:r}=e,{width:o,height:s}=n;if("hidden"===i)return!(o+2*r>t.w||s+2*r>t.h);if("fit"===i){const e=Math.min(t.w/(o+2*r),t.h/(s+2*r));if(e<1)return e}return!0}(e,s,b);if(!w)return;if(n.isNumber(w))if(m=function(t,e){return t.map(t=>{const{lineHeight:i,...r}=t;return n.toFont({...r,size:Math.floor(t.size*e)})})}(m,w),f){const e=B(t,a,m,p,!0);x=e.lines,y=e.styles,b=z(t,x,y,m)}else b={height:b.height*w,width:b.width*w};if("ellipsis"===u){const e=function(t,e,n,i,r,o){const s=[],a=[];let h=0;for(let t=0;t<e.length;t++){const r=H(i,n[t]);if(s.length&&h+r.lineHeight>o)break;h+=r.lineHeight,s.push(e[t]),a.push(n[t])}const l=s.length<e.length,c=s.length-1;for(let e=0;e<s.length;e++){const n=H(i,a[e]);(K(t,[s[e]],[n]).width>r||l&&e===c)&&(s[e]=F(t,s[e],r,[n]))}return{lines:s,styles:a}}(t,x,y,m,p,g);x=e.lines,y=e.styles,b=z(t,x,y,m)}const v=(e.active?c:l)||l;return{align:h,clipY:d,colors:n.isArray(v)?v:[v],fonts:m,lines:x,padding:d,styles:y,textAlign:s.textAlign,top:V(e,s,b),width:b.width}}(t,e,i,r,o)):L(l,e,a)&&(c=function(t,e,i,r,o,s){const{displayMode:a,rtl:h,spacing:l}=s,{captions:c}=i,{color:u,hoverColor:d,font:f,hoverFont:p,padding:g,align:m}=c,x=(e.active?p:f)||f,y=n.toFont(x);if(y.lineHeight>e.h)return;const b=function(t,e,n,i,r,o){const s=function(t,e,n){return I(t.formatter,D(e,n))||n.g||""}(n,i,r);if(!s)return;const a=n.padding;if(K(t,[s],o).width+2*a<=e.w)return s;const h=n.overflow||"ellipsis";if("hidden"===h)return;if("cut"===h)return s;return F(t,s,e.w-2*a,o)}(t,e,c,o,r,[y]);if(void 0===b)return;const w=[y],v="headerBoxes"===a?e.y+(e.h-y.lineHeight)/2:e.y+g+l;return{align:m||(h?"right":"left"),clipY:"headerBoxes"===a?0:g,colors:[(e.active?d:u)||u],fonts:w,lines:[b],padding:g,styles:[0],textAlign:c.textAlign,top:v,width:K(t,[b],w).width}}(t,e,i,r,o,s)),c&&(t.save(),function(t,e,n,i){const r=Math.max(0,n),o=Math.max(0,i);t.beginPath(),t.rect(e.x+r,e.y+o,Math.max(0,e.w-2*r),Math.max(0,e.h-2*o)),t.clip()}(t,e,c.padding,c.clipY),function(t,e,n){const{align:i,colors:r,fonts:o,lines:s,padding:a,styles:h,textAlign:l,top:c,width:u}=n,d=l||i,f=function(t,e,n,i,r){if(e===n)return"left"===e?t.x+i:"right"===e?t.x+t.w-i:t.x+t.w/2;const o=function(t,e,n,i){if("left"===e)return t.x+n;if("right"===e)return t.x+t.w-n-i;return t.x+(t.w-i)/2}(t,e,i,r);if("left"===n)return o;if("right"===n)return o+r;return o+r/2}(e,i,d,a,u);t.textAlign=d,t.textBaseline="middle";let p=0;s.forEach((e,n)=>{const i=h[n],s=H(o,i);t.font=s.string,t.fillStyle=r[Math.min(i,r.length-1)],t.fillText(e,f,c+p+s.lineHeight/2),p+=s.lineHeight})}(t,e,c),t.restore())}function D(t,e){const n=t.$context||{active:!!t.active,raw:e,type:"data"};return n.active=!!t.active,n.raw=e,n}function I(t,e){return"function"==typeof t?t(e):t}function F(t,e,n,i){const r=K(t,["..."],i).width;if(r>=n)return"";let o,s=1,a=e.length;for(;s<=a;){const h=Math.floor((s+a)/2);o=K(t,[e.slice(0,h)],i).width,o+r>n?a=h-1:s=h+1}const h=e.slice(0,Math.max(0,s-1));return h?h+"...":""}const H=(t,e)=>t[Math.min(e,t.length-1)];function S(t,e,n,i){if(i<=0)return[e];const r=e=>K(t,[e],[n]).width<=i,o=[];let s="";const a=t=>{if(r(t))return void(s=t);let e="";for(const n of t)e&&!r(e+n)&&(o.push(e),e=""),e+=n;s=e};for(const t of e.split(" ")){const e=s?`${s} ${t}`:t;r(e)?s=e:(s&&(o.push(s),s=""),a(t))}return s&&o.push(s),o.length?o:[""]}function B(t,e,i,r,o){const s=(n.isArray(e)?e:[e]).map(t=>`${t}`),a=[],h=[];return s.forEach((e,n)=>{const s=H(i,n);for(const i of e.split("\n"))for(const e of o?S(t,i,s,r):[i])a.push(e),h.push(n)}),{lines:a,styles:h}}function z(t,e,n,i){let r=0,o=0;return e.forEach((e,s)=>{const a=H(i,n[s]);r=Math.max(r,K(t,[e],[a]).width),o+=a.lineHeight}),{height:o,width:r}}function K(t,e,n){const i=n.reduce((t,e)=>t+=e.string,""),r=e.join()+i+(t._measureText?"-spriting":"");let o=A.get(r);if(!o){t.save();const i=e.length;let s=0,a=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const o=e[r];s=Math.max(s,t.measureText(o).width),a+=i.lineHeight}t.restore(),o={height:a,width:s},A.size>=4096&&A.clear(),A.set(r,o)}return o}function V(t,e,n){const{position:i,padding:r}=e;return"top"===i?t.y+r:"bottom"===i?t.y+t.h-r-n.height:t.y+(t.h-n.height)/2+r}function W(t,e,n,i,r){const{groups:o,leafKey:s,unsorted:a}=i,h=o.length,l=m(o[e]),c=M(t,l,n,s,void 0,r,o.filter((t,n)=>n<=e),o,e),u=P(c,n,l,e);a||k(u);for(const t of u){const r=t._data,o=r.groupIndex+1,s=e<h-1&&o<h?W(r.children,o,n,i,t.g):[];Object.defineProperty(t,"_children",{configurable:!0,value:s,writable:!0}),t.isLeaf=!s.length}return u}function q(t){const e=t.slice();for(const n of t)n._children?.length&&e.push(...q(n._children));return e}function Y(t,e,n,i){if(void 0!==i)for(const e of t)e.gs=i;!function(t,e){const n=t.length;if(!n)return;const i=new l(e),r=new p("v",i.area/j(t,"v"));let o,s=i.side;for(let e=0;e<n;++e)o=r.pushIf(t[e],E,s),o&&(i.map(r),s=i.side,r.reset(),r.push(o));r.length&&i.map(r)}(t,e);for(const i of t)i._children?.length&&Y(i._children,U(i,e,n),n,i.s)}function N(t,e,i){Y(t,e,i),function(t,e){const{captions:i,displayMode:r}=e;if("headerBoxes"!==r)return;const o=n.toFont(i.font),s=n.valueOrDefault(i.padding,3);for(const e of t)e.isLeaf||(L(r,e,i)?(e.h=T(r,e,o,s),e.hidden=!1):e.hidden=!0)}(q(t),i)}function U(t,e,i){const{borderWidth:r,captions:o,displayMode:a}=i,h="headerBoxes"===a?0:i.spacing,l="headerBoxes"===a?{b:0,l:0,r:0,t:0}:s(r,t.w/2,t.h/2),c={...e,h:t.h-2*h-l.t-l.b,w:t.w-2*h-l.l-l.r,x:t.x+h+l.l,y:t.y+h+l.t};if(L(a,c,o)){const t=T(a,c,n.toFont(o.font),n.valueOrDefault(o.padding,3));c.y+=t,c.h-=t}return c}function G(t,e,i){const{groups:r,leafKey:o,unsorted:s}=i,a=n.isObject(t)?b(e,o,t):t;if(r.length)return W(a,0,e,i);const h=P(a||[],e);return s||k(h),h}function X(){const t=e.registry.plugins.get("tooltip");t&&!t.positioners.treemap&&(t.positioners.treemap=t=>{if(!t.length)return!1;return t.at(-1).element.tooltipPosition()})}class J extends e.DatasetController{initialize(){X(),this.enableOptionSharing=!0,super.initialize()}getMinMax(t){return{max:"x"===t.axis?t.right-t.left:t.bottom-t.top,min:0}}configure(){super.configure();const{xScale:t,yScale:e}=this.getMeta();if(!t||!e)return;const n=t.right-t.left,i=e.bottom-e.top,r={h:i,rtl:!!this.options.rtl,unsorted:!!this.options.unsorted,w:n,x:0,y:0};var o,s;o=this._rect,s=r,o&&s&&o.x===s.x&&o.y===s.y&&o.w===s.w&&o.h===s.h&&o.rtl===s.rtl&&o.unsorted===s.unsorted||(this._rect=r,this._rectChanged=!0),this._rectChanged&&(t.max=n,t.configure(),e.max=i,e.configure())}_layoutOptions(){const t=this.getDataset(),e=this.options;return{borderWidth:t.borderWidth,captions:t.captions||{},displayMode:e.displayMode,groups:e.groups||[],leafKey:e.leafKey,spacing:n.valueOrDefault(t.spacing,0),unsorted:!!e.unsorted}}buildOrUpdateElements(t){this.parse(0,0);const e=this.getMeta(),n=e._parsed.length,i=e.data;for(i.length>n&&i.splice(n,i.length-n);i.length<n;)i.push(new this.dataElementType)}parse(t,e){const n=this.getDataset();if(void 0!==n.tree)throw new Error('chartjs-chart-treemap v5: the "tree" option was renamed to "data". See https://chartjs-chart-treemap.pages.dev/usage/');const i=this.options,r=[i.key||""].concat(i.sumKeys||[]),o=G(n.data||[],r,this._layoutOptions()),s=q(o),a=s.map(t=>`${t.v}\0${t.g}\0${t.l}`).join("");this._fingerprint!==a&&(this._fingerprint=a,this._nodes=o,this.getMeta()._parsed=s,this._layoutDirty=!0)}getContext(t,n,i){const r=e.DatasetController.prototype.getContext.call(this,t,n,i),o="number"==typeof t?this.getParsed(t):void 0;return o&&(r.raw=o,r.parsed=o),r}getLabelAndValue(t){const e=this.getParsed(t);if(!e)return{label:"",value:""};const n=this.getDataset(),i=e.g??e._data?.label??n.label;return{label:void 0===i?"":`${i}`,value:`${e.v}`}}update(t){const{data:e}=this.getMeta();"reset"===t&&this.configure(),(this._layoutDirty||this._rectChanged)&&(N(this._nodes,this._rect,this._layoutOptions()),this._layoutDirty=!1,this._rectChanged=!1),this.updateElements(e,0,e.length,t)}updateElements(t,e,n,r){const o="reset"===r,s=this.resolveDataElementOptions(e,r);this._rect.options=s;const a=this.getSharedOptions(s),h=this.includeOptions(r,a||{}),{xScale:l,yScale:c}=this.getMeta(),u=this.options.spacing;for(let s=e;s<e+n;s++){const e=a||this.resolveDataElementOptions(s,r),n=this.getParsed(s),d=i(n,l,c,u);d.hidden=d.hidden||!!n.hidden,o&&(d.width=0,d.height=0),h&&(d.options=e),this.updateElement(t[s],s,d,r)}this.updateSharedOptions(a||{},r,s)}draw(){const{ctx:t,chartArea:e}=this.chart,i=this.getMeta().data||[],{displayMode:r,rtl:o,spacing:s}=this.options,a={displayMode:r,rtl:o,spacing:s};n.clipArea(t,e);for(let e=0,n=i.length;e<n;++e){const n=i[e];n.hidden||n.draw(t,this.getParsed(e),a)}n.unclipArea(t)}constructor(t,e){super(t,e),this._rect=void 0,this._rectChanged=!0,this._nodes=[],this._layoutDirty=!0,this._fingerprint=void 0}}function Q(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{bottom:i+o,left:n,right:n+r,top:i}}function Z(t){const e=Q(t),i=e.right-e.left,r=e.bottom-e.top,a=s(t.options.borderWidth,i/2,r/2),h=function(t,e,i){const r=n.toTRBLCorners(t),s=Math.min(e,i);return{bottomLeft:o(r.bottomLeft,0,s),bottomRight:o(r.bottomRight,0,s),topLeft:o(r.topLeft,0,s),topRight:o(r.topRight,0,s)}}(t.options.borderRadius,i/2,r/2),l={active:t.active,h:r,radius:h,w:i,x:e.left,y:e.top};return{inner:{active:t.active,h:l.h-a.t-a.b,radius:{bottomLeft:Math.max(0,h.bottomLeft-Math.max(a.b,a.l)),bottomRight:Math.max(0,h.bottomRight-Math.max(a.b,a.r)),topLeft:Math.max(0,h.topLeft-Math.max(a.t,a.l)),topRight:Math.max(0,h.topRight-Math.max(a.t,a.r))},w:l.w-a.l-a.r,x:l.x+a.l,y:l.y+a.t},outer:l}}function tt(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&Q(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function et(t,e){t.rect(e.x,e.y,e.w,e.h)}J.id="treemap",J.version="5.0.0-next.8",J.defaults={animations:{numbers:{properties:["x","y","width","height"],type:"number"}},dataElementType:"treemap",displayMode:r.displayMode,groups:[],key:"",leafKey:"_leaf",rtl:r.rtl,spacing:r.spacing,sumKeys:[],unsorted:!1},J.descriptors={_indexable:!1,_scriptable:!0,captions:{_fallback:!0,_scriptable:t=>"formatter"!==t},labels:{_fallback:!0,_scriptable:t=>"formatter"!==t}},J.overrides={hover:{},interaction:{includeInvisible:!0,intersect:!0,mode:"point"},plugins:{tooltip:{callbacks:{label(t){const e=t.parsed,n=e.g||e._data?.label||t.dataset.label;return(n?`${n}: `:"")+e.v},title(t){if(t.length){return t[0].dataset.key||""}return""}},intersect:!0,position:"treemap"}},scales:{x:{alignToPixels:!0,bounds:"data",display:!1,type:"linear"},y:{alignToPixels:!0,bounds:"data",display:!1,reverse:!0,type:"linear"}}},J.beforeRegister=()=>{R("chart.js","4.0",e.Chart.version)},J.afterRegister=()=>{X()},J.afterUnregister=()=>{const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap};class nt extends e.Element{draw(t,e,i=r){if(!e)return;const o=this.options,{inner:s,outer:a}=Z(this),h=(l=a.radius).topLeft||l.topRight||l.bottomLeft||l.bottomRight?n.addRoundedRectPath:et;var l;t.save(),a.w===s.w&&a.h===s.h||(t.beginPath(),h(t,a),t.clip(),h(t,s),t.fillStyle=o.borderColor,t.fill("evenodd")),t.beginPath(),h(t,s),t.fillStyle=o.backgroundColor,t.fill(),$(t,s,o,e,this,i),t.restore()}inRange(t,e,n){return tt(this,t,e,n)}inXRange(t,e){return tt(this,t,null,e)}inYRange(t,e){return tt(this,null,t,e)}getCenterPoint(t){const{x:e,y:n,width:i,height:r}=this.getProps(["x","y","width","height"],t);return{x:e+i/2,y:n+r/2}}tooltipPosition(){return this.getCenterPoint()}constructor(t){super(),this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}}nt.id="treemap",nt.defaults={borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>{const e=t.raw._data?.label;return t.raw.g||("string"==typeof e?e:"")},overflow:"ellipsis",padding:3,textAlign:void 0},labels:{align:"center",color:"black",display:!1,font:{},formatter(t){const e=t.raw._data?.label;return t.raw.g?[t.raw.g,`${t.raw.v}`]:"string"==typeof e?[e,`${t.raw.v}`]:`${t.raw.v}`},overflow:"cut",padding:3,position:"middle",textAlign:void 0,wrap:!1}},nt.descriptors={_indexable:!1,_scriptable:!0,captions:{_fallback:!0,_scriptable:t=>"formatter"!==t},labels:{_fallback:!0,_scriptable:t=>"formatter"!==t}},nt.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},e.Chart.register(J,nt),t.TreemapController=J,t.TreemapElement=nt,t.flatten=function(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()},t.flattenTree=function(t,e,n){return b(e,n,t)},t.getGroupKey=m,t.group=M,t.index=C,t.normalizeTreeToArray=b,t.requireVersion=R,t.sort=O,t.sum=j});
|
|
8
8
|
//# sourceMappingURL=chartjs-chart-treemap.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chartjs-chart-treemap.min.js","sources":["../src/helpers/index.ts","../src/options.ts","../src/rect.ts","../src/statArray.ts","../src/utils.ts","../src/squarify.ts","../src/text.ts","../src/layout.ts","../src/controller.ts","../src/geometry.ts","../src/element.ts","../src/index.ts"],"sourcesContent":["export function scaleRect(sq: any, xScale: any, yScale: any, sp: number) {\n const sp2 = sp * 2\n const x = xScale.getPixelForValue(sq.x)\n const y = yScale.getPixelForValue(sq.y)\n const w = xScale.getPixelForValue(sq.x + sq.w) - x\n const h = yScale.getPixelForValue(sq.y + sq.h) - y\n return {\n height: h - sp2,\n hidden: sp2 > w || sp2 > h,\n width: w - sp2,\n x: x + sp,\n y: y + sp,\n }\n}\n\nexport function rectNotEqual(r1: any, r2: any) {\n return (\n !r1 ||\n !r2 ||\n r1.x !== r2.x ||\n r1.y !== r2.y ||\n r1.w !== r2.w ||\n r1.h !== r2.h ||\n r1.rtl !== r2.rtl ||\n r1.unsorted !== r2.unsorted\n )\n}\n\nexport function arrayNotEqual(a: any[], b: any[]) {\n let i: number\n let n: number\n\n if (!a || !b) {\n return true\n }\n\n if (a === b) {\n return false\n }\n\n if (a.length !== b.length) {\n return true\n }\n\n for (i = 0, n = a.length; i < n; ++i) {\n if (a[i] !== b[i]) {\n return true\n }\n }\n return false\n}\n","import type {\n TreemapBorderRadius,\n TreemapBorderWidth,\n TreemapLayoutOptions,\n TreemapOptions,\n} from './types'\n\nimport { toTRBL, toTRBLCorners } from 'chart.js/helpers'\n\n/**\n * Options that shape the whole dataset's layout rather than a single element.\n * They live in the controller's defaults; the element receives the resolved\n * values as an argument to `draw`.\n */\nexport const layoutDefaults: TreemapLayoutOptions = {\n displayMode: 'containerBoxes',\n rtl: false,\n spacing: 0.5,\n}\n\nexport type ParsedBorderWidth = {\n b: number\n l: number\n r: number\n t: number\n}\n\nfunction limit(value: number, min: number, max: number) {\n return Math.max(Math.min(value, max), min)\n}\n\nexport function parseBorderWidth(\n value: TreemapBorderWidth,\n maxW: number,\n maxH: number\n): ParsedBorderWidth {\n const o = toTRBL(value as Parameters<typeof toTRBL>[0])\n\n return {\n b: limit(o.bottom, 0, maxH),\n l: limit(o.left, 0, maxW),\n r: limit(o.right, 0, maxW),\n t: limit(o.top, 0, maxH),\n }\n}\n\nexport function parseBorderRadius(\n value: TreemapOptions['borderRadius'],\n maxW: number,\n maxH: number\n): TreemapBorderRadius {\n const o = toTRBLCorners(value as Parameters<typeof toTRBLCorners>[0])\n const maxR = Math.min(maxW, maxH)\n\n return {\n bottomLeft: limit(o.bottomLeft, 0, maxR),\n bottomRight: limit(o.bottomRight, 0, maxR),\n topLeft: limit(o.topLeft, 0, maxR),\n topRight: limit(o.topRight, 0, maxR),\n }\n}\n","function getDims(itm: any, w2: number, s2: number, key: string) {\n const a = itm._normalized\n const ar = (w2 * a) / s2\n const d1 = Math.sqrt(a * ar)\n const d2 = a / d1\n const w = key === '_ix' ? d1 : d2\n const h = key === '_ix' ? d2 : d1\n\n return { d1, d2, h, w }\n}\n\nconst getX = (rect: Rect, w: number) => (rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix)\n\n/** Writes the geometry of one packed row onto the nodes themselves. */\nfunction assignRow(rect: Rect, itm: any, dims: any, sum: number) {\n itm.a = itm._normalized\n itm.h = dims.h\n itm.s = sum\n itm.w = dims.w\n itm.x = getX(rect, dims.w)\n itm.y = rect.y + rect._iy\n delete itm._normalized\n}\n\nexport default class Rect {\n [key: string]: any\n rtl: boolean\n unsorted: boolean\n x: number\n y: number\n _ix: number\n _iy: number\n w: number\n h: number\n\n constructor(r?: any) {\n r = r || { h: 1, w: 1 }\n this.rtl = !!r.rtl\n this.unsorted = !!r.unsorted\n this.x = r.x || r.left || 0\n this.y = r.y || r.top || 0\n this._ix = 0\n this._iy = 0\n this.w = r.w || r.width || r.right - r.left\n this.h = r.h || r.height || r.bottom - r.top\n }\n\n get area() {\n return this.w * this.h\n }\n\n get iw() {\n return this.w - this._ix\n }\n\n get ih() {\n return this.h - this._iy\n }\n\n get dir() {\n const ih = this.ih\n return ih <= this.iw && ih > 0 ? 'y' : 'x'\n }\n\n get side() {\n return this.dir === 'x' ? this.iw : this.ih\n }\n\n map(arr: any) {\n const { dir, side } = this\n const key = dir === 'x' ? '_ix' : '_iy'\n const sum = arr.nsum\n const row = arr.get()\n const w2 = side * side\n const s2 = sum * sum\n let maxd2 = 0\n let totd1 = 0\n for (const itm of row) {\n const dims = getDims(itm, w2, s2, key)\n totd1 += dims.d1\n maxd2 = Math.max(maxd2, dims.d2)\n assignRow(this, itm, dims, arr.sum)\n this[key] += dims.d1\n }\n\n this[dir === 'x' ? '_iy' : '_ix'] += maxd2\n this[key] -= totd1\n }\n}\n","const min = Math.min\nconst max = Math.max\n\nfunction getStat(sa: StatArray) {\n return {\n max: sa.max,\n min: sa.min,\n nmax: sa.nmax,\n nmin: sa.nmin,\n nsum: sa.nsum,\n sum: sa.sum,\n }\n}\n\nfunction getNewStat(sa: StatArray, o: any) {\n const v = +o[sa.key]\n const n = v * sa.ratio\n o._normalized = n\n\n return {\n max: max(sa.max, v),\n min: min(sa.min, v),\n nmax: max(sa.nmax, n),\n nmin: min(sa.nmin, n),\n nsum: sa.nsum + n,\n sum: sa.sum + v,\n }\n}\n\nfunction setStat(sa: StatArray, stat: any) {\n Object.assign(sa, stat)\n}\n\nfunction push(sa: StatArray, o: any, stat: any) {\n sa._arr.push(o)\n setStat(sa, stat)\n}\n\nexport default class StatArray {\n key: string\n ratio: number\n _arr: any[] = []\n _hist: any[] = []\n sum = 0\n nsum = 0\n min = Infinity\n max = -Infinity\n nmin = Infinity\n nmax = -Infinity\n\n constructor(key: string, ratio: number) {\n this.key = key\n this.ratio = ratio\n this.reset()\n }\n\n get length() {\n return this._arr.length\n }\n\n reset() {\n this._arr = []\n this._hist = []\n this.sum = 0\n this.nsum = 0\n this.min = Infinity\n this.max = -Infinity\n this.nmin = Infinity\n this.nmax = -Infinity\n }\n\n push(o: any) {\n push(this, o, getNewStat(this, o))\n }\n\n pushIf(o: any, fn: any, ...args: any[]) {\n const nstat = getNewStat(this, o)\n if (!fn(getStat(this), nstat, args)) {\n return o\n }\n push(this, o, nstat)\n }\n\n get() {\n return this._arr\n }\n}\n","import type { AnyObject } from './types'\n\nimport { isObject } from 'chart.js/helpers'\n\nconst isOlderPart = (act: string, req: string) =>\n req > act || (act.length > req.length && act.startsWith(req))\n\nexport const getGroupKey = (lvl: unknown) => String(lvl)\n\nconst hasGroupValue = (value: unknown) => value !== undefined && value !== null && value !== ''\n\nfunction scanTreeObject(\n keys: string[],\n leafKey: string,\n obj: Record<string, any>,\n tree: string[] = [],\n lvl = 0,\n result: Record<string, any>[] = []\n) {\n const objIndex = lvl - 1\n if (keys[0] in obj && lvl > 0) {\n const record = tree.reduce<Record<string, any>>((reduced, item, i) => {\n if (i !== objIndex) {\n reduced[getGroupKey(i)] = item\n }\n return reduced\n }, {})\n record[leafKey] = tree[objIndex]\n keys.forEach((k) => {\n record[k] = obj[k]\n })\n result.push(record)\n } else {\n for (const childKey of Object.keys(obj)) {\n const child = obj[childKey]\n if (isObject(child)) {\n tree.push(childKey)\n scanTreeObject(keys, leafKey, child, tree, lvl + 1, result)\n }\n }\n }\n tree.splice(objIndex, 1)\n return result\n}\n\n/**\n * Flattens a nested object into the array form of `data`.\n *\n * The controller does this at runtime, so JavaScript configurations never need\n * it. TypeScript users who would rather pass an array than a generic can call\n * it up front.\n */\nexport function flattenTree<T = AnyObject>(tree: AnyObject, keys: string[], leafKey: string): T[] {\n return normalizeTreeToArray(keys, leafKey, tree) as T[]\n}\n\nexport function normalizeTreeToArray(keys: string[], leafKey: string, obj: Record<string, any>) {\n const data = scanTreeObject(keys, leafKey, obj)\n if (!data.length) {\n return data\n }\n const max = data.reduce((maxVal, element) => {\n // minus 2 because _leaf and value properties are added\n // on top to groups ones\n const ikeys = Object.keys(element).length - 2\n return Math.max(maxVal, ikeys)\n }, 0)\n data.forEach((element) => {\n for (let i = 0; i < max; i++) {\n const groupKey = getGroupKey(i)\n if (!element[groupKey]) {\n element[groupKey] = ''\n }\n }\n })\n return data\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat\nexport function flatten(input: any[]) {\n const stack = [...input]\n const res = []\n while (stack.length) {\n // pop value from stack\n const next = stack.pop()\n if (Array.isArray(next)) {\n // push back array items, won't modify the original input\n stack.push(...next)\n } else {\n res.push(next)\n }\n }\n // reverse to restore input order\n return res.reverse()\n}\n\nfunction getPath(groups: string[], value: Record<string, any>, defaultValue: string) {\n const path = []\n for (const grp of groups) {\n const item = value[grp]\n if (!hasGroupValue(item)) {\n continue\n }\n path.push(item)\n }\n return path.length ? path.join('.') : defaultValue\n}\n\nfunction resolveGroup(\n value: Record<string, any>,\n leafKey: string,\n allGroups: string[],\n groupIndex: number\n) {\n for (let idx = groupIndex; idx < allGroups.length; idx++) {\n const groupKey = getGroupKey(allGroups[idx])\n if (hasGroupValue(value[groupKey])) {\n return { group: groupKey, groupIndex: idx, value: value[groupKey] }\n }\n }\n if (hasGroupValue(value[leafKey])) {\n return { group: leafKey, groupIndex, value: value[leafKey] }\n }\n return undefined\n}\n\nfunction ensureGroup(\n tmp: Record<string, any>,\n data: Record<string, any[]>,\n groupValue: string,\n addKeys: string[]\n) {\n if (groupValue in tmp) {\n return\n }\n tmp[groupValue] = { value: 0 }\n const tmpRef = tmp[groupValue]\n addKeys.forEach((k) => {\n tmpRef[k] = 0\n })\n data[groupValue] = []\n}\n\nexport function group(\n values: Record<string, any>[],\n grp: string,\n keys: string[],\n leafKey: string,\n mainGrp?: string,\n mainValue?: any,\n groups: string[] = [],\n allGroups: string[] = groups,\n groupIndex = groups.length - 1\n) {\n const key = keys[0]\n const addKeys = keys.slice(1)\n const tmp: Record<string, any> = Object.create(null)\n const data: Record<string, any[]> = Object.create(null)\n const ret: Record<string, any>[] = []\n const resolvedAllGroups = allGroups.length ? allGroups : [grp]\n const resolvedGroupIndex = allGroups.length ? groupIndex : 0\n let i: number\n let n: number\n for (i = 0, n = values.length; i < n; ++i) {\n const v = values[i]\n if (mainGrp && v[mainGrp] !== mainValue) {\n continue\n }\n const itemGroup = resolveGroup(v, leafKey, resolvedAllGroups, resolvedGroupIndex)\n if (!itemGroup) {\n return []\n }\n const g = itemGroup.value\n ensureGroup(tmp, data, g, addKeys)\n tmp[g].value += +v[key]\n tmp[g].label = g\n tmp[g].group = itemGroup.group\n tmp[g].groupIndex = itemGroup.groupIndex\n const tmpRef = tmp[g]\n addKeys.forEach((k) => {\n tmpRef[k] += v[k]\n })\n tmp[g].path = getPath(resolvedAllGroups.slice(0, itemGroup.groupIndex + 1), v, g)\n data[g].push(v)\n }\n\n Object.keys(tmp).forEach((k) => {\n const v: Record<string, any> = { children: data[k] }\n v[key] = +tmp[k].value\n addKeys.forEach((ak) => {\n v[ak] = +tmp[k][ak]\n })\n v[grp] = tmp[k].label\n v.group = tmp[k].group\n v.groupIndex = tmp[k].groupIndex\n v.label = k\n v.path = tmp[k].path\n\n if (mainGrp) {\n v[mainGrp] = mainValue\n }\n ret.push(v)\n })\n\n return ret\n}\n\nexport function index(values: any[], key: string) {\n let n = values.length\n let i: number\n\n if (!n) {\n return key\n }\n\n const obj = isObject(values[0])\n key = obj ? key : 'v'\n\n for (i = 0, n = values.length; i < n; ++i) {\n if (obj) {\n values[i]._idx = i\n } else {\n values[i] = { _idx: i, v: values[i] }\n }\n }\n return key\n}\n\nexport function sort(values: any[], key?: string) {\n if (key) {\n values.sort((a, b) => +b[key] - +a[key])\n } else {\n values.sort((a, b) => +b - +a)\n }\n}\n\nexport function sum(values: any[], key?: string) {\n let s: number\n let i: number\n let n: number\n\n for (s = 0, i = 0, n = values.length; i < n; ++i) {\n s += key ? +values[i][key] : +values[i]\n }\n\n return s\n}\n\nexport function requireVersion(pkg: string, min: string, ver: string, strict = true) {\n const parts = ver.split('.')\n let i = 0\n for (const req of min.split('.')) {\n const act = parts[i++]\n if (Number.parseInt(req, 10) < Number.parseInt(act, 10)) {\n break\n }\n if (isOlderPart(act, req)) {\n if (strict) {\n throw new Error(`${pkg} v${ver} is not supported. v${min} or newer is required.`)\n } else {\n return false\n }\n }\n }\n return true\n}\n","import Rect from './rect'\nimport StatArray from './statArray'\nimport { index, sort, sum } from './utils'\n\nfunction compareAspectRatio(oldStat: any, newStat: any, args: any[]) {\n if (oldStat.sum === 0) {\n return true\n }\n\n const [length] = args\n const os2 = oldStat.nsum * oldStat.nsum\n const ns2 = newStat.nsum * newStat.nsum\n const l2 = length * length\n const or = Math.max((l2 * oldStat.nmax) / os2, os2 / (l2 * oldStat.nmin))\n const nr = Math.max((l2 * newStat.nmax) / ns2, ns2 / (l2 * newStat.nmin))\n return nr <= or\n}\n\n/**\n * Builds the nodes for one set of siblings, without any geometry.\n *\n * Everything here depends only on the data: which item a node came from, its\n * value, its group and level. The rectangle is not involved, which is what lets\n * the controller know how many elements it needs before the chart area is known.\n */\nexport function toNodes(values: any[], keys: string[], grp?: string, lvl?: number) {\n const items = values ? values.slice() : []\n const key = index(items, keys[0])\n\n return items.map((item: any) => {\n const node: any = {\n _data: values[item._idx],\n v: key ? +item[key] : +item,\n vs: undefined,\n }\n if (grp) {\n node.g = item[grp]\n node.gs = undefined\n node.l = item.groupIndex ?? lvl\n node.vs = keys.reduce<Record<string, number>>((obj, k) => {\n obj[k] = +item[k]\n return obj\n }, {})\n }\n return node\n })\n}\n\n/** Orders a set of siblings the way the layout draws them: largest first. */\nexport function sortNodes(nodes: any[]) {\n sort(nodes, 'v')\n}\n\n/**\n * Packs already-ordered nodes into the rectangle, writing `x`, `y`, `w`, `h`,\n * the row sum `s` and the normalized area `a` onto them.\n */\nexport function packInto(nodes: any[], rectangle: any) {\n const n = nodes.length\n if (!n) {\n return\n }\n const rect = new Rect(rectangle)\n const row = new StatArray('v', rect.area / sum(nodes, 'v'))\n let length = rect.side\n let o: any\n\n for (let i = 0; i < n; ++i) {\n o = row.pushIf(nodes[i], compareAspectRatio, length)\n if (o) {\n rect.map(row)\n length = rect.side\n row.reset()\n row.push(o)\n }\n }\n if (row.length) {\n rect.map(row)\n }\n}\n\nexport default function squarify(\n values: any[],\n rectangle: any,\n keys: string[] = [],\n grp?: string,\n lvl?: number,\n gsum?: number\n) {\n const nodes = toNodes(values || [], keys, grp, lvl)\n if (grp) {\n for (const node of nodes) {\n node.gs = gsum\n }\n }\n if (!rectangle?.unsorted) {\n sortNodes(nodes)\n }\n packInto(nodes, rectangle)\n return nodes\n}\n","import type { Color, Element } from 'chart.js'\nimport type { DrawRect } from './geometry'\nimport type {\n TreemapCaptionsOptions,\n TreemapConfig,\n TreemapDataPoint,\n TreemapDisplayMode,\n TreemapLabelsOptions,\n TreemapLayoutOptions,\n TreemapOptions,\n TreemapScriptableContext,\n} from './types'\n\nimport { defined, isArray, isNumber, toFont, valueOrDefault } from 'chart.js/helpers'\n\ntype RectSize = {\n h: number\n w: number\n}\n\ntype RectHeight = {\n h: number\n}\n\ntype LabelSize = {\n height: number\n width: number\n}\n\ntype Font = ReturnType<typeof toFont>\n\ntype TextElement = Element<TreemapConfig, TreemapOptions> & {\n $context?: TreemapScriptableContext\n}\n\n/**\n * One block of text ready to draw: the lines, the styles they are drawn with,\n * and where the block's top edge sits. Captions and labels differ only in how\n * they arrive at this, which is why they can share the drawing code.\n */\ntype TextBlock = {\n align: CanvasTextAlign\n /** Vertical clip inset. Zero where the box was sized to hold the text. */\n clipY: number\n colors: Color[]\n fonts: Font[]\n lines: string[]\n padding: number\n top: number\n}\n\nconst widthCache = new Map<string, LabelSize>()\n\nexport function shouldDrawCaption(\n displayMode: TreemapDisplayMode,\n rect: RectSize,\n options?: Partial<TreemapCaptionsOptions>\n) {\n if (!options || options.display === false) {\n return false\n }\n if (displayMode === 'headerBoxes') {\n return true\n }\n const { w, h } = rect\n const font = toFont(options.font || {})\n const min = font.lineHeight\n const padding = Math.max(Math.min(valueOrDefault(options.padding, 3) * 2, Math.min(w, h)), 0)\n return w - padding > min && h - padding > min\n}\n\nexport function getCaptionHeight(\n displayMode: TreemapDisplayMode,\n rect: RectHeight,\n font: { lineHeight: number },\n padding: number\n) {\n if (displayMode !== 'headerBoxes') {\n return font.lineHeight + padding * 2\n }\n const captionHeight = font.lineHeight + padding * 2\n return rect.h < 2 * captionHeight ? rect.h / 3 : captionHeight\n}\n\nexport function drawText(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n options: TreemapOptions,\n item: TreemapDataPoint,\n element: TextElement,\n layout: TreemapLayoutOptions\n) {\n const { captions, labels } = options\n const { displayMode } = layout\n const isLeaf = item && (!defined(item.l) || item.isLeaf)\n\n // Resolve the text before touching the canvas. Most elements in a large\n // treemap draw no text at all, and clipping is not free: this is the\n // difference between five canvas calls per element and none.\n let block: TextBlock | undefined\n if (isLeaf) {\n if (labels.display) {\n block = labelBlock(ctx, rect, options, item, element)\n }\n } else if (shouldDrawCaption(displayMode, rect, captions)) {\n block = captionBlock(ctx, rect, options, item, element, layout)\n }\n if (!block) {\n return\n }\n\n ctx.save()\n clipToPadding(ctx, rect, block.padding, block.clipY)\n drawTextBlock(ctx, rect, block)\n ctx.restore()\n}\n\n/**\n * Text is clipped at the padding, not at the element's border (#135).\n * `overflow: 'cut'` used to run into the padding region, which made the padding\n * mean one thing for placement and nothing for clipping.\n *\n * The vertical inset is separate because a headerBoxes caption sits in a strip\n * whose height was derived from that caption's own line height. There is no\n * vertical overflow to prevent there, and insetting would slice the glyphs of\n * any font whose ascender and descender exceed its line height.\n */\nfunction clipToPadding(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n padding: number,\n clipY: number\n) {\n const x = Math.max(0, padding)\n const y = Math.max(0, clipY)\n ctx.beginPath()\n ctx.rect(rect.x + x, rect.y + y, Math.max(0, rect.w - 2 * x), Math.max(0, rect.h - 2 * y))\n ctx.clip()\n}\n\nfunction drawTextBlock(ctx: CanvasRenderingContext2D, rect: DrawRect, block: TextBlock) {\n const { align, colors, fonts, lines, padding, top } = block\n const x = calculateX(rect, align, padding)\n ctx.textAlign = align\n ctx.textBaseline = 'middle'\n let offset = 0\n lines.forEach((line, i) => {\n const font = fonts[Math.min(i, fonts.length - 1)]\n ctx.font = font.string\n ctx.fillStyle = colors[Math.min(i, colors.length - 1)]\n ctx.fillText(line, x, top + offset + font.lineHeight / 2)\n offset += font.lineHeight\n })\n}\n\nfunction callbackContext(element: TextElement, item: TreemapDataPoint): TreemapScriptableContext {\n const context =\n element.$context ||\n ({ active: !!element.active, raw: item, type: 'data' } as TreemapScriptableContext)\n context.active = !!element.active\n context.raw = item\n return context\n}\n\nfunction resolveOption<T>(\n option: T | ((context: TreemapScriptableContext) => T) | undefined,\n context: TreemapScriptableContext\n) {\n return typeof option === 'function'\n ? (option as (context: TreemapScriptableContext) => T)(context)\n : option\n}\n\nfunction resolveCaptionText(\n captions: TreemapCaptionsOptions,\n element: TextElement,\n item: TreemapDataPoint\n) {\n return resolveOption(captions.formatter, callbackContext(element, item)) || item.g || ''\n}\n\n/** The caption's text, truncated with an ellipsis when it does not fit. */\nfunction captionText(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n captions: TreemapCaptionsOptions,\n element: TextElement,\n item: TreemapDataPoint,\n fonts: Font[]\n) {\n const text = resolveCaptionText(captions, element, item)\n if (!text) {\n return undefined\n }\n const padding = captions.padding\n if (measureLabelSize(ctx, [text], fonts).width + 2 * padding > rect.w) {\n return sliceTextToFitWidth(ctx, text, rect.w - 2 * padding, fonts)\n }\n return text\n}\n\nfunction captionBlock(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n options: TreemapOptions,\n item: TreemapDataPoint,\n element: TextElement,\n layout: TreemapLayoutOptions\n): TextBlock | undefined {\n const { displayMode, rtl, spacing } = layout\n const { captions } = options\n const { color, hoverColor, font, hoverFont, padding, align } = captions\n const optFont = (rect.active ? hoverFont : font) || font\n const oFont = toFont(optFont)\n if (oFont.lineHeight > rect.h) {\n return\n }\n const text = captionText(ctx, rect, captions, element, item, [oFont])\n if (text === undefined) {\n return\n }\n const fonts = [oFont]\n // A caption is a single line, centred in the header strip in headerBoxes mode\n // and sitting under the top padding otherwise.\n const top =\n displayMode === 'headerBoxes'\n ? rect.y + (rect.h - oFont.lineHeight) / 2\n : rect.y + padding + spacing\n return {\n align: align || (rtl ? 'right' : 'left'),\n clipY: displayMode === 'headerBoxes' ? 0 : padding,\n colors: [(rect.active ? hoverColor : color) || color],\n fonts,\n lines: [text],\n padding,\n top,\n }\n}\n\nfunction labelBlock(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n options: TreemapOptions,\n item: TreemapDataPoint,\n element: TextElement\n): TextBlock | undefined {\n const labels = options.labels\n const content = resolveOption(labels.formatter, callbackContext(element, item))\n if (!content) {\n return\n }\n const lines = isArray(content) ? content : [content]\n let fonts = getFontFromOptions(rect, labels)\n let labelSize = measureLabelSize(ctx, lines, fonts)\n const lblToDraw = labelToDraw(rect, labels, labelSize)\n if (!lblToDraw) {\n return\n }\n if (isNumber(lblToDraw)) {\n labelSize = { height: labelSize.height * lblToDraw, width: labelSize.width * lblToDraw }\n fonts = toFonts(fonts, lblToDraw)\n }\n const { color, hoverColor, align, padding } = labels\n const optColor = (rect.active ? hoverColor : color) || color\n return {\n align,\n clipY: padding,\n colors: isArray(optColor) ? optColor : [optColor],\n fonts,\n lines,\n padding,\n top: calculateBlockTop(rect, labels, labelSize),\n }\n}\n\nfunction sliceTextToFitWidth(\n ctx: CanvasRenderingContext2D,\n text: string,\n width: number,\n fonts: Font[]\n) {\n const ellipsis = '...'\n const ellipsisWidth = measureLabelSize(ctx, [ellipsis], fonts).width\n if (ellipsisWidth >= width) {\n return ''\n }\n let lowerBoundLen = 1\n let upperBoundLen = text.length\n let currentWidth: number\n while (lowerBoundLen <= upperBoundLen) {\n const currentLen = Math.floor((lowerBoundLen + upperBoundLen) / 2)\n const currentText = text.slice(0, currentLen)\n currentWidth = measureLabelSize(ctx, [currentText], fonts).width\n if (currentWidth + ellipsisWidth > width) {\n upperBoundLen = currentLen - 1\n } else {\n lowerBoundLen = currentLen + 1\n }\n }\n const slicedText = text.slice(0, Math.max(0, lowerBoundLen - 1))\n return slicedText ? slicedText + ellipsis : ''\n}\n\nfunction measureLabelSize(\n ctx: CanvasRenderingContext2D & { _measureText?: unknown },\n lines: string[],\n fonts: Font[]\n) {\n const fontsKey = fonts.reduce((prev, item) => {\n prev += item.string\n return prev\n }, '')\n const mapKey = lines.join() + fontsKey + (ctx._measureText ? '-spriting' : '')\n let size = widthCache.get(mapKey)\n if (!size) {\n ctx.save()\n const count = lines.length\n let width = 0\n let height = 0\n for (let i = 0; i < count; i++) {\n const font = fonts[Math.min(i, fonts.length - 1)]\n ctx.font = font.string\n const text = lines[i]\n width = Math.max(width, ctx.measureText(text).width)\n height += font.lineHeight\n }\n ctx.restore()\n size = { height, width }\n widthCache.set(mapKey, size)\n }\n return size\n}\n\nfunction toFonts(fonts: Font[], fitRatio: number) {\n return fonts.map((f) => {\n const { lineHeight: _lineHeight, ...font } = f\n return toFont({ ...font, size: Math.floor(f.size * fitRatio) })\n })\n}\n\nfunction labelToDraw(rect: DrawRect, options: TreemapLabelsOptions, labelSize: LabelSize) {\n const { overflow, padding } = options\n const { width, height } = labelSize\n if (overflow === 'hidden') {\n return !(width + padding * 2 > rect.w || height + padding * 2 > rect.h)\n } else if (overflow === 'fit') {\n const ratio = Math.min(rect.w / (width + padding * 2), rect.h / (height + padding * 2))\n if (ratio < 1) {\n return ratio\n }\n }\n return true\n}\n\nfunction getFontFromOptions(rect: DrawRect, labels: TreemapLabelsOptions) {\n const { font, hoverFont } = labels\n const optFont = (rect.active ? hoverFont : font) || font\n return Array.isArray(optFont) ? optFont.map((f) => toFont(f)) : [toFont(optFont)]\n}\n\nfunction calculateBlockTop(rect: DrawRect, options: TreemapLabelsOptions, labelSize: LabelSize) {\n const { position, padding } = options\n if (position === 'top') {\n return rect.y + padding\n }\n if (position === 'bottom') {\n return rect.y + rect.h - padding - labelSize.height\n }\n return rect.y + (rect.h - labelSize.height) / 2 + padding\n}\n\nfunction calculateX(rect: DrawRect, align: CanvasTextAlign, padding: number) {\n if (align === 'left') {\n return rect.x + padding\n } else if (align === 'right') {\n return rect.x + rect.w - padding\n }\n return rect.x + rect.w / 2\n}\n","import type { DrawRect } from './geometry'\nimport type { TreemapDataPoint, TreemapDisplayMode } from './types'\n\nimport { isObject, toFont, valueOrDefault } from 'chart.js/helpers'\n\nimport { parseBorderWidth } from './options'\nimport { packInto, sortNodes, toNodes } from './squarify'\nimport { getCaptionHeight, shouldDrawCaption } from './text'\nimport { getGroupKey, group, normalizeTreeToArray } from './utils'\n\nexport type LayoutOptions = {\n borderWidth: any\n captions: any\n displayMode: TreemapDisplayMode\n groups: any[]\n leafKey: string\n spacing: number\n unsorted: boolean\n}\n\n/** A node while the layout is being built; `_children` is dropped before use. */\nexport type LayoutNode = TreemapDataPoint & { _children?: LayoutNode[] }\n\n/**\n * Pass one: the hierarchy.\n *\n * Groups the items level by level and orders each set of siblings. Nothing here\n * depends on the chart area, so the number of nodes and their order are known\n * before the layout has a rectangle to fill.\n */\nfunction buildHierarchy(\n values: any[],\n gidx: number,\n keys: string[],\n layout: LayoutOptions,\n parentGroupValue?: string\n): LayoutNode[] {\n const { groups, leafKey, unsorted } = layout\n const glen = groups.length\n const g = getGroupKey(groups[gidx])\n const gdata = group(\n values,\n g,\n keys,\n leafKey,\n undefined,\n parentGroupValue,\n groups.filter((_item: any, index: number) => index <= gidx),\n groups,\n gidx\n )\n const nodes = toNodes(gdata, keys, g, gidx) as LayoutNode[]\n if (!unsorted) {\n sortNodes(nodes)\n }\n\n for (const node of nodes) {\n const record = node._data as any\n const nextGroupIndex = record.groupIndex + 1\n const children =\n gidx < glen - 1 && nextGroupIndex < glen\n ? buildHierarchy(record.children, nextGroupIndex, keys, layout, node.g)\n : []\n // Non-enumerable: the geometry pass needs it on every layout, but it\n // must not show up in ctx.raw.\n Object.defineProperty(node, '_children', {\n configurable: true,\n value: children,\n writable: true,\n })\n node.isLeaf = !children.length\n }\n return nodes\n}\n\n/** Draw order: a set of siblings, then the descendants of each in turn. */\nexport function flattenNodes(nodes: LayoutNode[]): LayoutNode[] {\n const flat = nodes.slice()\n for (const node of nodes) {\n if (node._children?.length) {\n flat.push(...flattenNodes(node._children))\n }\n }\n return flat\n}\n\n/**\n * Pass two: the geometry.\n *\n * Packs each set of siblings into its parent's rectangle, writing the\n * coordinates onto the nodes the first pass produced.\n */\nfunction layoutLevel(nodes: LayoutNode[], rect: any, layout: LayoutOptions, parentSum?: number) {\n if (parentSum !== undefined) {\n for (const node of nodes) {\n node.gs = parentSum\n }\n }\n packInto(nodes, rect)\n\n for (const node of nodes) {\n if (node._children?.length) {\n layoutLevel(node._children, getSubRect(node, rect, layout), layout, node.s)\n }\n }\n}\n\n/** Writes the geometry for a whole tree of nodes, then applies headerBoxes. */\nexport function layoutNodes(nodes: LayoutNode[], rect: any, layout: LayoutOptions) {\n layoutLevel(nodes, rect, layout)\n applyHeaderBoxes(flattenNodes(nodes), layout)\n}\n\n/** The rectangle left for a group's children once its border and caption are taken. */\nfunction getSubRect(sq: any, rect: any, layout: LayoutOptions) {\n const { borderWidth, captions, displayMode } = layout\n const sp = displayMode === 'headerBoxes' ? 0 : layout.spacing\n const bw =\n displayMode === 'headerBoxes'\n ? { b: 0, l: 0, r: 0, t: 0 }\n : parseBorderWidth(borderWidth, sq.w / 2, sq.h / 2)\n const subRect = {\n ...rect,\n h: sq.h - 2 * sp - bw.t - bw.b,\n w: sq.w - 2 * sp - bw.l - bw.r,\n x: sq.x + sp + bw.l,\n y: sq.y + sp + bw.t,\n }\n if (shouldDrawCaption(displayMode, subRect, captions)) {\n const captionHeight = getCaptionHeight(\n displayMode,\n subRect,\n toFont(captions.font),\n valueOrDefault(captions.padding, 3)\n )\n subRect.y += captionHeight\n subRect.h -= captionHeight\n }\n return subRect\n}\n\n/**\n * The hierarchy pass on its own: the nested nodes, in draw order, with no\n * geometry. Takes no rectangle, which is the whole point - the controller needs\n * the node count before the chart area is known.\n */\nexport function buildNodes(tree: any, keys: string[], layout: LayoutOptions): LayoutNode[] {\n const { groups, leafKey, unsorted } = layout\n const input = isObject(tree) ? normalizeTreeToArray(keys, leafKey, tree) : tree\n\n if (groups.length) {\n return buildHierarchy(input, 0, keys, layout)\n }\n const nodes = toNodes(input || [], keys) as LayoutNode[]\n if (!unsorted) {\n sortNodes(nodes)\n }\n return nodes\n}\n\n/**\n * In headerBoxes mode a group is drawn as a header strip rather than a box\n * around its children, and a group whose caption does not fit is not drawn at\n * all. It is marked hidden rather than removed: the number of parsed nodes must\n * not depend on the size of the chart area.\n */\nfunction applyHeaderBoxes(nodes: LayoutNode[], layout: LayoutOptions) {\n const { captions, displayMode } = layout\n if (displayMode !== 'headerBoxes') {\n return\n }\n const font = toFont(captions.font)\n const padding = valueOrDefault(captions.padding, 3)\n for (const node of nodes) {\n if (node.isLeaf) {\n continue\n }\n if (shouldDrawCaption(displayMode, node, captions)) {\n node.h = getCaptionHeight(displayMode, node, font, padding)\n node.hidden = false\n } else {\n node.hidden = true\n }\n }\n}\n\n/** Turns the user's input into the flat list of rectangles the chart draws. */\nexport function buildData(\n tree: any,\n keys: string[],\n mainRect: DrawRect,\n layout: LayoutOptions\n): TreemapDataPoint[] {\n const nodes = buildNodes(tree, keys, layout)\n layoutNodes(nodes, mainRect, layout)\n return flattenNodes(nodes)\n}\n","import type { LayoutNode, LayoutOptions } from './layout'\n\nimport { Chart, DatasetController, registry } from 'chart.js'\nimport { clipArea, unclipArea, valueOrDefault } from 'chart.js/helpers'\n\nimport { version } from '../package.json'\nimport { rectNotEqual, scaleRect } from './helpers/index'\nimport { buildNodes, flattenNodes, layoutNodes } from './layout'\nimport { layoutDefaults } from './options'\nimport { requireVersion } from './utils'\n\nfunction registerTooltipPositioner() {\n const tooltipPlugin = registry.plugins.get('tooltip') as any\n if (!tooltipPlugin || tooltipPlugin.positioners.treemap) {\n return\n }\n tooltipPlugin.positioners.treemap = (active: any[]) => {\n if (!active.length) {\n return false\n }\n\n const item = active.at(-1)\n return item.element.tooltipPosition()\n }\n}\n\nexport default class TreemapController extends DatasetController {\n declare static readonly id: string\n declare static readonly defaults: Record<string, unknown>\n declare static readonly descriptors: Record<string, unknown>\n declare static readonly overrides: Record<string, unknown>\n declare static readonly beforeRegister: () => void\n declare static readonly afterRegister: () => void\n declare static readonly afterUnregister: () => void\n\n // Chart.js assigns this on the class when the controller is registered; its\n // type definitions do not describe it.\n declare dataElementType: new () => any\n\n options: any\n _rect: any\n _rectChanged: boolean\n _nodes: LayoutNode[]\n _layoutDirty: boolean\n _fingerprint: string | undefined\n\n constructor(chart: any, datasetIndex: number) {\n super(chart, datasetIndex)\n\n this._rect = undefined\n this._rectChanged = true\n this._nodes = []\n this._layoutDirty = true\n this._fingerprint = undefined\n }\n\n override initialize() {\n // The tooltip can be registered after the treemap controller. At chart creation time all\n // components are available, so retry here to make registration order irrelevant.\n registerTooltipPositioner()\n this.enableOptionSharing = true\n super.initialize()\n }\n\n override getMinMax(scale: any) {\n return {\n max: scale.axis === 'x' ? scale.right - scale.left : scale.bottom - scale.top,\n min: 0,\n }\n }\n\n override configure() {\n super.configure()\n const { xScale, yScale } = this.getMeta() as any\n if (!xScale || !yScale) {\n // configure is called once before `linkScales`, and at that call we don't have any scales linked yet\n return\n }\n\n const w = xScale.right - xScale.left\n const h = yScale.bottom - yScale.top\n const rect = { h, rtl: !!this.options.rtl, unsorted: !!this.options.unsorted, w, x: 0, y: 0 }\n\n if (rectNotEqual(this._rect, rect)) {\n this._rect = rect\n this._rectChanged = true\n }\n\n if (this._rectChanged) {\n xScale.max = w\n xScale.configure()\n yScale.max = h\n yScale.configure()\n }\n }\n\n /**\n * Options that shape the layout rather than a single rectangle, resolved once\n * per dataset. Reading them from `this.options` rather than from the raw\n * dataset is what makes `options.datasets.treemap` work for all of them.\n */\n _layoutOptions(): LayoutOptions {\n const dataset = this.getDataset() as any\n const options = this.options\n return {\n // Still raw: resolving these with the dataset context is feature 2's\n // change, and doing it here would move pixels in this refactor.\n borderWidth: dataset.borderWidth,\n captions: dataset.captions || {},\n displayMode: options.displayMode,\n groups: options.groups || [],\n leafKey: options.leafKey,\n // Deliberately NOT options.spacing. The child rectangle calculation has\n // always defaulted spacing to 0 while the drawn rectangle defaults it to\n // 0.5, so reading the resolved value here would inset every nested group\n // by an extra 0.5 and move 11 fixtures. Unifying the two is a visual\n // change that deserves its own pull request.\n spacing: valueOrDefault(dataset.spacing, 0),\n unsorted: !!options.unsorted,\n }\n }\n\n /**\n * Chart.js calls this before `configure()`, so the chart area is not\n * available here - see the hierarchy pass in `./layout`, which does not need\n * one. Elements are created from the parsed nodes rather than from\n * `dataset.data`, because a treemap with groups has more rectangles than the\n * user supplied rows.\n */\n override buildOrUpdateElements(_resetNewElements?: boolean) {\n this.parse(0, 0)\n\n const meta = this.getMeta() as any\n const count = (meta._parsed as unknown[]).length\n const elements = meta.data as unknown[]\n if (elements.length > count) {\n elements.splice(count, elements.length - count)\n }\n while (elements.length < count) {\n elements.push(new this.dataElementType())\n }\n }\n\n override parse(_start: number, _count: number) {\n const dataset = this.getDataset() as any\n if (dataset.tree !== undefined) {\n throw new Error(\n 'chartjs-chart-treemap v5: the \"tree\" option was renamed to \"data\". ' +\n 'See https://chartjs-chart-treemap.pages.dev/usage/'\n )\n }\n\n const options = this.options\n const keys = [options.key || ''].concat(options.sumKeys || [])\n const nodes = buildNodes(dataset.data || [], keys, this._layoutOptions())\n const flat = flattenNodes(nodes)\n\n // A `chart.update('none')` per wheel event must not re-run the layout when\n // nothing about the data changed, so keep the previous nodes - and with\n // them their geometry - when the hierarchy is identical.\n const fingerprint = flat.map((node) => `${node.v}\\u0000${node.g}\\u0000${node.l}`).join('\\u0001')\n if (this._fingerprint === fingerprint) {\n return\n }\n\n this._fingerprint = fingerprint\n this._nodes = nodes\n ;(this.getMeta() as any)._parsed = flat\n this._layoutDirty = true\n }\n\n // `getContext` exists on DatasetController at runtime but not in its type\n // definitions, so this cannot be declared as an override.\n getContext(index: number, active?: boolean, mode?: string) {\n const base = (DatasetController.prototype as any).getContext\n const context = base.call(this, index, active, mode)\n const parsed = typeof index === 'number' ? this.getParsed(index) : undefined\n if (parsed) {\n context.raw = parsed\n context.parsed = parsed\n }\n return context\n }\n\n override getLabelAndValue(index: number) {\n const node = this.getParsed(index) as any\n if (!node) {\n return { label: '', value: '' }\n }\n const dataset = this.getDataset() as any\n const label = node.g ?? node._data?.label ?? dataset.label\n return { label: label === undefined ? '' : `${label}`, value: `${node.v}` }\n }\n\n override update(mode: any) {\n const { data } = this.getMeta()\n\n if (mode === 'reset') {\n // reset is called before 2nd configure and is only called if animations are enabled. So wen need an extra configure call here.\n this.configure()\n }\n\n if (this._layoutDirty || this._rectChanged) {\n layoutNodes(this._nodes, this._rect, this._layoutOptions())\n this._layoutDirty = false\n this._rectChanged = false\n }\n\n this.updateElements(data, 0, data.length, mode)\n }\n\n override updateElements(rects: any[], start: number, count: number, mode: any) {\n const reset = mode === 'reset'\n const firstOpts = this.resolveDataElementOptions(start, mode)\n this._rect.options = firstOpts\n const sharedOptions = this.getSharedOptions(firstOpts)\n const includeOptions = this.includeOptions(mode, sharedOptions || {})\n const { xScale, yScale } = this.getMeta() as any\n const spacing = this.options.spacing\n\n for (let i = start; i < start + count; i++) {\n const options = sharedOptions || this.resolveDataElementOptions(i, mode)\n const node = this.getParsed(i) as any\n const properties: any = scaleRect(node, xScale, yScale, spacing)\n properties.hidden = properties.hidden || !!node.hidden\n if (reset) {\n properties.width = 0\n properties.height = 0\n }\n\n if (includeOptions) {\n properties.options = options\n }\n this.updateElement(rects[i], i, properties, mode)\n }\n\n this.updateSharedOptions(sharedOptions || {}, mode, firstOpts)\n }\n\n override draw() {\n const { ctx, chartArea } = this.chart\n const metadata = ((this.getMeta() as any).data || []) as any[]\n const { displayMode, rtl, spacing } = this.options\n const layout = { displayMode, rtl, spacing }\n\n clipArea(ctx, chartArea)\n for (let i = 0, ilen = metadata.length; i < ilen; ++i) {\n const rect = metadata[i]\n if (!rect.hidden) {\n rect.draw(ctx, this.getParsed(i) as any, layout)\n }\n }\n unclipArea(ctx)\n }\n}\n\n;(TreemapController as any).id = 'treemap'\n\n;(TreemapController as any).version = version\n\n;(TreemapController as any).defaults = {\n animations: {\n numbers: {\n properties: ['x', 'y', 'width', 'height'],\n type: 'number',\n },\n },\n dataElementType: 'treemap',\n displayMode: layoutDefaults.displayMode,\n groups: [],\n key: '',\n leafKey: '_leaf',\n rtl: layoutDefaults.rtl,\n spacing: layoutDefaults.spacing,\n sumKeys: [],\n unsorted: false,\n}\n\n;(TreemapController as any).descriptors = {\n _indexable: false,\n _scriptable: true,\n captions: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n labels: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n}\n\n;(TreemapController as any).overrides = {\n hover: {},\n interaction: {\n includeInvisible: true,\n intersect: true,\n mode: 'point',\n },\n\n plugins: {\n tooltip: {\n callbacks: {\n label(item: any) {\n const node = item.parsed\n const label = node.g || node._data?.label || item.dataset.label\n return (label ? `${label}: ` : '') + node.v\n },\n title(items: any[]) {\n if (items.length) {\n const item = items[0]\n return item.dataset.key || ''\n }\n return ''\n },\n },\n intersect: true,\n position: 'treemap',\n },\n },\n scales: {\n x: {\n alignToPixels: true,\n bounds: 'data',\n display: false,\n type: 'linear',\n },\n y: {\n alignToPixels: true,\n bounds: 'data',\n display: false,\n reverse: true,\n type: 'linear',\n },\n },\n}\n\n;(TreemapController as any).beforeRegister = () => {\n requireVersion('chart.js', '4.0', Chart.version)\n}\n\n;(TreemapController as any).afterRegister = () => {\n registerTooltipPositioner()\n}\n\n;(TreemapController as any).afterUnregister = () => {\n const tooltipPlugin = registry.plugins.get('tooltip') as any\n if (tooltipPlugin) {\n delete tooltipPlugin.positioners.treemap\n }\n}\n","import type { Element } from 'chart.js'\nimport type { TreemapBorderRadius, TreemapConfig, TreemapOptions } from './types'\n\nimport { parseBorderRadius, parseBorderWidth } from './options'\n\nexport type DrawRect = {\n active?: boolean\n h: number\n radius: TreemapBorderRadius\n w: number\n x: number\n y: number\n}\n\ntype TreemapElementBase = Element<TreemapConfig, TreemapOptions>\n\nfunction getBounds(rect: TreemapElementBase, useFinalPosition?: boolean) {\n const { x, y, width, height } = rect.getProps(['x', 'y', 'width', 'height'], useFinalPosition)\n return { bottom: y + height, left: x, right: x + width, top: y }\n}\n\nexport function boundingRects(rect: TreemapElementBase) {\n const bounds = getBounds(rect)\n const width = bounds.right - bounds.left\n const height = bounds.bottom - bounds.top\n const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2)\n const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2)\n const outer = {\n active: rect.active,\n h: height,\n radius,\n w: width,\n x: bounds.left,\n y: bounds.top,\n }\n\n return {\n inner: {\n active: rect.active,\n h: outer.h - border.t - border.b,\n radius: {\n bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),\n bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)),\n topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),\n topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),\n },\n w: outer.w - border.l - border.r,\n x: outer.x + border.l,\n y: outer.y + border.t,\n },\n outer,\n }\n}\n\nexport function inRange(\n rect: TreemapElementBase,\n x: number | null,\n y: number | null,\n useFinalPosition?: boolean\n) {\n const skipX = x === null\n const skipY = y === null\n const bounds = !rect || (skipX && skipY) ? false : getBounds(rect, useFinalPosition)\n\n return (\n bounds &&\n (skipX || (x >= bounds.left && x <= bounds.right)) &&\n (skipY || (y >= bounds.top && y <= bounds.bottom))\n )\n}\n\nexport function hasRadius(radius: TreemapBorderRadius) {\n return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight\n}\n\nexport function addNormalRectPath(ctx: CanvasRenderingContext2D, rect: DrawRect) {\n ctx.rect(rect.x, rect.y, rect.w, rect.h)\n}\n","import type {\n TreemapConfig,\n TreemapDataPoint,\n TreemapLayoutOptions,\n TreemapOptions,\n TreemapScriptableContext,\n} from './types'\n\nimport { Element } from 'chart.js'\nimport { addRoundedRectPath } from 'chart.js/helpers'\n\nimport { addNormalRectPath, boundingRects, hasRadius, inRange } from './geometry'\nimport { layoutDefaults } from './options'\nimport { drawText } from './text'\n\nexport default class TreemapElement extends Element<TreemapConfig, TreemapOptions> {\n static readonly id = 'treemap'\n\n static override readonly defaults = {\n borderRadius: 0,\n borderWidth: 0,\n captions: {\n align: undefined,\n color: 'black',\n display: true,\n font: {},\n formatter: (ctx: TreemapScriptableContext) => {\n const label = ctx.raw._data?.label\n return ctx.raw.g || (typeof label === 'string' ? label : '')\n },\n padding: 3,\n },\n labels: {\n align: 'center',\n color: 'black',\n display: false,\n font: {},\n formatter(ctx: TreemapScriptableContext) {\n const label = ctx.raw._data?.label\n if (ctx.raw.g) {\n return [ctx.raw.g, `${ctx.raw.v}`]\n }\n return typeof label === 'string' ? [label, `${ctx.raw.v}`] : `${ctx.raw.v}`\n },\n overflow: 'cut',\n padding: 3,\n position: 'middle',\n },\n }\n\n static readonly descriptors = {\n _indexable: false,\n _scriptable: true,\n captions: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n labels: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n }\n\n static override readonly defaultRoutes = {\n backgroundColor: 'backgroundColor',\n borderColor: 'borderColor',\n }\n\n $context?: TreemapScriptableContext\n width: number | undefined\n height: number | undefined\n\n constructor(cfg?: Partial<TreemapConfig> & { options?: TreemapOptions }) {\n super()\n\n this.width = undefined\n this.height = undefined\n\n if (cfg) {\n Object.assign(this, cfg)\n }\n }\n\n draw(\n ctx: CanvasRenderingContext2D,\n data?: TreemapDataPoint,\n layout: TreemapLayoutOptions = layoutDefaults\n ) {\n if (!data) {\n return\n }\n const options = this.options\n const { inner, outer } = boundingRects(this)\n const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath\n\n ctx.save()\n\n if (outer.w !== inner.w || outer.h !== inner.h) {\n ctx.beginPath()\n addRectPath(ctx, outer)\n ctx.clip()\n addRectPath(ctx, inner)\n ctx.fillStyle = options.borderColor\n ctx.fill('evenodd')\n }\n\n ctx.beginPath()\n addRectPath(ctx, inner)\n ctx.fillStyle = options.backgroundColor\n ctx.fill()\n\n drawText(ctx, inner, options, data, this, layout)\n ctx.restore()\n }\n\n inRange(mouseX: number, mouseY: number, useFinalPosition?: boolean) {\n return inRange(this, mouseX, mouseY, useFinalPosition)\n }\n\n inXRange(mouseX: number, useFinalPosition?: boolean) {\n return inRange(this, mouseX, null, useFinalPosition)\n }\n\n inYRange(mouseY: number, useFinalPosition?: boolean) {\n return inRange(this, null, mouseY, useFinalPosition)\n }\n\n getCenterPoint(useFinalPosition?: boolean) {\n const { x, y, width, height } = this.getProps(['x', 'y', 'width', 'height'], useFinalPosition)\n return {\n x: x + width / 2,\n y: y + height / 2,\n }\n }\n\n override tooltipPosition() {\n return this.getCenterPoint()\n }\n}\n","import { Chart } from 'chart.js'\n\nimport TreemapController from './controller'\nimport TreemapElement from './element'\n\nChart.register(TreemapController as any, TreemapElement as any)\n\nexport type {\n LabelAlign,\n LabelOverflow,\n LabelPosition,\n TreemapConfig,\n TreemapControllerDatasetOptions,\n TreemapDataPoint,\n TreemapElement as TreemapElementType,\n TreemapOptions,\n} from './types'\n\nexport * from './utils'\nexport { TreemapController, TreemapElement }\n"],"names":["scaleRect","sq","xScale","yScale","sp","sp2","x","getPixelForValue","y","w","h","height","hidden","width","layoutDefaults","displayMode","rtl","spacing","limit","value","min","max","Math","parseBorderWidth","maxW","maxH","o","toTRBL","b","bottom","l","left","r","right","t","top","getDims","itm","w2","s2","key","a","_normalized","ar","d1","sqrt","d2","assignRow","rect","dims","sum","s","iw","_ix","getX","_iy","Rect","area","this","ih","dir","side","map","arr","nsum","row","get","maxd2","totd1","constructor","unsorted","getNewStat","sa","v","n","ratio","nmax","nmin","push","stat","_arr","Object","assign","setStat","StatArray","length","reset","_hist","Infinity","pushIf","fn","args","nstat","isOlderPart","act","req","startsWith","getGroupKey","lvl","String","hasGroupValue","scanTreeObject","keys","leafKey","obj","tree","result","objIndex","record","reduce","reduced","item","i","forEach","k","childKey","child","isObject","splice","normalizeTreeToArray","data","maxVal","element","ikeys","groupKey","getPath","groups","defaultValue","path","grp","join","resolveGroup","allGroups","groupIndex","idx","group","ensureGroup","tmp","groupValue","addKeys","tmpRef","values","mainGrp","mainValue","slice","create","ret","resolvedAllGroups","resolvedGroupIndex","itemGroup","g","label","children","ak","index","_idx","sort","requireVersion","pkg","ver","strict","parts","split","Number","parseInt","Error","compareAspectRatio","oldStat","newStat","os2","ns2","l2","or","toNodes","items","node","_data","vs","undefined","gs","sortNodes","nodes","widthCache","Map","shouldDrawCaption","options","display","toFont","font","lineHeight","padding","valueOrDefault","getCaptionHeight","captionHeight","drawText","ctx","layout","captions","labels","block","defined","isLeaf","content","resolveOption","formatter","callbackContext","lines","isArray","fonts","hoverFont","optFont","active","Array","f","getFontFromOptions","labelSize","measureLabelSize","lblToDraw","overflow","labelToDraw","isNumber","fitRatio","_lineHeight","size","floor","toFonts","color","hoverColor","align","optColor","clipY","colors","calculateBlockTop","labelBlock","oFont","text","resolveCaptionText","ellipsis","ellipsisWidth","currentWidth","lowerBoundLen","upperBoundLen","currentLen","slicedText","sliceTextToFitWidth","captionText","captionBlock","save","beginPath","clip","clipToPadding","calculateX","textAlign","textBaseline","offset","line","string","fillStyle","fillText","drawTextBlock","restore","context","$context","raw","type","option","fontsKey","prev","mapKey","_measureText","count","measureText","set","position","buildHierarchy","gidx","parentGroupValue","glen","gdata","filter","_item","nextGroupIndex","defineProperty","configurable","writable","flattenNodes","flat","_children","layoutLevel","parentSum","rectangle","packInto","getSubRect","layoutNodes","applyHeaderBoxes","borderWidth","bw","subRect","buildNodes","input","registerTooltipPositioner","tooltipPlugin","registry","plugins","positioners","treemap","at","tooltipPosition","TreemapController","DatasetController","initialize","enableOptionSharing","super","getMinMax","scale","axis","configure","getMeta","r1","r2","_rect","_rectChanged","_layoutOptions","dataset","getDataset","buildOrUpdateElements","_resetNewElements","parse","meta","_parsed","elements","dataElementType","_start","_count","concat","sumKeys","fingerprint","_fingerprint","_nodes","_layoutDirty","getContext","mode","prototype","call","parsed","getParsed","getLabelAndValue","update","updateElements","rects","start","firstOpts","resolveDataElementOptions","sharedOptions","getSharedOptions","includeOptions","properties","updateElement","updateSharedOptions","draw","chartArea","chart","metadata","clipArea","ilen","unclipArea","datasetIndex","getBounds","useFinalPosition","getProps","boundingRects","bounds","border","radius","toTRBLCorners","maxR","bottomLeft","bottomRight","topLeft","topRight","parseBorderRadius","borderRadius","outer","inner","inRange","skipX","skipY","addNormalRectPath","id","version","defaults","animations","numbers","descriptors","_indexable","_scriptable","_fallback","name","overrides","hover","interaction","includeInvisible","intersect","tooltip","callbacks","title","scales","alignToPixels","reverse","beforeRegister","Chart","afterRegister","afterUnregister","TreemapElement","Element","addRectPath","addRoundedRectPath","borderColor","fill","backgroundColor","mouseX","mouseY","inXRange","inYRange","getCenterPoint","cfg","defaultRoutes","register","stack","res","next","pop"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chartjs-chart-treemap.min.js","sources":["../src/helpers/index.ts","../src/options.ts","../src/rect.ts","../src/statArray.ts","../src/utils.ts","../src/squarify.ts","../src/text.ts","../src/layout.ts","../src/controller.ts","../src/geometry.ts","../src/element.ts","../src/index.ts"],"sourcesContent":["export function scaleRect(sq: any, xScale: any, yScale: any, sp: number) {\n const sp2 = sp * 2\n const x = xScale.getPixelForValue(sq.x)\n const y = yScale.getPixelForValue(sq.y)\n const w = xScale.getPixelForValue(sq.x + sq.w) - x\n const h = yScale.getPixelForValue(sq.y + sq.h) - y\n return {\n height: h - sp2,\n hidden: sp2 > w || sp2 > h,\n width: w - sp2,\n x: x + sp,\n y: y + sp,\n }\n}\n\nexport function rectNotEqual(r1: any, r2: any) {\n return (\n !r1 ||\n !r2 ||\n r1.x !== r2.x ||\n r1.y !== r2.y ||\n r1.w !== r2.w ||\n r1.h !== r2.h ||\n r1.rtl !== r2.rtl ||\n r1.unsorted !== r2.unsorted\n )\n}\n\nexport function arrayNotEqual(a: any[], b: any[]) {\n let i: number\n let n: number\n\n if (!a || !b) {\n return true\n }\n\n if (a === b) {\n return false\n }\n\n if (a.length !== b.length) {\n return true\n }\n\n for (i = 0, n = a.length; i < n; ++i) {\n if (a[i] !== b[i]) {\n return true\n }\n }\n return false\n}\n","import type {\n TreemapBorderRadius,\n TreemapBorderWidth,\n TreemapLayoutOptions,\n TreemapOptions,\n} from './types'\n\nimport { toTRBL, toTRBLCorners } from 'chart.js/helpers'\n\n/**\n * Options that shape the whole dataset's layout rather than a single element.\n * They live in the controller's defaults; the element receives the resolved\n * values as an argument to `draw`.\n */\nexport const layoutDefaults: TreemapLayoutOptions = {\n displayMode: 'containerBoxes',\n rtl: false,\n spacing: 0.5,\n}\n\nexport type ParsedBorderWidth = {\n b: number\n l: number\n r: number\n t: number\n}\n\nfunction limit(value: number, min: number, max: number) {\n return Math.max(Math.min(value, max), min)\n}\n\nexport function parseBorderWidth(\n value: TreemapBorderWidth,\n maxW: number,\n maxH: number\n): ParsedBorderWidth {\n const o = toTRBL(value as Parameters<typeof toTRBL>[0])\n\n return {\n b: limit(o.bottom, 0, maxH),\n l: limit(o.left, 0, maxW),\n r: limit(o.right, 0, maxW),\n t: limit(o.top, 0, maxH),\n }\n}\n\nexport function parseBorderRadius(\n value: TreemapOptions['borderRadius'],\n maxW: number,\n maxH: number\n): TreemapBorderRadius {\n const o = toTRBLCorners(value as Parameters<typeof toTRBLCorners>[0])\n const maxR = Math.min(maxW, maxH)\n\n return {\n bottomLeft: limit(o.bottomLeft, 0, maxR),\n bottomRight: limit(o.bottomRight, 0, maxR),\n topLeft: limit(o.topLeft, 0, maxR),\n topRight: limit(o.topRight, 0, maxR),\n }\n}\n","function getDims(itm: any, w2: number, s2: number, key: string) {\n const a = itm._normalized\n const ar = (w2 * a) / s2\n const d1 = Math.sqrt(a * ar)\n const d2 = a / d1\n const w = key === '_ix' ? d1 : d2\n const h = key === '_ix' ? d2 : d1\n\n return { d1, d2, h, w }\n}\n\nconst getX = (rect: Rect, w: number) => (rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix)\n\n/** Writes the geometry of one packed row onto the nodes themselves. */\nfunction assignRow(rect: Rect, itm: any, dims: any, sum: number) {\n itm.a = itm._normalized\n itm.h = dims.h\n itm.s = sum\n itm.w = dims.w\n itm.x = getX(rect, dims.w)\n itm.y = rect.y + rect._iy\n delete itm._normalized\n}\n\nexport default class Rect {\n [key: string]: any\n rtl: boolean\n unsorted: boolean\n x: number\n y: number\n _ix: number\n _iy: number\n w: number\n h: number\n\n constructor(r?: any) {\n r = r || { h: 1, w: 1 }\n this.rtl = !!r.rtl\n this.unsorted = !!r.unsorted\n this.x = r.x || r.left || 0\n this.y = r.y || r.top || 0\n this._ix = 0\n this._iy = 0\n this.w = r.w || r.width || r.right - r.left\n this.h = r.h || r.height || r.bottom - r.top\n }\n\n get area() {\n return this.w * this.h\n }\n\n get iw() {\n return this.w - this._ix\n }\n\n get ih() {\n return this.h - this._iy\n }\n\n get dir() {\n const ih = this.ih\n return ih <= this.iw && ih > 0 ? 'y' : 'x'\n }\n\n get side() {\n return this.dir === 'x' ? this.iw : this.ih\n }\n\n map(arr: any) {\n const { dir, side } = this\n const key = dir === 'x' ? '_ix' : '_iy'\n const sum = arr.nsum\n const row = arr.get()\n const w2 = side * side\n const s2 = sum * sum\n let maxd2 = 0\n let totd1 = 0\n for (const itm of row) {\n const dims = getDims(itm, w2, s2, key)\n totd1 += dims.d1\n maxd2 = Math.max(maxd2, dims.d2)\n assignRow(this, itm, dims, arr.sum)\n this[key] += dims.d1\n }\n\n this[dir === 'x' ? '_iy' : '_ix'] += maxd2\n this[key] -= totd1\n }\n}\n","const min = Math.min\nconst max = Math.max\n\nfunction getStat(sa: StatArray) {\n return {\n max: sa.max,\n min: sa.min,\n nmax: sa.nmax,\n nmin: sa.nmin,\n nsum: sa.nsum,\n sum: sa.sum,\n }\n}\n\nfunction getNewStat(sa: StatArray, o: any) {\n const v = +o[sa.key]\n const n = v * sa.ratio\n o._normalized = n\n\n return {\n max: max(sa.max, v),\n min: min(sa.min, v),\n nmax: max(sa.nmax, n),\n nmin: min(sa.nmin, n),\n nsum: sa.nsum + n,\n sum: sa.sum + v,\n }\n}\n\nfunction setStat(sa: StatArray, stat: any) {\n Object.assign(sa, stat)\n}\n\nfunction push(sa: StatArray, o: any, stat: any) {\n sa._arr.push(o)\n setStat(sa, stat)\n}\n\nexport default class StatArray {\n key: string\n ratio: number\n _arr: any[] = []\n _hist: any[] = []\n sum = 0\n nsum = 0\n min = Infinity\n max = -Infinity\n nmin = Infinity\n nmax = -Infinity\n\n constructor(key: string, ratio: number) {\n this.key = key\n this.ratio = ratio\n this.reset()\n }\n\n get length() {\n return this._arr.length\n }\n\n reset() {\n this._arr = []\n this._hist = []\n this.sum = 0\n this.nsum = 0\n this.min = Infinity\n this.max = -Infinity\n this.nmin = Infinity\n this.nmax = -Infinity\n }\n\n push(o: any) {\n push(this, o, getNewStat(this, o))\n }\n\n pushIf(o: any, fn: any, ...args: any[]) {\n const nstat = getNewStat(this, o)\n if (!fn(getStat(this), nstat, args)) {\n return o\n }\n push(this, o, nstat)\n }\n\n get() {\n return this._arr\n }\n}\n","import type { AnyObject } from './types'\n\nimport { isObject } from 'chart.js/helpers'\n\nconst isOlderPart = (act: string, req: string) =>\n req > act || (act.length > req.length && act.startsWith(req))\n\nexport const getGroupKey = (lvl: unknown) => String(lvl)\n\nconst hasGroupValue = (value: unknown) => value !== undefined && value !== null && value !== ''\n\nfunction scanTreeObject(\n keys: string[],\n leafKey: string,\n obj: Record<string, any>,\n tree: string[] = [],\n lvl = 0,\n result: Record<string, any>[] = []\n) {\n const objIndex = lvl - 1\n if (keys[0] in obj && lvl > 0) {\n const record = tree.reduce<Record<string, any>>((reduced, item, i) => {\n if (i !== objIndex) {\n reduced[getGroupKey(i)] = item\n }\n return reduced\n }, {})\n record[leafKey] = tree[objIndex]\n keys.forEach((k) => {\n record[k] = obj[k]\n })\n result.push(record)\n } else {\n for (const childKey of Object.keys(obj)) {\n const child = obj[childKey]\n if (isObject(child)) {\n tree.push(childKey)\n scanTreeObject(keys, leafKey, child, tree, lvl + 1, result)\n }\n }\n }\n tree.splice(objIndex, 1)\n return result\n}\n\n/**\n * Flattens a nested object into the array form of `data`.\n *\n * The controller does this at runtime, so JavaScript configurations never need\n * it. TypeScript users who would rather pass an array than a generic can call\n * it up front.\n */\nexport function flattenTree<T = AnyObject>(tree: AnyObject, keys: string[], leafKey: string): T[] {\n return normalizeTreeToArray(keys, leafKey, tree) as T[]\n}\n\nexport function normalizeTreeToArray(keys: string[], leafKey: string, obj: Record<string, any>) {\n const data = scanTreeObject(keys, leafKey, obj)\n if (!data.length) {\n return data\n }\n const max = data.reduce((maxVal, element) => {\n // minus 2 because _leaf and value properties are added\n // on top to groups ones\n const ikeys = Object.keys(element).length - 2\n return Math.max(maxVal, ikeys)\n }, 0)\n data.forEach((element) => {\n for (let i = 0; i < max; i++) {\n const groupKey = getGroupKey(i)\n if (!element[groupKey]) {\n element[groupKey] = ''\n }\n }\n })\n return data\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat\nexport function flatten(input: any[]) {\n const stack = [...input]\n const res = []\n while (stack.length) {\n // pop value from stack\n const next = stack.pop()\n if (Array.isArray(next)) {\n // push back array items, won't modify the original input\n stack.push(...next)\n } else {\n res.push(next)\n }\n }\n // reverse to restore input order\n return res.reverse()\n}\n\nfunction getPath(groups: string[], value: Record<string, any>, defaultValue: string) {\n const path = []\n for (const grp of groups) {\n const item = value[grp]\n if (!hasGroupValue(item)) {\n continue\n }\n path.push(item)\n }\n return path.length ? path.join('.') : defaultValue\n}\n\nfunction resolveGroup(\n value: Record<string, any>,\n leafKey: string,\n allGroups: string[],\n groupIndex: number\n) {\n for (let idx = groupIndex; idx < allGroups.length; idx++) {\n const groupKey = getGroupKey(allGroups[idx])\n if (hasGroupValue(value[groupKey])) {\n return { group: groupKey, groupIndex: idx, value: value[groupKey] }\n }\n }\n if (hasGroupValue(value[leafKey])) {\n return { group: leafKey, groupIndex, value: value[leafKey] }\n }\n return undefined\n}\n\nfunction ensureGroup(\n tmp: Record<string, any>,\n data: Record<string, any[]>,\n groupValue: string,\n addKeys: string[]\n) {\n if (groupValue in tmp) {\n return\n }\n tmp[groupValue] = { value: 0 }\n const tmpRef = tmp[groupValue]\n addKeys.forEach((k) => {\n tmpRef[k] = 0\n })\n data[groupValue] = []\n}\n\nexport function group(\n values: Record<string, any>[],\n grp: string,\n keys: string[],\n leafKey: string,\n mainGrp?: string,\n mainValue?: any,\n groups: string[] = [],\n allGroups: string[] = groups,\n groupIndex = groups.length - 1\n) {\n const key = keys[0]\n const addKeys = keys.slice(1)\n const tmp: Record<string, any> = Object.create(null)\n const data: Record<string, any[]> = Object.create(null)\n const ret: Record<string, any>[] = []\n const resolvedAllGroups = allGroups.length ? allGroups : [grp]\n const resolvedGroupIndex = allGroups.length ? groupIndex : 0\n let i: number\n let n: number\n for (i = 0, n = values.length; i < n; ++i) {\n const v = values[i]\n if (mainGrp && v[mainGrp] !== mainValue) {\n continue\n }\n const itemGroup = resolveGroup(v, leafKey, resolvedAllGroups, resolvedGroupIndex)\n if (!itemGroup) {\n return []\n }\n const g = itemGroup.value\n ensureGroup(tmp, data, g, addKeys)\n tmp[g].value += +v[key]\n tmp[g].label = g\n tmp[g].group = itemGroup.group\n tmp[g].groupIndex = itemGroup.groupIndex\n const tmpRef = tmp[g]\n addKeys.forEach((k) => {\n tmpRef[k] += v[k]\n })\n tmp[g].path = getPath(resolvedAllGroups.slice(0, itemGroup.groupIndex + 1), v, g)\n data[g].push(v)\n }\n\n Object.keys(tmp).forEach((k) => {\n const v: Record<string, any> = { children: data[k] }\n v[key] = +tmp[k].value\n addKeys.forEach((ak) => {\n v[ak] = +tmp[k][ak]\n })\n v[grp] = tmp[k].label\n v.group = tmp[k].group\n v.groupIndex = tmp[k].groupIndex\n v.label = k\n v.path = tmp[k].path\n\n if (mainGrp) {\n v[mainGrp] = mainValue\n }\n ret.push(v)\n })\n\n return ret\n}\n\nexport function index(values: any[], key: string) {\n let n = values.length\n let i: number\n\n if (!n) {\n return key\n }\n\n const obj = isObject(values[0])\n key = obj ? key : 'v'\n\n for (i = 0, n = values.length; i < n; ++i) {\n if (obj) {\n values[i]._idx = i\n } else {\n values[i] = { _idx: i, v: values[i] }\n }\n }\n return key\n}\n\nexport function sort(values: any[], key?: string) {\n if (key) {\n values.sort((a, b) => +b[key] - +a[key])\n } else {\n values.sort((a, b) => +b - +a)\n }\n}\n\nexport function sum(values: any[], key?: string) {\n let s: number\n let i: number\n let n: number\n\n for (s = 0, i = 0, n = values.length; i < n; ++i) {\n s += key ? +values[i][key] : +values[i]\n }\n\n return s\n}\n\nexport function requireVersion(pkg: string, min: string, ver: string, strict = true) {\n const parts = ver.split('.')\n let i = 0\n for (const req of min.split('.')) {\n const act = parts[i++]\n if (Number.parseInt(req, 10) < Number.parseInt(act, 10)) {\n break\n }\n if (isOlderPart(act, req)) {\n if (strict) {\n throw new Error(`${pkg} v${ver} is not supported. v${min} or newer is required.`)\n } else {\n return false\n }\n }\n }\n return true\n}\n","import Rect from './rect'\nimport StatArray from './statArray'\nimport { index, sort, sum } from './utils'\n\nfunction compareAspectRatio(oldStat: any, newStat: any, args: any[]) {\n if (oldStat.sum === 0) {\n return true\n }\n\n const [length] = args\n const os2 = oldStat.nsum * oldStat.nsum\n const ns2 = newStat.nsum * newStat.nsum\n const l2 = length * length\n const or = Math.max((l2 * oldStat.nmax) / os2, os2 / (l2 * oldStat.nmin))\n const nr = Math.max((l2 * newStat.nmax) / ns2, ns2 / (l2 * newStat.nmin))\n return nr <= or\n}\n\n/**\n * Builds the nodes for one set of siblings, without any geometry.\n *\n * Everything here depends only on the data: which item a node came from, its\n * value, its group and level. The rectangle is not involved, which is what lets\n * the controller know how many elements it needs before the chart area is known.\n */\nexport function toNodes(values: any[], keys: string[], grp?: string, lvl?: number) {\n const items = values ? values.slice() : []\n const key = index(items, keys[0])\n\n return items.map((item: any) => {\n const node: any = {\n _data: values[item._idx],\n v: key ? +item[key] : +item,\n vs: undefined,\n }\n if (grp) {\n node.g = item[grp]\n node.gs = undefined\n node.l = item.groupIndex ?? lvl\n node.vs = keys.reduce<Record<string, number>>((obj, k) => {\n obj[k] = +item[k]\n return obj\n }, {})\n }\n return node\n })\n}\n\n/** Orders a set of siblings the way the layout draws them: largest first. */\nexport function sortNodes(nodes: any[]) {\n sort(nodes, 'v')\n}\n\n/**\n * Packs already-ordered nodes into the rectangle, writing `x`, `y`, `w`, `h`,\n * the row sum `s` and the normalized area `a` onto them.\n */\nexport function packInto(nodes: any[], rectangle: any) {\n const n = nodes.length\n if (!n) {\n return\n }\n const rect = new Rect(rectangle)\n const row = new StatArray('v', rect.area / sum(nodes, 'v'))\n let length = rect.side\n let o: any\n\n for (let i = 0; i < n; ++i) {\n o = row.pushIf(nodes[i], compareAspectRatio, length)\n if (o) {\n rect.map(row)\n length = rect.side\n row.reset()\n row.push(o)\n }\n }\n if (row.length) {\n rect.map(row)\n }\n}\n\nexport default function squarify(\n values: any[],\n rectangle: any,\n keys: string[] = [],\n grp?: string,\n lvl?: number,\n gsum?: number\n) {\n const nodes = toNodes(values || [], keys, grp, lvl)\n if (grp) {\n for (const node of nodes) {\n node.gs = gsum\n }\n }\n if (!rectangle?.unsorted) {\n sortNodes(nodes)\n }\n packInto(nodes, rectangle)\n return nodes\n}\n","import type { Color, Element } from 'chart.js'\nimport type { DrawRect } from './geometry'\nimport type {\n TreemapCaptionsOptions,\n TreemapConfig,\n TreemapDataPoint,\n TreemapDisplayMode,\n TreemapLabelsOptions,\n TreemapLayoutOptions,\n TreemapOptions,\n TreemapScriptableContext,\n} from './types'\n\nimport { defined, isArray, isNumber, toFont, valueOrDefault } from 'chart.js/helpers'\n\ntype RectSize = {\n h: number\n w: number\n}\n\ntype RectHeight = {\n h: number\n}\n\ntype LabelSize = {\n height: number\n width: number\n}\n\ntype Font = ReturnType<typeof toFont>\n\ntype TextElement = Element<TreemapConfig, TreemapOptions> & {\n $context?: TreemapScriptableContext\n}\n\n/**\n * One block of text ready to draw: the lines, the styles they are drawn with,\n * and where the block's top edge sits. Captions and labels differ only in how\n * they arrive at this, which is why they can share the drawing code.\n */\ntype TextBlock = {\n /** Where the block sits inside the padded rect. */\n align: CanvasTextAlign\n /** Vertical clip inset. Zero where the box was sized to hold the text. */\n clipY: number\n colors: Color[]\n fonts: Font[]\n lines: string[]\n padding: number\n /** Paragraph each line belongs to, which is what indexes fonts and colours. */\n styles: number[]\n /** How each line sits inside the block. Follows `align` when undefined. */\n textAlign: CanvasTextAlign | undefined\n top: number\n /** Width of the widest line, which is the block's own width. */\n width: number\n}\n\n// Capped so a chart with many distinct labels cannot grow it without bound.\nconst WIDTH_CACHE_LIMIT = 4096\nconst widthCache = new Map<string, LabelSize>()\n\nexport function shouldDrawCaption(\n displayMode: TreemapDisplayMode,\n rect: RectSize,\n options?: Partial<TreemapCaptionsOptions>\n) {\n if (!options || options.display === false) {\n return false\n }\n if (displayMode === 'headerBoxes') {\n return true\n }\n const { w, h } = rect\n const font = toFont(options.font || {})\n const min = font.lineHeight\n const padding = Math.max(Math.min(valueOrDefault(options.padding, 3) * 2, Math.min(w, h)), 0)\n return w - padding > min && h - padding > min\n}\n\nexport function getCaptionHeight(\n displayMode: TreemapDisplayMode,\n rect: RectHeight,\n font: { lineHeight: number },\n padding: number\n) {\n if (displayMode !== 'headerBoxes') {\n return font.lineHeight + padding * 2\n }\n const captionHeight = font.lineHeight + padding * 2\n return rect.h < 2 * captionHeight ? rect.h / 3 : captionHeight\n}\n\nexport function drawText(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n options: TreemapOptions,\n item: TreemapDataPoint,\n element: TextElement,\n layout: TreemapLayoutOptions\n) {\n const { captions, labels } = options\n const { displayMode } = layout\n const isLeaf = item && (!defined(item.l) || item.isLeaf)\n\n // Resolve the text before touching the canvas. Most elements in a large\n // treemap draw no text at all, and clipping is not free: this is the\n // difference between five canvas calls per element and none.\n let block: TextBlock | undefined\n if (isLeaf) {\n if (labels.display) {\n block = labelBlock(ctx, rect, options, item, element)\n }\n } else if (shouldDrawCaption(displayMode, rect, captions)) {\n block = captionBlock(ctx, rect, options, item, element, layout)\n }\n if (!block) {\n return\n }\n\n ctx.save()\n clipToPadding(ctx, rect, block.padding, block.clipY)\n drawTextBlock(ctx, rect, block)\n ctx.restore()\n}\n\n/**\n * Text is clipped at the padding, not at the element's border (#135).\n * `overflow: 'cut'` used to run into the padding region, which made the padding\n * mean one thing for placement and nothing for clipping.\n *\n * The vertical inset is separate because a headerBoxes caption sits in a strip\n * whose height was derived from that caption's own line height. There is no\n * vertical overflow to prevent there, and insetting would slice the glyphs of\n * any font whose ascender and descender exceed its line height.\n */\nfunction clipToPadding(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n padding: number,\n clipY: number\n) {\n const x = Math.max(0, padding)\n const y = Math.max(0, clipY)\n ctx.beginPath()\n ctx.rect(rect.x + x, rect.y + y, Math.max(0, rect.w - 2 * x), Math.max(0, rect.h - 2 * y))\n ctx.clip()\n}\n\nfunction drawTextBlock(ctx: CanvasRenderingContext2D, rect: DrawRect, block: TextBlock) {\n const { align, colors, fonts, lines, padding, styles, textAlign, top, width } = block\n // `align` places the block in the rect, `textAlign` places each line in the\n // block. When they agree, which is the default, this is the same arithmetic\n // v4 did with a single x.\n const lineAlign = textAlign || align\n const x = calculateLineX(rect, align, lineAlign, padding, width)\n ctx.textAlign = lineAlign\n ctx.textBaseline = 'middle'\n let offset = 0\n lines.forEach((line, i) => {\n const style = styles[i]\n const font = fontFor(fonts, style)\n ctx.font = font.string\n ctx.fillStyle = colors[Math.min(style, colors.length - 1)]\n ctx.fillText(line, x, top + offset + font.lineHeight / 2)\n offset += font.lineHeight\n })\n}\n\nfunction callbackContext(element: TextElement, item: TreemapDataPoint): TreemapScriptableContext {\n const context =\n element.$context ||\n ({ active: !!element.active, raw: item, type: 'data' } as TreemapScriptableContext)\n context.active = !!element.active\n context.raw = item\n return context\n}\n\nfunction resolveOption<T>(\n option: T | ((context: TreemapScriptableContext) => T) | undefined,\n context: TreemapScriptableContext\n) {\n return typeof option === 'function'\n ? (option as (context: TreemapScriptableContext) => T)(context)\n : option\n}\n\nfunction resolveCaptionText(\n captions: TreemapCaptionsOptions,\n element: TextElement,\n item: TreemapDataPoint\n) {\n return resolveOption(captions.formatter, callbackContext(element, item)) || item.g || ''\n}\n\n/** The caption's text, truncated with an ellipsis when it does not fit. */\nfunction captionText(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n captions: TreemapCaptionsOptions,\n element: TextElement,\n item: TreemapDataPoint,\n fonts: Font[]\n) {\n const text = resolveCaptionText(captions, element, item)\n if (!text) {\n return undefined\n }\n const padding = captions.padding\n if (measureLabelSize(ctx, [text], fonts).width + 2 * padding <= rect.w) {\n return text\n }\n // `ellipsis` is the default and is what v4 always did; the other modes leave\n // the clip to tell the whole story.\n const overflow = captions.overflow || 'ellipsis'\n if (overflow === 'hidden') {\n return undefined\n }\n if (overflow === 'cut') {\n return text\n }\n return sliceTextToFitWidth(ctx, text, rect.w - 2 * padding, fonts)\n}\n\nfunction captionBlock(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n options: TreemapOptions,\n item: TreemapDataPoint,\n element: TextElement,\n layout: TreemapLayoutOptions\n): TextBlock | undefined {\n const { displayMode, rtl, spacing } = layout\n const { captions } = options\n const { color, hoverColor, font, hoverFont, padding, align } = captions\n const optFont = (rect.active ? hoverFont : font) || font\n const oFont = toFont(optFont)\n if (oFont.lineHeight > rect.h) {\n return\n }\n const text = captionText(ctx, rect, captions, element, item, [oFont])\n if (text === undefined) {\n return\n }\n const fonts = [oFont]\n // A caption is a single line, centred in the header strip in headerBoxes mode\n // and sitting under the top padding otherwise.\n const top =\n displayMode === 'headerBoxes'\n ? rect.y + (rect.h - oFont.lineHeight) / 2\n : rect.y + padding + spacing\n return {\n align: align || (rtl ? 'right' : 'left'),\n clipY: displayMode === 'headerBoxes' ? 0 : padding,\n colors: [(rect.active ? hoverColor : color) || color],\n fonts,\n lines: [text],\n padding,\n styles: [0],\n textAlign: captions.textAlign,\n top,\n width: measureLabelSize(ctx, [text], fonts).width,\n }\n}\n\nfunction labelBlock(\n ctx: CanvasRenderingContext2D,\n rect: DrawRect,\n options: TreemapOptions,\n item: TreemapDataPoint,\n element: TextElement\n): TextBlock | undefined {\n const labels = options.labels\n const content = resolveOption(labels.formatter, callbackContext(element, item))\n if (!content) {\n return\n }\n const { align, color, hoverColor, overflow, padding, wrap } = labels\n const maxWidth = rect.w - padding * 2\n const maxHeight = rect.h - padding * 2\n\n let fonts = getFontFromOptions(rect, labels)\n let { lines, styles } = toLines(ctx, content, fonts, maxWidth, !!wrap)\n let labelSize = measureLines(ctx, lines, styles, fonts)\n\n const lblToDraw = labelToDraw(rect, labels, labelSize)\n if (!lblToDraw) {\n return\n }\n if (isNumber(lblToDraw)) {\n fonts = toFonts(fonts, lblToDraw)\n if (wrap) {\n // Shorter lines pack into fewer rows, so wrap once more at the smaller\n // size rather than iterating towards a fixed point.\n const rewrapped = toLines(ctx, content, fonts, maxWidth, true)\n lines = rewrapped.lines\n styles = rewrapped.styles\n labelSize = measureLines(ctx, lines, styles, fonts)\n } else {\n labelSize = { height: labelSize.height * lblToDraw, width: labelSize.width * lblToDraw }\n }\n }\n\n if (overflow === 'ellipsis') {\n const trimmed = applyEllipsis(ctx, lines, styles, fonts, maxWidth, maxHeight)\n lines = trimmed.lines\n styles = trimmed.styles\n labelSize = measureLines(ctx, lines, styles, fonts)\n }\n\n const optColor = (rect.active ? hoverColor : color) || color\n return {\n align,\n clipY: padding,\n colors: isArray(optColor) ? optColor : [optColor],\n fonts,\n lines,\n padding,\n styles,\n textAlign: labels.textAlign,\n top: calculateBlockTop(rect, labels, labelSize),\n width: labelSize.width,\n }\n}\n\nfunction sliceTextToFitWidth(\n ctx: CanvasRenderingContext2D,\n text: string,\n width: number,\n fonts: Font[]\n) {\n const ellipsis = '...'\n const ellipsisWidth = measureLabelSize(ctx, [ellipsis], fonts).width\n if (ellipsisWidth >= width) {\n return ''\n }\n let lowerBoundLen = 1\n let upperBoundLen = text.length\n let currentWidth: number\n while (lowerBoundLen <= upperBoundLen) {\n const currentLen = Math.floor((lowerBoundLen + upperBoundLen) / 2)\n const currentText = text.slice(0, currentLen)\n currentWidth = measureLabelSize(ctx, [currentText], fonts).width\n if (currentWidth + ellipsisWidth > width) {\n upperBoundLen = currentLen - 1\n } else {\n lowerBoundLen = currentLen + 1\n }\n }\n const slicedText = text.slice(0, Math.max(0, lowerBoundLen - 1))\n return slicedText ? slicedText + ellipsis : ''\n}\n\nconst fontFor = (fonts: Font[], index: number) => fonts[Math.min(index, fonts.length - 1)]\n\n/**\n * Breaks one piece of text to `width`, greedily on spaces. A single word wider\n * than the width is broken by character, because leaving it to overflow would\n * defeat the point of asking for wrapping.\n */\nfunction wrapToWidth(ctx: CanvasRenderingContext2D, text: string, font: Font, width: number) {\n if (width <= 0) {\n return [text]\n }\n const fits = (value: string) => measureLabelSize(ctx, [value], [font]).width <= width\n const lines: string[] = []\n let line = ''\n\n const pushWord = (word: string) => {\n if (fits(word)) {\n line = word\n return\n }\n let chunk = ''\n for (const char of word) {\n if (chunk && !fits(chunk + char)) {\n lines.push(chunk)\n chunk = ''\n }\n chunk += char\n }\n line = chunk\n }\n\n for (const word of text.split(' ')) {\n const candidate = line ? `${line} ${word}` : word\n if (fits(candidate)) {\n line = candidate\n continue\n }\n if (line) {\n lines.push(line)\n line = ''\n }\n pushWord(word)\n }\n if (line) {\n lines.push(line)\n }\n return lines.length ? lines : ['']\n}\n\n/**\n * Formatter output as drawable lines.\n *\n * An array is one paragraph per entry and a string breaks on newlines, which\n * canvas would otherwise draw as a stray glyph. Colours and fonts are indexed\n * by paragraph, so a wrapped paragraph keeps one style throughout.\n */\nfunction toLines(\n ctx: CanvasRenderingContext2D,\n content: string | string[],\n fonts: Font[],\n width: number,\n wrap: boolean\n) {\n const paragraphs = (isArray(content) ? content : [content]).map((entry) => `${entry}`)\n const lines: string[] = []\n const styles: number[] = []\n\n paragraphs.forEach((paragraph, index) => {\n const font = fontFor(fonts, index)\n for (const piece of paragraph.split('\\n')) {\n for (const line of wrap ? wrapToWidth(ctx, piece, font, width) : [piece]) {\n lines.push(line)\n styles.push(index)\n }\n }\n })\n return { lines, styles }\n}\n\n/** Measures a set of lines whose fonts are indexed by paragraph. */\nfunction measureLines(\n ctx: CanvasRenderingContext2D,\n lines: string[],\n styles: number[],\n fonts: Font[]\n): LabelSize {\n let width = 0\n let height = 0\n lines.forEach((line, i) => {\n const font = fontFor(fonts, styles[i])\n width = Math.max(width, measureLabelSize(ctx, [line], [font]).width)\n height += font.lineHeight\n })\n return { height, width }\n}\n\n/**\n * Keeps as many whole lines as fit, and marks the truncation with an ellipsis:\n * on any line too wide for the box, and on the last line kept when there were\n * more below it.\n */\nfunction applyEllipsis(\n ctx: CanvasRenderingContext2D,\n lines: string[],\n styles: number[],\n fonts: Font[],\n maxWidth: number,\n maxHeight: number\n) {\n const keptLines: string[] = []\n const keptStyles: number[] = []\n let used = 0\n for (let i = 0; i < lines.length; i++) {\n const font = fontFor(fonts, styles[i])\n if (keptLines.length && used + font.lineHeight > maxHeight) {\n break\n }\n used += font.lineHeight\n keptLines.push(lines[i])\n keptStyles.push(styles[i])\n }\n\n const dropped = keptLines.length < lines.length\n const last = keptLines.length - 1\n for (let i = 0; i < keptLines.length; i++) {\n const font = fontFor(fonts, keptStyles[i])\n const tooWide = measureLabelSize(ctx, [keptLines[i]], [font]).width > maxWidth\n if (tooWide || (dropped && i === last)) {\n keptLines[i] = sliceTextToFitWidth(ctx, keptLines[i], maxWidth, [font])\n }\n }\n return { lines: keptLines, styles: keptStyles }\n}\n\nfunction measureLabelSize(\n ctx: CanvasRenderingContext2D & { _measureText?: unknown },\n lines: string[],\n fonts: Font[]\n) {\n const fontsKey = fonts.reduce((prev, item) => {\n prev += item.string\n return prev\n }, '')\n const mapKey = lines.join() + fontsKey + (ctx._measureText ? '-spriting' : '')\n let size = widthCache.get(mapKey)\n if (!size) {\n ctx.save()\n const count = lines.length\n let width = 0\n let height = 0\n for (let i = 0; i < count; i++) {\n const font = fonts[Math.min(i, fonts.length - 1)]\n ctx.font = font.string\n const text = lines[i]\n width = Math.max(width, ctx.measureText(text).width)\n height += font.lineHeight\n }\n ctx.restore()\n size = { height, width }\n if (widthCache.size >= WIDTH_CACHE_LIMIT) {\n widthCache.clear()\n }\n widthCache.set(mapKey, size)\n }\n return size\n}\n\nfunction toFonts(fonts: Font[], fitRatio: number) {\n return fonts.map((f) => {\n const { lineHeight: _lineHeight, ...font } = f\n return toFont({ ...font, size: Math.floor(f.size * fitRatio) })\n })\n}\n\nfunction labelToDraw(rect: DrawRect, options: TreemapLabelsOptions, labelSize: LabelSize) {\n const { overflow, padding } = options\n const { width, height } = labelSize\n if (overflow === 'hidden') {\n return !(width + padding * 2 > rect.w || height + padding * 2 > rect.h)\n } else if (overflow === 'fit') {\n const ratio = Math.min(rect.w / (width + padding * 2), rect.h / (height + padding * 2))\n if (ratio < 1) {\n return ratio\n }\n }\n return true\n}\n\nfunction getFontFromOptions(rect: DrawRect, labels: TreemapLabelsOptions) {\n const { font, hoverFont } = labels\n const optFont = (rect.active ? hoverFont : font) || font\n return Array.isArray(optFont) ? optFont.map((f) => toFont(f)) : [toFont(optFont)]\n}\n\nfunction calculateBlockTop(rect: DrawRect, options: TreemapLabelsOptions, labelSize: LabelSize) {\n const { position, padding } = options\n if (position === 'top') {\n return rect.y + padding\n }\n if (position === 'bottom') {\n return rect.y + rect.h - padding - labelSize.height\n }\n return rect.y + (rect.h - labelSize.height) / 2 + padding\n}\n\n/** The block's left edge inside the padded rect. */\nfunction calculateBlockLeft(\n rect: DrawRect,\n align: CanvasTextAlign,\n padding: number,\n width: number\n) {\n if (align === 'left') {\n return rect.x + padding\n }\n if (align === 'right') {\n return rect.x + rect.w - padding - width\n }\n return rect.x + (rect.w - width) / 2\n}\n\n/**\n * The x every line is drawn at, given the canvas `textAlign` that will be in\n * effect. When the two alignments agree this reduces to v4's single x, so the\n * default output is unchanged.\n */\nfunction calculateLineX(\n rect: DrawRect,\n align: CanvasTextAlign,\n lineAlign: CanvasTextAlign,\n padding: number,\n width: number\n) {\n if (align === lineAlign) {\n if (align === 'left') {\n return rect.x + padding\n }\n if (align === 'right') {\n return rect.x + rect.w - padding\n }\n return rect.x + rect.w / 2\n }\n const left = calculateBlockLeft(rect, align, padding, width)\n if (lineAlign === 'left') {\n return left\n }\n if (lineAlign === 'right') {\n return left + width\n }\n return left + width / 2\n}\n","import type { DrawRect } from './geometry'\nimport type { TreemapDataPoint, TreemapDisplayMode } from './types'\n\nimport { isObject, toFont, valueOrDefault } from 'chart.js/helpers'\n\nimport { parseBorderWidth } from './options'\nimport { packInto, sortNodes, toNodes } from './squarify'\nimport { getCaptionHeight, shouldDrawCaption } from './text'\nimport { getGroupKey, group, normalizeTreeToArray } from './utils'\n\nexport type LayoutOptions = {\n borderWidth: any\n captions: any\n displayMode: TreemapDisplayMode\n groups: any[]\n leafKey: string\n spacing: number\n unsorted: boolean\n}\n\n/** A node while the layout is being built; `_children` is dropped before use. */\nexport type LayoutNode = TreemapDataPoint & { _children?: LayoutNode[] }\n\n/**\n * Pass one: the hierarchy.\n *\n * Groups the items level by level and orders each set of siblings. Nothing here\n * depends on the chart area, so the number of nodes and their order are known\n * before the layout has a rectangle to fill.\n */\nfunction buildHierarchy(\n values: any[],\n gidx: number,\n keys: string[],\n layout: LayoutOptions,\n parentGroupValue?: string\n): LayoutNode[] {\n const { groups, leafKey, unsorted } = layout\n const glen = groups.length\n const g = getGroupKey(groups[gidx])\n const gdata = group(\n values,\n g,\n keys,\n leafKey,\n undefined,\n parentGroupValue,\n groups.filter((_item: any, index: number) => index <= gidx),\n groups,\n gidx\n )\n const nodes = toNodes(gdata, keys, g, gidx) as LayoutNode[]\n if (!unsorted) {\n sortNodes(nodes)\n }\n\n for (const node of nodes) {\n const record = node._data as any\n const nextGroupIndex = record.groupIndex + 1\n const children =\n gidx < glen - 1 && nextGroupIndex < glen\n ? buildHierarchy(record.children, nextGroupIndex, keys, layout, node.g)\n : []\n // Non-enumerable: the geometry pass needs it on every layout, but it\n // must not show up in ctx.raw.\n Object.defineProperty(node, '_children', {\n configurable: true,\n value: children,\n writable: true,\n })\n node.isLeaf = !children.length\n }\n return nodes\n}\n\n/** Draw order: a set of siblings, then the descendants of each in turn. */\nexport function flattenNodes(nodes: LayoutNode[]): LayoutNode[] {\n const flat = nodes.slice()\n for (const node of nodes) {\n if (node._children?.length) {\n flat.push(...flattenNodes(node._children))\n }\n }\n return flat\n}\n\n/**\n * Pass two: the geometry.\n *\n * Packs each set of siblings into its parent's rectangle, writing the\n * coordinates onto the nodes the first pass produced.\n */\nfunction layoutLevel(nodes: LayoutNode[], rect: any, layout: LayoutOptions, parentSum?: number) {\n if (parentSum !== undefined) {\n for (const node of nodes) {\n node.gs = parentSum\n }\n }\n packInto(nodes, rect)\n\n for (const node of nodes) {\n if (node._children?.length) {\n layoutLevel(node._children, getSubRect(node, rect, layout), layout, node.s)\n }\n }\n}\n\n/** Writes the geometry for a whole tree of nodes, then applies headerBoxes. */\nexport function layoutNodes(nodes: LayoutNode[], rect: any, layout: LayoutOptions) {\n layoutLevel(nodes, rect, layout)\n applyHeaderBoxes(flattenNodes(nodes), layout)\n}\n\n/** The rectangle left for a group's children once its border and caption are taken. */\nfunction getSubRect(sq: any, rect: any, layout: LayoutOptions) {\n const { borderWidth, captions, displayMode } = layout\n const sp = displayMode === 'headerBoxes' ? 0 : layout.spacing\n const bw =\n displayMode === 'headerBoxes'\n ? { b: 0, l: 0, r: 0, t: 0 }\n : parseBorderWidth(borderWidth, sq.w / 2, sq.h / 2)\n const subRect = {\n ...rect,\n h: sq.h - 2 * sp - bw.t - bw.b,\n w: sq.w - 2 * sp - bw.l - bw.r,\n x: sq.x + sp + bw.l,\n y: sq.y + sp + bw.t,\n }\n if (shouldDrawCaption(displayMode, subRect, captions)) {\n const captionHeight = getCaptionHeight(\n displayMode,\n subRect,\n toFont(captions.font),\n valueOrDefault(captions.padding, 3)\n )\n subRect.y += captionHeight\n subRect.h -= captionHeight\n }\n return subRect\n}\n\n/**\n * The hierarchy pass on its own: the nested nodes, in draw order, with no\n * geometry. Takes no rectangle, which is the whole point - the controller needs\n * the node count before the chart area is known.\n */\nexport function buildNodes(tree: any, keys: string[], layout: LayoutOptions): LayoutNode[] {\n const { groups, leafKey, unsorted } = layout\n const input = isObject(tree) ? normalizeTreeToArray(keys, leafKey, tree) : tree\n\n if (groups.length) {\n return buildHierarchy(input, 0, keys, layout)\n }\n const nodes = toNodes(input || [], keys) as LayoutNode[]\n if (!unsorted) {\n sortNodes(nodes)\n }\n return nodes\n}\n\n/**\n * In headerBoxes mode a group is drawn as a header strip rather than a box\n * around its children, and a group whose caption does not fit is not drawn at\n * all. It is marked hidden rather than removed: the number of parsed nodes must\n * not depend on the size of the chart area.\n */\nfunction applyHeaderBoxes(nodes: LayoutNode[], layout: LayoutOptions) {\n const { captions, displayMode } = layout\n if (displayMode !== 'headerBoxes') {\n return\n }\n const font = toFont(captions.font)\n const padding = valueOrDefault(captions.padding, 3)\n for (const node of nodes) {\n if (node.isLeaf) {\n continue\n }\n if (shouldDrawCaption(displayMode, node, captions)) {\n node.h = getCaptionHeight(displayMode, node, font, padding)\n node.hidden = false\n } else {\n node.hidden = true\n }\n }\n}\n\n/** Turns the user's input into the flat list of rectangles the chart draws. */\nexport function buildData(\n tree: any,\n keys: string[],\n mainRect: DrawRect,\n layout: LayoutOptions\n): TreemapDataPoint[] {\n const nodes = buildNodes(tree, keys, layout)\n layoutNodes(nodes, mainRect, layout)\n return flattenNodes(nodes)\n}\n","import type { LayoutNode, LayoutOptions } from './layout'\n\nimport { Chart, DatasetController, registry } from 'chart.js'\nimport { clipArea, unclipArea, valueOrDefault } from 'chart.js/helpers'\n\nimport { version } from '../package.json'\nimport { rectNotEqual, scaleRect } from './helpers/index'\nimport { buildNodes, flattenNodes, layoutNodes } from './layout'\nimport { layoutDefaults } from './options'\nimport { requireVersion } from './utils'\n\nfunction registerTooltipPositioner() {\n const tooltipPlugin = registry.plugins.get('tooltip') as any\n if (!tooltipPlugin || tooltipPlugin.positioners.treemap) {\n return\n }\n tooltipPlugin.positioners.treemap = (active: any[]) => {\n if (!active.length) {\n return false\n }\n\n const item = active.at(-1)\n return item.element.tooltipPosition()\n }\n}\n\nexport default class TreemapController extends DatasetController {\n declare static readonly id: string\n declare static readonly defaults: Record<string, unknown>\n declare static readonly descriptors: Record<string, unknown>\n declare static readonly overrides: Record<string, unknown>\n declare static readonly beforeRegister: () => void\n declare static readonly afterRegister: () => void\n declare static readonly afterUnregister: () => void\n\n // Chart.js assigns this on the class when the controller is registered; its\n // type definitions do not describe it.\n declare dataElementType: new () => any\n\n options: any\n _rect: any\n _rectChanged: boolean\n _nodes: LayoutNode[]\n _layoutDirty: boolean\n _fingerprint: string | undefined\n\n constructor(chart: any, datasetIndex: number) {\n super(chart, datasetIndex)\n\n this._rect = undefined\n this._rectChanged = true\n this._nodes = []\n this._layoutDirty = true\n this._fingerprint = undefined\n }\n\n override initialize() {\n // The tooltip can be registered after the treemap controller. At chart creation time all\n // components are available, so retry here to make registration order irrelevant.\n registerTooltipPositioner()\n this.enableOptionSharing = true\n super.initialize()\n }\n\n override getMinMax(scale: any) {\n return {\n max: scale.axis === 'x' ? scale.right - scale.left : scale.bottom - scale.top,\n min: 0,\n }\n }\n\n override configure() {\n super.configure()\n const { xScale, yScale } = this.getMeta() as any\n if (!xScale || !yScale) {\n // configure is called once before `linkScales`, and at that call we don't have any scales linked yet\n return\n }\n\n const w = xScale.right - xScale.left\n const h = yScale.bottom - yScale.top\n const rect = { h, rtl: !!this.options.rtl, unsorted: !!this.options.unsorted, w, x: 0, y: 0 }\n\n if (rectNotEqual(this._rect, rect)) {\n this._rect = rect\n this._rectChanged = true\n }\n\n if (this._rectChanged) {\n xScale.max = w\n xScale.configure()\n yScale.max = h\n yScale.configure()\n }\n }\n\n /**\n * Options that shape the layout rather than a single rectangle, resolved once\n * per dataset. Reading them from `this.options` rather than from the raw\n * dataset is what makes `options.datasets.treemap` work for all of them.\n */\n _layoutOptions(): LayoutOptions {\n const dataset = this.getDataset() as any\n const options = this.options\n return {\n // Still raw: resolving these with the dataset context is feature 2's\n // change, and doing it here would move pixels in this refactor.\n borderWidth: dataset.borderWidth,\n captions: dataset.captions || {},\n displayMode: options.displayMode,\n groups: options.groups || [],\n leafKey: options.leafKey,\n // Deliberately NOT options.spacing. The child rectangle calculation has\n // always defaulted spacing to 0 while the drawn rectangle defaults it to\n // 0.5, so reading the resolved value here would inset every nested group\n // by an extra 0.5 and move 11 fixtures. Unifying the two is a visual\n // change that deserves its own pull request.\n spacing: valueOrDefault(dataset.spacing, 0),\n unsorted: !!options.unsorted,\n }\n }\n\n /**\n * Chart.js calls this before `configure()`, so the chart area is not\n * available here - see the hierarchy pass in `./layout`, which does not need\n * one. Elements are created from the parsed nodes rather than from\n * `dataset.data`, because a treemap with groups has more rectangles than the\n * user supplied rows.\n */\n override buildOrUpdateElements(_resetNewElements?: boolean) {\n this.parse(0, 0)\n\n const meta = this.getMeta() as any\n const count = (meta._parsed as unknown[]).length\n const elements = meta.data as unknown[]\n if (elements.length > count) {\n elements.splice(count, elements.length - count)\n }\n while (elements.length < count) {\n elements.push(new this.dataElementType())\n }\n }\n\n override parse(_start: number, _count: number) {\n const dataset = this.getDataset() as any\n if (dataset.tree !== undefined) {\n throw new Error(\n 'chartjs-chart-treemap v5: the \"tree\" option was renamed to \"data\". ' +\n 'See https://chartjs-chart-treemap.pages.dev/usage/'\n )\n }\n\n const options = this.options\n const keys = [options.key || ''].concat(options.sumKeys || [])\n const nodes = buildNodes(dataset.data || [], keys, this._layoutOptions())\n const flat = flattenNodes(nodes)\n\n // A `chart.update('none')` per wheel event must not re-run the layout when\n // nothing about the data changed, so keep the previous nodes - and with\n // them their geometry - when the hierarchy is identical.\n const fingerprint = flat.map((node) => `${node.v}\\u0000${node.g}\\u0000${node.l}`).join('\\u0001')\n if (this._fingerprint === fingerprint) {\n return\n }\n\n this._fingerprint = fingerprint\n this._nodes = nodes\n ;(this.getMeta() as any)._parsed = flat\n this._layoutDirty = true\n }\n\n // `getContext` exists on DatasetController at runtime but not in its type\n // definitions, so this cannot be declared as an override.\n getContext(index: number, active?: boolean, mode?: string) {\n const base = (DatasetController.prototype as any).getContext\n const context = base.call(this, index, active, mode)\n const parsed = typeof index === 'number' ? this.getParsed(index) : undefined\n if (parsed) {\n context.raw = parsed\n context.parsed = parsed\n }\n return context\n }\n\n override getLabelAndValue(index: number) {\n const node = this.getParsed(index) as any\n if (!node) {\n return { label: '', value: '' }\n }\n const dataset = this.getDataset() as any\n const label = node.g ?? node._data?.label ?? dataset.label\n return { label: label === undefined ? '' : `${label}`, value: `${node.v}` }\n }\n\n override update(mode: any) {\n const { data } = this.getMeta()\n\n if (mode === 'reset') {\n // reset is called before 2nd configure and is only called if animations are enabled. So wen need an extra configure call here.\n this.configure()\n }\n\n if (this._layoutDirty || this._rectChanged) {\n layoutNodes(this._nodes, this._rect, this._layoutOptions())\n this._layoutDirty = false\n this._rectChanged = false\n }\n\n this.updateElements(data, 0, data.length, mode)\n }\n\n override updateElements(rects: any[], start: number, count: number, mode: any) {\n const reset = mode === 'reset'\n const firstOpts = this.resolveDataElementOptions(start, mode)\n this._rect.options = firstOpts\n const sharedOptions = this.getSharedOptions(firstOpts)\n const includeOptions = this.includeOptions(mode, sharedOptions || {})\n const { xScale, yScale } = this.getMeta() as any\n const spacing = this.options.spacing\n\n for (let i = start; i < start + count; i++) {\n const options = sharedOptions || this.resolveDataElementOptions(i, mode)\n const node = this.getParsed(i) as any\n const properties: any = scaleRect(node, xScale, yScale, spacing)\n properties.hidden = properties.hidden || !!node.hidden\n if (reset) {\n properties.width = 0\n properties.height = 0\n }\n\n if (includeOptions) {\n properties.options = options\n }\n this.updateElement(rects[i], i, properties, mode)\n }\n\n this.updateSharedOptions(sharedOptions || {}, mode, firstOpts)\n }\n\n override draw() {\n const { ctx, chartArea } = this.chart\n const metadata = ((this.getMeta() as any).data || []) as any[]\n const { displayMode, rtl, spacing } = this.options\n const layout = { displayMode, rtl, spacing }\n\n clipArea(ctx, chartArea)\n for (let i = 0, ilen = metadata.length; i < ilen; ++i) {\n const rect = metadata[i]\n if (!rect.hidden) {\n rect.draw(ctx, this.getParsed(i) as any, layout)\n }\n }\n unclipArea(ctx)\n }\n}\n\n;(TreemapController as any).id = 'treemap'\n\n;(TreemapController as any).version = version\n\n;(TreemapController as any).defaults = {\n animations: {\n numbers: {\n properties: ['x', 'y', 'width', 'height'],\n type: 'number',\n },\n },\n dataElementType: 'treemap',\n displayMode: layoutDefaults.displayMode,\n groups: [],\n key: '',\n leafKey: '_leaf',\n rtl: layoutDefaults.rtl,\n spacing: layoutDefaults.spacing,\n sumKeys: [],\n unsorted: false,\n}\n\n;(TreemapController as any).descriptors = {\n _indexable: false,\n _scriptable: true,\n captions: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n labels: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n}\n\n;(TreemapController as any).overrides = {\n hover: {},\n interaction: {\n includeInvisible: true,\n intersect: true,\n mode: 'point',\n },\n\n plugins: {\n tooltip: {\n callbacks: {\n label(item: any) {\n const node = item.parsed\n const label = node.g || node._data?.label || item.dataset.label\n return (label ? `${label}: ` : '') + node.v\n },\n title(items: any[]) {\n if (items.length) {\n const item = items[0]\n return item.dataset.key || ''\n }\n return ''\n },\n },\n intersect: true,\n position: 'treemap',\n },\n },\n scales: {\n x: {\n alignToPixels: true,\n bounds: 'data',\n display: false,\n type: 'linear',\n },\n y: {\n alignToPixels: true,\n bounds: 'data',\n display: false,\n reverse: true,\n type: 'linear',\n },\n },\n}\n\n;(TreemapController as any).beforeRegister = () => {\n requireVersion('chart.js', '4.0', Chart.version)\n}\n\n;(TreemapController as any).afterRegister = () => {\n registerTooltipPositioner()\n}\n\n;(TreemapController as any).afterUnregister = () => {\n const tooltipPlugin = registry.plugins.get('tooltip') as any\n if (tooltipPlugin) {\n delete tooltipPlugin.positioners.treemap\n }\n}\n","import type { Element } from 'chart.js'\nimport type { TreemapBorderRadius, TreemapConfig, TreemapOptions } from './types'\n\nimport { parseBorderRadius, parseBorderWidth } from './options'\n\nexport type DrawRect = {\n active?: boolean\n h: number\n radius: TreemapBorderRadius\n w: number\n x: number\n y: number\n}\n\ntype TreemapElementBase = Element<TreemapConfig, TreemapOptions>\n\nfunction getBounds(rect: TreemapElementBase, useFinalPosition?: boolean) {\n const { x, y, width, height } = rect.getProps(['x', 'y', 'width', 'height'], useFinalPosition)\n return { bottom: y + height, left: x, right: x + width, top: y }\n}\n\nexport function boundingRects(rect: TreemapElementBase) {\n const bounds = getBounds(rect)\n const width = bounds.right - bounds.left\n const height = bounds.bottom - bounds.top\n const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2)\n const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2)\n const outer = {\n active: rect.active,\n h: height,\n radius,\n w: width,\n x: bounds.left,\n y: bounds.top,\n }\n\n return {\n inner: {\n active: rect.active,\n h: outer.h - border.t - border.b,\n radius: {\n bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),\n bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)),\n topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),\n topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),\n },\n w: outer.w - border.l - border.r,\n x: outer.x + border.l,\n y: outer.y + border.t,\n },\n outer,\n }\n}\n\nexport function inRange(\n rect: TreemapElementBase,\n x: number | null,\n y: number | null,\n useFinalPosition?: boolean\n) {\n const skipX = x === null\n const skipY = y === null\n const bounds = !rect || (skipX && skipY) ? false : getBounds(rect, useFinalPosition)\n\n return (\n bounds &&\n (skipX || (x >= bounds.left && x <= bounds.right)) &&\n (skipY || (y >= bounds.top && y <= bounds.bottom))\n )\n}\n\nexport function hasRadius(radius: TreemapBorderRadius) {\n return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight\n}\n\nexport function addNormalRectPath(ctx: CanvasRenderingContext2D, rect: DrawRect) {\n ctx.rect(rect.x, rect.y, rect.w, rect.h)\n}\n","import type {\n TreemapConfig,\n TreemapDataPoint,\n TreemapLayoutOptions,\n TreemapOptions,\n TreemapScriptableContext,\n} from './types'\n\nimport { Element } from 'chart.js'\nimport { addRoundedRectPath } from 'chart.js/helpers'\n\nimport { addNormalRectPath, boundingRects, hasRadius, inRange } from './geometry'\nimport { layoutDefaults } from './options'\nimport { drawText } from './text'\n\nexport default class TreemapElement extends Element<TreemapConfig, TreemapOptions> {\n static readonly id = 'treemap'\n\n static override readonly defaults = {\n borderRadius: 0,\n borderWidth: 0,\n captions: {\n align: undefined,\n color: 'black',\n display: true,\n font: {},\n formatter: (ctx: TreemapScriptableContext) => {\n const label = ctx.raw._data?.label\n return ctx.raw.g || (typeof label === 'string' ? label : '')\n },\n overflow: 'ellipsis',\n padding: 3,\n textAlign: undefined,\n },\n labels: {\n align: 'center',\n color: 'black',\n display: false,\n font: {},\n formatter(ctx: TreemapScriptableContext) {\n const label = ctx.raw._data?.label\n if (ctx.raw.g) {\n return [ctx.raw.g, `${ctx.raw.v}`]\n }\n return typeof label === 'string' ? [label, `${ctx.raw.v}`] : `${ctx.raw.v}`\n },\n overflow: 'cut',\n padding: 3,\n position: 'middle',\n textAlign: undefined,\n wrap: false,\n },\n }\n\n static readonly descriptors = {\n _indexable: false,\n _scriptable: true,\n captions: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n labels: {\n _fallback: true,\n _scriptable: (name: string) => name !== 'formatter',\n },\n }\n\n static override readonly defaultRoutes = {\n backgroundColor: 'backgroundColor',\n borderColor: 'borderColor',\n }\n\n $context?: TreemapScriptableContext\n width: number | undefined\n height: number | undefined\n\n constructor(cfg?: Partial<TreemapConfig> & { options?: TreemapOptions }) {\n super()\n\n this.width = undefined\n this.height = undefined\n\n if (cfg) {\n Object.assign(this, cfg)\n }\n }\n\n draw(\n ctx: CanvasRenderingContext2D,\n data?: TreemapDataPoint,\n layout: TreemapLayoutOptions = layoutDefaults\n ) {\n if (!data) {\n return\n }\n const options = this.options\n const { inner, outer } = boundingRects(this)\n const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath\n\n ctx.save()\n\n if (outer.w !== inner.w || outer.h !== inner.h) {\n ctx.beginPath()\n addRectPath(ctx, outer)\n ctx.clip()\n addRectPath(ctx, inner)\n ctx.fillStyle = options.borderColor\n ctx.fill('evenodd')\n }\n\n ctx.beginPath()\n addRectPath(ctx, inner)\n ctx.fillStyle = options.backgroundColor\n ctx.fill()\n\n drawText(ctx, inner, options, data, this, layout)\n ctx.restore()\n }\n\n inRange(mouseX: number, mouseY: number, useFinalPosition?: boolean) {\n return inRange(this, mouseX, mouseY, useFinalPosition)\n }\n\n inXRange(mouseX: number, useFinalPosition?: boolean) {\n return inRange(this, mouseX, null, useFinalPosition)\n }\n\n inYRange(mouseY: number, useFinalPosition?: boolean) {\n return inRange(this, null, mouseY, useFinalPosition)\n }\n\n getCenterPoint(useFinalPosition?: boolean) {\n const { x, y, width, height } = this.getProps(['x', 'y', 'width', 'height'], useFinalPosition)\n return {\n x: x + width / 2,\n y: y + height / 2,\n }\n }\n\n override tooltipPosition() {\n return this.getCenterPoint()\n }\n}\n","import { Chart } from 'chart.js'\n\nimport TreemapController from './controller'\nimport TreemapElement from './element'\n\nChart.register(TreemapController as any, TreemapElement as any)\n\nexport type {\n LabelAlign,\n LabelOverflow,\n LabelPosition,\n TreemapConfig,\n TreemapControllerDatasetOptions,\n TreemapDataPoint,\n TreemapElement as TreemapElementType,\n TreemapOptions,\n} from './types'\n\nexport * from './utils'\nexport { TreemapController, TreemapElement }\n"],"names":["scaleRect","sq","xScale","yScale","sp","sp2","x","getPixelForValue","y","w","h","height","hidden","width","layoutDefaults","displayMode","rtl","spacing","limit","value","min","max","Math","parseBorderWidth","maxW","maxH","o","toTRBL","b","bottom","l","left","r","right","t","top","getDims","itm","w2","s2","key","a","_normalized","ar","d1","sqrt","d2","assignRow","rect","dims","sum","s","iw","_ix","getX","_iy","Rect","area","this","ih","dir","side","map","arr","nsum","row","get","maxd2","totd1","constructor","unsorted","getNewStat","sa","v","n","ratio","nmax","nmin","push","stat","_arr","Object","assign","setStat","StatArray","length","reset","_hist","Infinity","pushIf","fn","args","nstat","isOlderPart","act","req","startsWith","getGroupKey","lvl","String","hasGroupValue","scanTreeObject","keys","leafKey","obj","tree","result","objIndex","record","reduce","reduced","item","i","forEach","k","childKey","child","isObject","splice","normalizeTreeToArray","data","maxVal","element","ikeys","groupKey","getPath","groups","defaultValue","path","grp","join","resolveGroup","allGroups","groupIndex","idx","group","ensureGroup","tmp","groupValue","addKeys","tmpRef","values","mainGrp","mainValue","slice","create","ret","resolvedAllGroups","resolvedGroupIndex","itemGroup","g","label","children","ak","index","_idx","sort","requireVersion","pkg","ver","strict","parts","split","Number","parseInt","Error","compareAspectRatio","oldStat","newStat","os2","ns2","l2","or","toNodes","items","node","_data","vs","undefined","gs","sortNodes","nodes","widthCache","Map","shouldDrawCaption","options","display","toFont","font","lineHeight","padding","valueOrDefault","getCaptionHeight","captionHeight","drawText","ctx","layout","captions","labels","block","defined","isLeaf","content","resolveOption","formatter","callbackContext","align","color","hoverColor","overflow","wrap","maxWidth","maxHeight","fonts","hoverFont","optFont","active","Array","isArray","f","getFontFromOptions","lines","styles","toLines","labelSize","measureLines","lblToDraw","labelToDraw","isNumber","fitRatio","_lineHeight","size","floor","toFonts","rewrapped","trimmed","keptLines","keptStyles","used","fontFor","dropped","last","measureLabelSize","sliceTextToFitWidth","applyEllipsis","optColor","clipY","colors","textAlign","calculateBlockTop","labelBlock","oFont","text","resolveCaptionText","captionText","captionBlock","save","beginPath","clip","clipToPadding","lineAlign","calculateBlockLeft","calculateLineX","textBaseline","offset","line","style","string","fillStyle","fillText","drawTextBlock","restore","context","$context","raw","type","option","ellipsisWidth","currentWidth","lowerBoundLen","upperBoundLen","currentLen","slicedText","wrapToWidth","fits","pushWord","word","chunk","char","candidate","paragraphs","entry","paragraph","piece","fontsKey","prev","mapKey","_measureText","count","measureText","clear","set","position","buildHierarchy","gidx","parentGroupValue","glen","gdata","filter","_item","nextGroupIndex","defineProperty","configurable","writable","flattenNodes","flat","_children","layoutLevel","parentSum","rectangle","packInto","getSubRect","layoutNodes","applyHeaderBoxes","borderWidth","bw","subRect","buildNodes","input","registerTooltipPositioner","tooltipPlugin","registry","plugins","positioners","treemap","at","tooltipPosition","TreemapController","DatasetController","initialize","enableOptionSharing","super","getMinMax","scale","axis","configure","getMeta","r1","r2","_rect","_rectChanged","_layoutOptions","dataset","getDataset","buildOrUpdateElements","_resetNewElements","parse","meta","_parsed","elements","dataElementType","_start","_count","concat","sumKeys","fingerprint","_fingerprint","_nodes","_layoutDirty","getContext","mode","prototype","call","parsed","getParsed","getLabelAndValue","update","updateElements","rects","start","firstOpts","resolveDataElementOptions","sharedOptions","getSharedOptions","includeOptions","properties","updateElement","updateSharedOptions","draw","chartArea","chart","metadata","clipArea","ilen","unclipArea","datasetIndex","getBounds","useFinalPosition","getProps","boundingRects","bounds","border","radius","toTRBLCorners","maxR","bottomLeft","bottomRight","topLeft","topRight","parseBorderRadius","borderRadius","outer","inner","inRange","skipX","skipY","addNormalRectPath","id","version","defaults","animations","numbers","descriptors","_indexable","_scriptable","_fallback","name","overrides","hover","interaction","includeInvisible","intersect","tooltip","callbacks","title","scales","alignToPixels","reverse","beforeRegister","Chart","afterRegister","afterUnregister","TreemapElement","Element","addRectPath","addRoundedRectPath","borderColor","fill","backgroundColor","mouseX","mouseY","inXRange","inYRange","getCenterPoint","cfg","defaultRoutes","register","stack","res","next","pop"],"mappings":"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"}
|
package/dist/element.d.ts
CHANGED
|
@@ -11,7 +11,9 @@ export default class TreemapElement extends Element<TreemapConfig, TreemapOption
|
|
|
11
11
|
display: boolean;
|
|
12
12
|
font: {};
|
|
13
13
|
formatter: (ctx: TreemapScriptableContext) => string;
|
|
14
|
+
overflow: string;
|
|
14
15
|
padding: number;
|
|
16
|
+
textAlign: undefined;
|
|
15
17
|
};
|
|
16
18
|
labels: {
|
|
17
19
|
align: string;
|
|
@@ -22,6 +24,8 @@ export default class TreemapElement extends Element<TreemapConfig, TreemapOption
|
|
|
22
24
|
overflow: string;
|
|
23
25
|
padding: number;
|
|
24
26
|
position: string;
|
|
27
|
+
textAlign: undefined;
|
|
28
|
+
wrap: boolean;
|
|
25
29
|
};
|
|
26
30
|
};
|
|
27
31
|
static readonly descriptors: {
|
package/dist/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { BorderRadius, Chart, ChartComponent, Color, CoreChartOptions, Data
|
|
|
2
2
|
export type AnyObject = Record<string, unknown>;
|
|
3
3
|
export type LabelPosition = 'top' | 'middle' | 'bottom';
|
|
4
4
|
export type LabelAlign = 'left' | 'center' | 'right';
|
|
5
|
-
export type LabelOverflow = 'cut' | '
|
|
5
|
+
export type LabelOverflow = 'cut' | 'ellipsis' | 'fit' | 'hidden';
|
|
6
6
|
export type TreemapDisplayMode = 'containerBoxes' | 'headerBoxes';
|
|
7
7
|
export type TreemapBorderWidth = number | Partial<Record<'bottom' | 'left' | 'right' | 'top', number>>;
|
|
8
8
|
export type TreemapBorderRadius = Required<BorderRadius>;
|
|
@@ -13,6 +13,8 @@ export type TreemapScriptableContext = ScriptableContext<'treemap'> & {
|
|
|
13
13
|
export type TreemapFormatter<T> = T | ((context: TreemapScriptableContext) => T);
|
|
14
14
|
export type TreemapControllerDatasetCaptionsOptions = {
|
|
15
15
|
align?: Scriptable<LabelAlign, TreemapScriptableContext>;
|
|
16
|
+
overflow?: Scriptable<LabelOverflow, TreemapScriptableContext>;
|
|
17
|
+
textAlign?: Scriptable<LabelAlign, TreemapScriptableContext>;
|
|
16
18
|
color?: Scriptable<Color, TreemapScriptableContext>;
|
|
17
19
|
display?: boolean;
|
|
18
20
|
formatter?: TreemapFormatter<string>;
|
|
@@ -23,6 +25,8 @@ export type TreemapControllerDatasetCaptionsOptions = {
|
|
|
23
25
|
};
|
|
24
26
|
export type TreemapControllerDatasetLabelsOptions = {
|
|
25
27
|
align?: Scriptable<LabelAlign, TreemapScriptableContext>;
|
|
28
|
+
textAlign?: Scriptable<LabelAlign, TreemapScriptableContext>;
|
|
29
|
+
wrap?: boolean;
|
|
26
30
|
color?: Scriptable<Color | Color[], TreemapScriptableContext>;
|
|
27
31
|
display?: boolean;
|
|
28
32
|
formatter?: TreemapFormatter<string | string[]>;
|
|
@@ -35,6 +39,8 @@ export type TreemapControllerDatasetLabelsOptions = {
|
|
|
35
39
|
};
|
|
36
40
|
export type TreemapCaptionsOptions = {
|
|
37
41
|
align?: LabelAlign;
|
|
42
|
+
overflow?: LabelOverflow;
|
|
43
|
+
textAlign?: LabelAlign;
|
|
38
44
|
color: Color;
|
|
39
45
|
display?: boolean;
|
|
40
46
|
font: TreemapFontSpec;
|
|
@@ -45,6 +51,8 @@ export type TreemapCaptionsOptions = {
|
|
|
45
51
|
};
|
|
46
52
|
export type TreemapLabelsOptions = {
|
|
47
53
|
align: LabelAlign;
|
|
54
|
+
textAlign?: LabelAlign;
|
|
55
|
+
wrap?: boolean;
|
|
48
56
|
color: Color | Color[];
|
|
49
57
|
display?: boolean;
|
|
50
58
|
font: TreemapFontSpec | TreemapFontSpec[];
|
package/package.json
CHANGED