chartjs-chart-treemap 2.1.2 → 2.1.3

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,21 +1,11 @@
1
1
  /*!
2
- * chartjs-chart-treemap v2.1.2
2
+ * chartjs-chart-treemap v2.1.3
3
3
  * https://chartjs-chart-treemap.pages.dev/
4
4
  * (c) 2022 Jukka Kurkela
5
5
  * Released under the MIT license
6
6
  */
7
7
  import { Element, Chart, registry, DatasetController } from 'chart.js';
8
- import { isObject, addRoundedRectPath, toFont, isArray, toTRBL, toTRBLCorners, valueOrDefault, defined, clipArea, unclipArea } from 'chart.js/helpers';
9
-
10
- const getValue = (item) => isObject(item) ? item.v : item;
11
-
12
- const maxValue = (data) => data.reduce(function(m, v) {
13
- return (m > getValue(v) ? m : getValue(v));
14
- }, 0);
15
-
16
- const minValue = (data, mx) => data.reduce(function(m, v) {
17
- return (m < getValue(v) ? m : getValue(v));
18
- }, mx);
8
+ import { isObject, addRoundedRectPath, defined, toFont, isArray, toTRBL, toTRBLCorners, valueOrDefault, clipArea, unclipArea } from 'chart.js/helpers';
19
9
 
20
10
  const getGroupKey = (lvl) => '' + lvl;
21
11
 
@@ -192,18 +182,6 @@ function requireVersion(min, ver) {
192
182
  }
193
183
  }
194
184
 
195
- const rasterize = (v, dpr) => Math.round(v * dpr) / dpr;
196
-
197
- function rasterizeRect(rect, dpr) {
198
- return {
199
- ...rect,
200
- x: rasterize(rect.x, dpr),
201
- y: rasterize(rect.y, dpr),
202
- w: rasterize(rect.w, dpr),
203
- h: rasterize(rect.h, dpr),
204
- };
205
- }
206
-
207
185
  const widthCache = new Map();
208
186
 
209
187
  /**
@@ -245,20 +223,20 @@ function parseBorderRadius(value, maxW, maxH) {
245
223
  };
246
224
  }
247
225
 
248
- function boundingRects(rect, dpr) {
226
+ function boundingRects(rect) {
249
227
  const bounds = getBounds(rect);
250
228
  const width = bounds.right - bounds.left;
251
229
  const height = bounds.bottom - bounds.top;
252
230
  const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
253
231
  const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2);
254
- const outer = rasterizeRect({
232
+ const outer = {
255
233
  x: bounds.left,
256
234
  y: bounds.top,
257
235
  w: width,
258
236
  h: height,
259
237
  active: rect.active,
260
238
  radius
261
- }, dpr);
239
+ };
262
240
 
263
241
  return {
264
242
  outer,
@@ -318,7 +296,7 @@ function drawText(ctx, rect, options, item, levels) {
318
296
  ctx.beginPath();
319
297
  ctx.rect(rect.x, rect.y, rect.w, rect.h);
320
298
  ctx.clip();
321
- const isLeaf = (!('l' in item) || item.l === levels);
299
+ const isLeaf = item && (!defined(item.l) || item.l === levels);
322
300
  if (isLeaf && labels.display) {
323
301
  drawLabel(ctx, rect, options);
324
302
  } else if (!isLeaf && shouldDrawCaption(rect, captions)) {
@@ -472,12 +450,12 @@ class TreemapElement extends Element {
472
450
  }
473
451
  }
474
452
 
475
- draw(ctx, data, levels = 0, dpr) {
453
+ draw(ctx, data, levels = 0) {
476
454
  if (!data) {
477
455
  return;
478
456
  }
479
457
  const options = this.options;
480
- const {inner, outer} = boundingRects(this, dpr);
458
+ const {inner, outer} = boundingRects(this);
481
459
 
482
460
  const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
483
461
 
@@ -591,11 +569,11 @@ TreemapElement.defaultRoutes = {
591
569
  borderColor: 'borderColor'
592
570
  };
593
571
 
594
- function getDims(itm, w2, s2, key, dpr, maxd2) {
572
+ function getDims(itm, w2, s2, key) {
595
573
  const a = itm._normalized;
596
574
  const ar = w2 * a / s2;
597
- const d1 = rasterize(Math.sqrt(a * ar), dpr);
598
- const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
575
+ const d1 = Math.sqrt(a * ar);
576
+ const d2 = a / d1;
599
577
  const w = key === '_ix' ? d1 : d2;
600
578
  const h = key === '_ix' ? d2 : d1;
601
579
 
@@ -604,8 +582,8 @@ function getDims(itm, w2, s2, key, dpr, maxd2) {
604
582
 
605
583
  const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
606
584
 
607
- function buildRow(rect, itm, dims, sum, dpr) {
608
- const r = rasterizeRect({
585
+ function buildRow(rect, itm, dims, sum) {
586
+ const r = {
609
587
  x: getX(rect, dims.w),
610
588
  y: rect.y + rect._iy,
611
589
  w: dims.w,
@@ -614,7 +592,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
614
592
  v: itm.value,
615
593
  s: sum,
616
594
  _data: itm._data
617
- }, dpr);
595
+ };
618
596
  if (itm.group) {
619
597
  r.g = itm.group;
620
598
  r.l = itm.level;
@@ -624,8 +602,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
624
602
  }
625
603
 
626
604
  class Rect {
627
- constructor(r, dpr) {
628
- this.dpr = dpr;
605
+ constructor(r) {
629
606
  r = r || {w: 1, h: 1};
630
607
  this.rtl = !!r.rtl;
631
608
  this.x = r.x || r.left || 0;
@@ -654,61 +631,33 @@ class Rect {
654
631
  }
655
632
 
656
633
  get side() {
657
- return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
634
+ return this.dir === 'x' ? this.iw : this.ih;
658
635
  }
659
636
 
660
637
  map(arr) {
661
- const {dir, side, dpr} = this;
662
- const {key, d2prop, id2prop, d2key} = getPropNames(dir);
638
+ const {dir, side} = this;
639
+ const key = dir === 'x' ? '_ix' : '_iy';
663
640
  const sum = arr.nsum;
664
641
  const row = arr.get();
665
642
  const w2 = side * side;
666
- const availd2 = rasterize(this[id2prop], dpr);
667
643
  const s2 = sum * sum;
668
644
  const ret = [];
669
645
  let maxd2 = 0;
670
646
  let totd1 = 0;
671
647
  for (const itm of row) {
672
- const dims = getDims(itm, w2, s2, key, dpr, availd2);
648
+ const dims = getDims(itm, w2, s2, key);
673
649
  totd1 += dims.d1;
674
- maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
675
- ret.push(buildRow(this, itm, dims, arr.sum, dpr));
650
+ maxd2 = Math.max(maxd2, dims.d2);
651
+ ret.push(buildRow(this, itm, dims, arr.sum));
676
652
  this[key] += dims.d1;
677
653
  }
678
- // make sure all rects are same size in d2 direction
679
- for (const r of ret) {
680
- const d2 = r[d2prop];
681
- if (d2 !== maxd2) {
682
- if (this.rtl && dir === 'y') {
683
- // for RTL, x-coordinate needs to be adjusted too
684
- r.x -= maxd2 - d2;
685
- }
686
- r[d2prop] = maxd2;
687
- }
688
- }
689
- this[d2key] += maxd2;
654
+
655
+ this[dir === 'x' ? '_iy' : '_ix'] += maxd2;
690
656
  this[key] -= totd1;
691
657
  return ret;
692
658
  }
693
659
  }
694
660
 
695
- function getPropNames(dir) {
696
- if (dir === 'x') {
697
- return {
698
- key: '_ix',
699
- d2prop: 'h',
700
- id2prop: 'ih',
701
- d2key: '_iy'
702
- };
703
- }
704
- return {
705
- key: '_iy',
706
- d2prop: 'w',
707
- id2prop: 'iw',
708
- d2key: '_ix'
709
- };
710
- }
711
-
712
661
  const min = Math.min;
713
662
  const max = Math.max;
714
663
 
@@ -807,15 +756,14 @@ function compareAspectRatio(oldStat, newStat, args) {
807
756
  * @param {number[]|object[]} values
808
757
  * @param {object} rectangle
809
758
  * @param {string} [key]
810
- * @param {number} [dpr=1]
811
- * @param {*} [grp]
812
- * @param {*} [lvl]
813
- * @param {*} [gsum]
759
+ * @param {string} [grp]
760
+ * @param {number} [lvl]
761
+ * @param {number} [gsum]
814
762
  */
815
- function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
763
+ function squarify(values, rectangle, key, grp, lvl, gsum) {
816
764
  values = values || [];
817
765
  const rows = [];
818
- const rect = new Rect(rectangle, dpr);
766
+ const rect = new Rect(rectangle);
819
767
  const row = new StatArray('value', rect.area / sum(values, key));
820
768
  let length = rect.side;
821
769
  const n = values.length;
@@ -852,35 +800,58 @@ function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
852
800
  return flatten(rows);
853
801
  }
854
802
 
855
- var version = "2.1.2";
803
+ var version = "2.1.3";
804
+
805
+ function scaleRect(sq, xScale, yScale, sp) {
806
+ const sp2 = sp * 2;
807
+ const x = xScale.getPixelForValue(sq.x);
808
+ const y = yScale.getPixelForValue(sq.y);
809
+ const w = xScale.getPixelForValue(sq.x + sq.w) - x;
810
+ const h = yScale.getPixelForValue(sq.y + sq.h) - y;
811
+ return {
812
+ x: x + sp,
813
+ y: y + sp,
814
+ width: w - sp2,
815
+ height: h - sp2,
816
+ hidden: sp2 > w || sp2 > h,
817
+ };
818
+ }
856
819
 
857
820
  function rectNotEqual(r1, r2) {
858
821
  return !r1 || !r2
859
822
  || r1.x !== r2.x
860
823
  || r1.y !== r2.y
861
824
  || r1.w !== r2.w
862
- || r1.h !== r2.h;
825
+ || r1.h !== r2.h
826
+ || r1.rtl !== r2.rtl;
863
827
  }
864
828
 
865
- function arrayNotEqual(a1, a2) {
829
+ function arrayNotEqual(a, b) {
866
830
  let i, n;
867
831
 
868
- if (a1.lenght !== a2.length) {
832
+ if (!a || !b) {
833
+ return true;
834
+ }
835
+
836
+ if (a === b) {
837
+ return false;
838
+ }
839
+
840
+ if (a.length !== b.length) {
869
841
  return true;
870
842
  }
871
843
 
872
- for (i = 0, n = a1.length; i < n; ++i) {
873
- if (a1[i] !== a2[i]) {
844
+ for (i = 0, n = a.length; i < n; ++i) {
845
+ if (a[i] !== b[i]) {
874
846
  return true;
875
847
  }
876
848
  }
877
849
  return false;
878
850
  }
879
851
 
880
- function buildData(dataset, mainRect, dpr) {
852
+ function buildData(tree, dataset, mainRect) {
881
853
  const key = dataset.key || '';
882
854
  const treeLeafKey = dataset.treeLeafKey || '_leaf';
883
- let tree = dataset.tree || [];
884
855
  if (isObject(tree)) {
885
856
  tree = normalizeTreeToArray(key, treeLeafKey, tree);
886
857
  }
@@ -895,7 +866,7 @@ function buildData(dataset, mainRect, dpr) {
895
866
  const g = getGroupKey(groups[gidx]);
896
867
  const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
897
868
  const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
898
- const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
869
+ const gsq = squarify(gdata, rect, key, g, gidx, gs);
899
870
  const ret = gsq.slice();
900
871
  if (gidx < glen - 1) {
901
872
  gsq.forEach((sq) => {
@@ -911,44 +882,25 @@ function buildData(dataset, mainRect, dpr) {
911
882
  subRect.y += font.lineHeight + padding * 2;
912
883
  subRect.h -= font.lineHeight + padding * 2;
913
884
  }
914
- ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
885
+ ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
915
886
  });
916
887
  }
917
888
  return ret;
918
889
  }
919
890
 
920
- if (!tree.length && dataset.data.length) {
921
- tree = dataset.tree = dataset.data;
922
- }
923
-
924
891
  return glen
925
892
  ? recur(0, mainRect)
926
- : squarify(tree, mainRect, key, dpr);
927
- }
928
-
929
- function getMinMax(data, useTree) {
930
- const vMax = useTree ? 1 : maxValue(data);
931
- const vMin = useTree ? 0 : minValue(data, vMax);
932
- return {vMin, vMax};
933
- }
934
-
935
- function getArea({xScale, yScale}, data, rtl, useTree) {
936
- const {vMin, vMax} = getMinMax(data, useTree);
937
- const xMin = xScale.getPixelForValue(0);
938
- const xMax = xScale.getPixelForValue(1);
939
- const yMin = yScale.getPixelForValue(vMin);
940
- const yMax = yScale.getPixelForValue(vMax);
941
- return {x: xMin, y: yMax, w: xMax - xMin, h: yMin - yMax, rtl};
893
+ : squarify(tree, mainRect, key);
942
894
  }
943
895
 
944
896
  class TreemapController extends DatasetController {
945
897
  constructor(chart, datasetIndex) {
946
898
  super(chart, datasetIndex);
947
899
 
948
- this._rect = undefined;
949
- this._key = undefined;
950
900
  this._groups = undefined;
951
- this._useTree = undefined;
901
+ this._key = undefined;
902
+ this._rect = undefined;
903
+ this._rectChanged = true;
952
904
  }
953
905
 
954
906
  initialize() {
@@ -956,86 +908,93 @@ class TreemapController extends DatasetController {
956
908
  super.initialize();
957
909
  }
958
910
 
959
- /**
960
- * @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
961
- */
962
- updateRangeFromParsed(range, scale) {
963
- if (range.updated) {
911
+ getMinMax(scale) {
912
+ return {
913
+ min: 0,
914
+ max: scale.axis === 'x' ? scale.right - scale.left : scale.bottom - scale.top
915
+ };
916
+ }
917
+
918
+ configure() {
919
+ super.configure();
920
+ const {xScale, yScale} = this.getMeta();
921
+ if (!xScale || !yScale) {
922
+ // configure is called once before `linkScales`, and at that call we don't have any scales linked yet
964
923
  return;
965
924
  }
966
- range.updated = true;
967
- if (scale.axis === 'x') {
968
- range.min = 0;
969
- range.max = 1;
970
- return;
925
+
926
+ const w = xScale.right - xScale.left;
927
+ const h = yScale.bottom - yScale.top;
928
+ const rect = {x: 0, y: 0, w, h, rtl: !!this.options.rtl};
929
+
930
+ if (rectNotEqual(this._rect, rect)) {
931
+ this._rect = rect;
932
+ this._rectChanged = true;
933
+ }
934
+
935
+ if (this._rectChanged) {
936
+ xScale.max = w;
937
+ xScale.configure();
938
+ yScale.max = h;
939
+ yScale.configure();
971
940
  }
972
- const dataset = this.getDataset();
973
- const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
974
- range.min = vMin;
975
- range.max = vMax;
976
941
  }
977
942
 
978
943
  update(mode) {
979
- const meta = this.getMeta();
980
944
  const dataset = this.getDataset();
981
- const dpr = this.chart.currentDevicePixelRatio;
982
-
983
- if (!defined(this._useTree)) {
984
- this._useTree = !!dataset.tree;
985
- }
945
+ const {data} = this.getMeta();
986
946
  const groups = dataset.groups || (dataset.groups = []);
987
- const key = dataset.key || '';
988
- const rtl = !!dataset.rtl;
947
+ const key = dataset.key;
948
+ const tree = dataset.tree = dataset.tree || dataset.data || [];
989
949
 
990
- const mainRect = rasterizeRect(getArea(meta, dataset.data, rtl, this._useTree), dpr);
950
+ if (mode === 'reset') {
951
+ // reset is called before 2nd configure and is only called if animations are enabled. So wen need an extra configure call here.
952
+ this.configure();
953
+ }
991
954
 
992
- if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
993
- this._rect = mainRect;
955
+ if (this._rectChanged || this._key !== key || arrayNotEqual(this._groups, groups) || this._prevTree !== tree) {
994
956
  this._groups = groups.slice();
995
957
  this._key = key;
958
+ this._prevTree = tree;
959
+ this._rectChanged = false;
996
960
 
997
- dataset.data = buildData(dataset, mainRect, dpr);
961
+ dataset.data = buildData(tree, dataset, this._rect);
998
962
  // @ts-ignore using private stuff
999
963
  this._dataCheck();
1000
964
  // @ts-ignore using private stuff
1001
965
  this._resyncElements();
1002
966
  }
1003
967
 
1004
- this.updateElements(meta.data, 0, meta.data.length, mode);
968
+ this.updateElements(data, 0, data.length, mode);
1005
969
  }
1006
970
 
1007
971
  updateElements(rects, start, count, mode) {
1008
- const me = this;
1009
972
  const reset = mode === 'reset';
1010
- const dataset = me.getDataset();
1011
- const firstOpts = me._rect.options = me.resolveDataElementOptions(start, mode);
1012
- const sharedOptions = me.getSharedOptions(firstOpts);
1013
- const includeOptions = me.includeOptions(mode, sharedOptions);
973
+ const dataset = this.getDataset();
974
+ const firstOpts = this._rect.options = this.resolveDataElementOptions(start, mode);
975
+ const sharedOptions = this.getSharedOptions(firstOpts);
976
+ const includeOptions = this.includeOptions(mode, sharedOptions);
977
+ const {xScale, yScale} = this.getMeta(this.index);
1014
978
 
1015
979
  for (let i = start; i < start + count; i++) {
1016
- const sq = dataset.data[i];
1017
- const options = sharedOptions || me.resolveDataElementOptions(i, mode);
1018
- const sp = options.spacing;
1019
- const sp2 = sp * 2;
1020
- const properties = {
1021
- x: sq.x + sp,
1022
- y: sq.y + sp,
1023
- width: reset ? 0 : sq.w - sp2,
1024
- height: reset ? 0 : sq.h - sp2,
1025
- hidden: sp2 > sq.w || sp2 > sq.h,
1026
- };
980
+ const options = sharedOptions || this.resolveDataElementOptions(i, mode);
981
+ const properties = scaleRect(dataset.data[i], xScale, yScale, options.spacing);
982
+ if (reset) {
983
+ properties.width = 0;
984
+ properties.height = 0;
985
+ }
1027
986
 
1028
987
  if (includeOptions) {
1029
988
  properties.options = options;
1030
989
  }
1031
- me.updateElement(rects[i], i, properties, mode);
990
+ this.updateElement(rects[i], i, properties, mode);
1032
991
  }
1033
992
 
1034
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
993
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
1035
994
  }
1036
995
 
1037
996
  draw() {
1038
- const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
997
+ const {ctx, chartArea} = this.chart;
1039
998
  const metadata = this.getMeta().data || [];
1040
999
  const dataset = this.getDataset();
1041
1000
  const levels = (dataset.groups || []).length - 1;
@@ -1045,7 +1004,7 @@ class TreemapController extends DatasetController {
1045
1004
  for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
1046
1005
  const rect = metadata[i];
1047
1006
  if (!rect.hidden) {
1048
- rect.draw(ctx, data[i], levels, dpr);
1007
+ rect.draw(ctx, data[i], levels);
1049
1008
  }
1050
1009
  }
1051
1010
  unclipArea(ctx);
@@ -1106,11 +1065,16 @@ TreemapController.overrides = {
1106
1065
  scales: {
1107
1066
  x: {
1108
1067
  type: 'linear',
1068
+ alignToPixels: true,
1069
+ bounds: 'data',
1109
1070
  display: false
1110
1071
  },
1111
1072
  y: {
1112
1073
  type: 'linear',
1113
- display: false
1074
+ alignToPixels: true,
1075
+ bounds: 'data',
1076
+ display: false,
1077
+ reverse: true
1114
1078
  }
1115
1079
  },
1116
1080
  };
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * chartjs-chart-treemap v2.1.2
2
+ * chartjs-chart-treemap v2.1.3
3
3
  * https://chartjs-chart-treemap.pages.dev/
4
4
  * (c) 2022 Jukka Kurkela
5
5
  * Released under the MIT license
@@ -10,16 +10,6 @@ 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
- const getValue = (item) => helpers.isObject(item) ? item.v : item;
14
-
15
- const maxValue = (data) => data.reduce(function(m, v) {
16
- return (m > getValue(v) ? m : getValue(v));
17
- }, 0);
18
-
19
- const minValue = (data, mx) => data.reduce(function(m, v) {
20
- return (m < getValue(v) ? m : getValue(v));
21
- }, mx);
22
-
23
13
  const getGroupKey = (lvl) => '' + lvl;
24
14
 
25
15
  function scanTreeObject(key, treeLeafKey, obj, tree = [], lvl = 0, result = []) {
@@ -195,18 +185,6 @@ function requireVersion(min, ver) {
195
185
  }
196
186
  }
197
187
 
198
- const rasterize = (v, dpr) => Math.round(v * dpr) / dpr;
199
-
200
- function rasterizeRect(rect, dpr) {
201
- return {
202
- ...rect,
203
- x: rasterize(rect.x, dpr),
204
- y: rasterize(rect.y, dpr),
205
- w: rasterize(rect.w, dpr),
206
- h: rasterize(rect.h, dpr),
207
- };
208
- }
209
-
210
188
  const widthCache = new Map();
211
189
 
212
190
  /**
@@ -248,20 +226,20 @@ function parseBorderRadius(value, maxW, maxH) {
248
226
  };
249
227
  }
250
228
 
251
- function boundingRects(rect, dpr) {
229
+ function boundingRects(rect) {
252
230
  const bounds = getBounds(rect);
253
231
  const width = bounds.right - bounds.left;
254
232
  const height = bounds.bottom - bounds.top;
255
233
  const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
256
234
  const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2);
257
- const outer = rasterizeRect({
235
+ const outer = {
258
236
  x: bounds.left,
259
237
  y: bounds.top,
260
238
  w: width,
261
239
  h: height,
262
240
  active: rect.active,
263
241
  radius
264
- }, dpr);
242
+ };
265
243
 
266
244
  return {
267
245
  outer,
@@ -321,7 +299,7 @@ function drawText(ctx, rect, options, item, levels) {
321
299
  ctx.beginPath();
322
300
  ctx.rect(rect.x, rect.y, rect.w, rect.h);
323
301
  ctx.clip();
324
- const isLeaf = (!('l' in item) || item.l === levels);
302
+ const isLeaf = item && (!helpers.defined(item.l) || item.l === levels);
325
303
  if (isLeaf && labels.display) {
326
304
  drawLabel(ctx, rect, options);
327
305
  } else if (!isLeaf && shouldDrawCaption(rect, captions)) {
@@ -475,12 +453,12 @@ class TreemapElement extends chart_js.Element {
475
453
  }
476
454
  }
477
455
 
478
- draw(ctx, data, levels = 0, dpr) {
456
+ draw(ctx, data, levels = 0) {
479
457
  if (!data) {
480
458
  return;
481
459
  }
482
460
  const options = this.options;
483
- const {inner, outer} = boundingRects(this, dpr);
461
+ const {inner, outer} = boundingRects(this);
484
462
 
485
463
  const addRectPath = hasRadius(outer.radius) ? helpers.addRoundedRectPath : addNormalRectPath;
486
464
 
@@ -594,11 +572,11 @@ TreemapElement.defaultRoutes = {
594
572
  borderColor: 'borderColor'
595
573
  };
596
574
 
597
- function getDims(itm, w2, s2, key, dpr, maxd2) {
575
+ function getDims(itm, w2, s2, key) {
598
576
  const a = itm._normalized;
599
577
  const ar = w2 * a / s2;
600
- const d1 = rasterize(Math.sqrt(a * ar), dpr);
601
- const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
578
+ const d1 = Math.sqrt(a * ar);
579
+ const d2 = a / d1;
602
580
  const w = key === '_ix' ? d1 : d2;
603
581
  const h = key === '_ix' ? d2 : d1;
604
582
 
@@ -607,8 +585,8 @@ function getDims(itm, w2, s2, key, dpr, maxd2) {
607
585
 
608
586
  const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
609
587
 
610
- function buildRow(rect, itm, dims, sum, dpr) {
611
- const r = rasterizeRect({
588
+ function buildRow(rect, itm, dims, sum) {
589
+ const r = {
612
590
  x: getX(rect, dims.w),
613
591
  y: rect.y + rect._iy,
614
592
  w: dims.w,
@@ -617,7 +595,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
617
595
  v: itm.value,
618
596
  s: sum,
619
597
  _data: itm._data
620
- }, dpr);
598
+ };
621
599
  if (itm.group) {
622
600
  r.g = itm.group;
623
601
  r.l = itm.level;
@@ -627,8 +605,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
627
605
  }
628
606
 
629
607
  class Rect {
630
- constructor(r, dpr) {
631
- this.dpr = dpr;
608
+ constructor(r) {
632
609
  r = r || {w: 1, h: 1};
633
610
  this.rtl = !!r.rtl;
634
611
  this.x = r.x || r.left || 0;
@@ -657,61 +634,33 @@ class Rect {
657
634
  }
658
635
 
659
636
  get side() {
660
- return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
637
+ return this.dir === 'x' ? this.iw : this.ih;
661
638
  }
662
639
 
663
640
  map(arr) {
664
- const {dir, side, dpr} = this;
665
- const {key, d2prop, id2prop, d2key} = getPropNames(dir);
641
+ const {dir, side} = this;
642
+ const key = dir === 'x' ? '_ix' : '_iy';
666
643
  const sum = arr.nsum;
667
644
  const row = arr.get();
668
645
  const w2 = side * side;
669
- const availd2 = rasterize(this[id2prop], dpr);
670
646
  const s2 = sum * sum;
671
647
  const ret = [];
672
648
  let maxd2 = 0;
673
649
  let totd1 = 0;
674
650
  for (const itm of row) {
675
- const dims = getDims(itm, w2, s2, key, dpr, availd2);
651
+ const dims = getDims(itm, w2, s2, key);
676
652
  totd1 += dims.d1;
677
- maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
678
- ret.push(buildRow(this, itm, dims, arr.sum, dpr));
653
+ maxd2 = Math.max(maxd2, dims.d2);
654
+ ret.push(buildRow(this, itm, dims, arr.sum));
679
655
  this[key] += dims.d1;
680
656
  }
681
- // make sure all rects are same size in d2 direction
682
- for (const r of ret) {
683
- const d2 = r[d2prop];
684
- if (d2 !== maxd2) {
685
- if (this.rtl && dir === 'y') {
686
- // for RTL, x-coordinate needs to be adjusted too
687
- r.x -= maxd2 - d2;
688
- }
689
- r[d2prop] = maxd2;
690
- }
691
- }
692
- this[d2key] += maxd2;
657
+
658
+ this[dir === 'x' ? '_iy' : '_ix'] += maxd2;
693
659
  this[key] -= totd1;
694
660
  return ret;
695
661
  }
696
662
  }
697
663
 
698
- function getPropNames(dir) {
699
- if (dir === 'x') {
700
- return {
701
- key: '_ix',
702
- d2prop: 'h',
703
- id2prop: 'ih',
704
- d2key: '_iy'
705
- };
706
- }
707
- return {
708
- key: '_iy',
709
- d2prop: 'w',
710
- id2prop: 'iw',
711
- d2key: '_ix'
712
- };
713
- }
714
-
715
664
  const min = Math.min;
716
665
  const max = Math.max;
717
666
 
@@ -810,15 +759,14 @@ function compareAspectRatio(oldStat, newStat, args) {
810
759
  * @param {number[]|object[]} values
811
760
  * @param {object} rectangle
812
761
  * @param {string} [key]
813
- * @param {number} [dpr=1]
814
- * @param {*} [grp]
815
- * @param {*} [lvl]
816
- * @param {*} [gsum]
762
+ * @param {string} [grp]
763
+ * @param {number} [lvl]
764
+ * @param {number} [gsum]
817
765
  */
818
- function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
766
+ function squarify(values, rectangle, key, grp, lvl, gsum) {
819
767
  values = values || [];
820
768
  const rows = [];
821
- const rect = new Rect(rectangle, dpr);
769
+ const rect = new Rect(rectangle);
822
770
  const row = new StatArray('value', rect.area / sum(values, key));
823
771
  let length = rect.side;
824
772
  const n = values.length;
@@ -855,35 +803,58 @@ function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
855
803
  return flatten(rows);
856
804
  }
857
805
 
858
- var version = "2.1.2";
806
+ var version = "2.1.3";
807
+
808
+ function scaleRect(sq, xScale, yScale, sp) {
809
+ const sp2 = sp * 2;
810
+ const x = xScale.getPixelForValue(sq.x);
811
+ const y = yScale.getPixelForValue(sq.y);
812
+ const w = xScale.getPixelForValue(sq.x + sq.w) - x;
813
+ const h = yScale.getPixelForValue(sq.y + sq.h) - y;
814
+ return {
815
+ x: x + sp,
816
+ y: y + sp,
817
+ width: w - sp2,
818
+ height: h - sp2,
819
+ hidden: sp2 > w || sp2 > h,
820
+ };
821
+ }
859
822
 
860
823
  function rectNotEqual(r1, r2) {
861
824
  return !r1 || !r2
862
825
  || r1.x !== r2.x
863
826
  || r1.y !== r2.y
864
827
  || r1.w !== r2.w
865
- || r1.h !== r2.h;
828
+ || r1.h !== r2.h
829
+ || r1.rtl !== r2.rtl;
866
830
  }
867
831
 
868
- function arrayNotEqual(a1, a2) {
832
+ function arrayNotEqual(a, b) {
869
833
  let i, n;
870
834
 
871
- if (a1.lenght !== a2.length) {
835
+ if (!a || !b) {
836
+ return true;
837
+ }
838
+
839
+ if (a === b) {
840
+ return false;
841
+ }
842
+
843
+ if (a.length !== b.length) {
872
844
  return true;
873
845
  }
874
846
 
875
- for (i = 0, n = a1.length; i < n; ++i) {
876
- if (a1[i] !== a2[i]) {
847
+ for (i = 0, n = a.length; i < n; ++i) {
848
+ if (a[i] !== b[i]) {
877
849
  return true;
878
850
  }
879
851
  }
880
852
  return false;
881
853
  }
882
854
 
883
- function buildData(dataset, mainRect, dpr) {
855
+ function buildData(tree, dataset, mainRect) {
884
856
  const key = dataset.key || '';
885
857
  const treeLeafKey = dataset.treeLeafKey || '_leaf';
886
- let tree = dataset.tree || [];
887
858
  if (helpers.isObject(tree)) {
888
859
  tree = normalizeTreeToArray(key, treeLeafKey, tree);
889
860
  }
@@ -898,7 +869,7 @@ function buildData(dataset, mainRect, dpr) {
898
869
  const g = getGroupKey(groups[gidx]);
899
870
  const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
900
871
  const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
901
- const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
872
+ const gsq = squarify(gdata, rect, key, g, gidx, gs);
902
873
  const ret = gsq.slice();
903
874
  if (gidx < glen - 1) {
904
875
  gsq.forEach((sq) => {
@@ -914,44 +885,25 @@ function buildData(dataset, mainRect, dpr) {
914
885
  subRect.y += font.lineHeight + padding * 2;
915
886
  subRect.h -= font.lineHeight + padding * 2;
916
887
  }
917
- ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
888
+ ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
918
889
  });
919
890
  }
920
891
  return ret;
921
892
  }
922
893
 
923
- if (!tree.length && dataset.data.length) {
924
- tree = dataset.tree = dataset.data;
925
- }
926
-
927
894
  return glen
928
895
  ? recur(0, mainRect)
929
- : squarify(tree, mainRect, key, dpr);
930
- }
931
-
932
- function getMinMax(data, useTree) {
933
- const vMax = useTree ? 1 : maxValue(data);
934
- const vMin = useTree ? 0 : minValue(data, vMax);
935
- return {vMin, vMax};
936
- }
937
-
938
- function getArea({xScale, yScale}, data, rtl, useTree) {
939
- const {vMin, vMax} = getMinMax(data, useTree);
940
- const xMin = xScale.getPixelForValue(0);
941
- const xMax = xScale.getPixelForValue(1);
942
- const yMin = yScale.getPixelForValue(vMin);
943
- const yMax = yScale.getPixelForValue(vMax);
944
- return {x: xMin, y: yMax, w: xMax - xMin, h: yMin - yMax, rtl};
896
+ : squarify(tree, mainRect, key);
945
897
  }
946
898
 
947
899
  class TreemapController extends chart_js.DatasetController {
948
900
  constructor(chart, datasetIndex) {
949
901
  super(chart, datasetIndex);
950
902
 
951
- this._rect = undefined;
952
- this._key = undefined;
953
903
  this._groups = undefined;
954
- this._useTree = undefined;
904
+ this._key = undefined;
905
+ this._rect = undefined;
906
+ this._rectChanged = true;
955
907
  }
956
908
 
957
909
  initialize() {
@@ -959,86 +911,93 @@ class TreemapController extends chart_js.DatasetController {
959
911
  super.initialize();
960
912
  }
961
913
 
962
- /**
963
- * @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
964
- */
965
- updateRangeFromParsed(range, scale) {
966
- if (range.updated) {
914
+ getMinMax(scale) {
915
+ return {
916
+ min: 0,
917
+ max: scale.axis === 'x' ? scale.right - scale.left : scale.bottom - scale.top
918
+ };
919
+ }
920
+
921
+ configure() {
922
+ super.configure();
923
+ const {xScale, yScale} = this.getMeta();
924
+ if (!xScale || !yScale) {
925
+ // configure is called once before `linkScales`, and at that call we don't have any scales linked yet
967
926
  return;
968
927
  }
969
- range.updated = true;
970
- if (scale.axis === 'x') {
971
- range.min = 0;
972
- range.max = 1;
973
- return;
928
+
929
+ const w = xScale.right - xScale.left;
930
+ const h = yScale.bottom - yScale.top;
931
+ const rect = {x: 0, y: 0, w, h, rtl: !!this.options.rtl};
932
+
933
+ if (rectNotEqual(this._rect, rect)) {
934
+ this._rect = rect;
935
+ this._rectChanged = true;
936
+ }
937
+
938
+ if (this._rectChanged) {
939
+ xScale.max = w;
940
+ xScale.configure();
941
+ yScale.max = h;
942
+ yScale.configure();
974
943
  }
975
- const dataset = this.getDataset();
976
- const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
977
- range.min = vMin;
978
- range.max = vMax;
979
944
  }
980
945
 
981
946
  update(mode) {
982
- const meta = this.getMeta();
983
947
  const dataset = this.getDataset();
984
- const dpr = this.chart.currentDevicePixelRatio;
985
-
986
- if (!helpers.defined(this._useTree)) {
987
- this._useTree = !!dataset.tree;
988
- }
948
+ const {data} = this.getMeta();
989
949
  const groups = dataset.groups || (dataset.groups = []);
990
- const key = dataset.key || '';
991
- const rtl = !!dataset.rtl;
950
+ const key = dataset.key;
951
+ const tree = dataset.tree = dataset.tree || dataset.data || [];
992
952
 
993
- const mainRect = rasterizeRect(getArea(meta, dataset.data, rtl, this._useTree), dpr);
953
+ if (mode === 'reset') {
954
+ // reset is called before 2nd configure and is only called if animations are enabled. So wen need an extra configure call here.
955
+ this.configure();
956
+ }
994
957
 
995
- if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
996
- this._rect = mainRect;
958
+ if (this._rectChanged || this._key !== key || arrayNotEqual(this._groups, groups) || this._prevTree !== tree) {
997
959
  this._groups = groups.slice();
998
960
  this._key = key;
961
+ this._prevTree = tree;
962
+ this._rectChanged = false;
999
963
 
1000
- dataset.data = buildData(dataset, mainRect, dpr);
964
+ dataset.data = buildData(tree, dataset, this._rect);
1001
965
  // @ts-ignore using private stuff
1002
966
  this._dataCheck();
1003
967
  // @ts-ignore using private stuff
1004
968
  this._resyncElements();
1005
969
  }
1006
970
 
1007
- this.updateElements(meta.data, 0, meta.data.length, mode);
971
+ this.updateElements(data, 0, data.length, mode);
1008
972
  }
1009
973
 
1010
974
  updateElements(rects, start, count, mode) {
1011
- const me = this;
1012
975
  const reset = mode === 'reset';
1013
- const dataset = me.getDataset();
1014
- const firstOpts = me._rect.options = me.resolveDataElementOptions(start, mode);
1015
- const sharedOptions = me.getSharedOptions(firstOpts);
1016
- const includeOptions = me.includeOptions(mode, sharedOptions);
976
+ const dataset = this.getDataset();
977
+ const firstOpts = this._rect.options = this.resolveDataElementOptions(start, mode);
978
+ const sharedOptions = this.getSharedOptions(firstOpts);
979
+ const includeOptions = this.includeOptions(mode, sharedOptions);
980
+ const {xScale, yScale} = this.getMeta(this.index);
1017
981
 
1018
982
  for (let i = start; i < start + count; i++) {
1019
- const sq = dataset.data[i];
1020
- const options = sharedOptions || me.resolveDataElementOptions(i, mode);
1021
- const sp = options.spacing;
1022
- const sp2 = sp * 2;
1023
- const properties = {
1024
- x: sq.x + sp,
1025
- y: sq.y + sp,
1026
- width: reset ? 0 : sq.w - sp2,
1027
- height: reset ? 0 : sq.h - sp2,
1028
- hidden: sp2 > sq.w || sp2 > sq.h,
1029
- };
983
+ const options = sharedOptions || this.resolveDataElementOptions(i, mode);
984
+ const properties = scaleRect(dataset.data[i], xScale, yScale, options.spacing);
985
+ if (reset) {
986
+ properties.width = 0;
987
+ properties.height = 0;
988
+ }
1030
989
 
1031
990
  if (includeOptions) {
1032
991
  properties.options = options;
1033
992
  }
1034
- me.updateElement(rects[i], i, properties, mode);
993
+ this.updateElement(rects[i], i, properties, mode);
1035
994
  }
1036
995
 
1037
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
996
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
1038
997
  }
1039
998
 
1040
999
  draw() {
1041
- const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
1000
+ const {ctx, chartArea} = this.chart;
1042
1001
  const metadata = this.getMeta().data || [];
1043
1002
  const dataset = this.getDataset();
1044
1003
  const levels = (dataset.groups || []).length - 1;
@@ -1048,7 +1007,7 @@ class TreemapController extends chart_js.DatasetController {
1048
1007
  for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
1049
1008
  const rect = metadata[i];
1050
1009
  if (!rect.hidden) {
1051
- rect.draw(ctx, data[i], levels, dpr);
1010
+ rect.draw(ctx, data[i], levels);
1052
1011
  }
1053
1012
  }
1054
1013
  helpers.unclipArea(ctx);
@@ -1109,11 +1068,16 @@ TreemapController.overrides = {
1109
1068
  scales: {
1110
1069
  x: {
1111
1070
  type: 'linear',
1071
+ alignToPixels: true,
1072
+ bounds: 'data',
1112
1073
  display: false
1113
1074
  },
1114
1075
  y: {
1115
1076
  type: 'linear',
1116
- display: false
1077
+ alignToPixels: true,
1078
+ bounds: 'data',
1079
+ display: false,
1080
+ reverse: true
1117
1081
  }
1118
1082
  },
1119
1083
  };
@@ -1153,8 +1117,6 @@ exports.flatten = flatten;
1153
1117
  exports.getGroupKey = getGroupKey;
1154
1118
  exports.group = group;
1155
1119
  exports.index = index;
1156
- exports.maxValue = maxValue;
1157
- exports.minValue = minValue;
1158
1120
  exports.normalizeTreeToArray = normalizeTreeToArray;
1159
1121
  exports.requireVersion = requireVersion;
1160
1122
  exports.sort = sort;
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * chartjs-chart-treemap v2.1.2
2
+ * chartjs-chart-treemap v2.1.3
3
3
  * https://chartjs-chart-treemap.pages.dev/
4
4
  * (c) 2022 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";const i=t=>n.isObject(t)?t.v:t,r=t=>t.reduce((function(t,e){return t>i(e)?t:i(e)}),0),o=(t,e)=>t.reduce((function(t,e){return t<i(e)?t:i(e)}),e),s=t=>""+t;function a(t,e,i,r=[],o=0,l=[]){const h=o-1;if(t in i&&o>0){const n=r.reduce((function(t,e,n){return n!==h&&(t[s(n)]=e),t}),{});n[e]=r[h],n[t]=i[t],l.push(n)}else for(const s of Object.keys(i)){const h=i[s];n.isObject(h)&&(r.push(s),a(t,e,h,r,o+1,l))}return r.splice(h,1),l}function l(t,e,n){const i=a(t,e,n);if(!i.length)return i;const r=i.reduce((function(t,e){const n=Object.keys(e).length-2;return t>n?t:n}));return i.forEach((function(t){for(let e=0;e<r;e++){const n=s(e);t[n]||(t[n]="")}})),i}function h(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()}function u(t,e,n){if(!t.length)return;const i=[];for(const r of t){const t=e[r];if(""===t){i.push(n);break}i.push(t)}return i.length?i.join("."):n}function c(t,e,n,i,r,o,s=[]){const a=Object.create(null),l=Object.create(null),h=[];let c,d,p;for(d=0,p=t.length;d<p;++d){const h=t[d];r&&h[r]!==o||(c=h[e]||h[i]||"",c in a||(a[c]={value:0},l[c]=[]),a[c].value+=+h[n],a[c].label=h[e]||"",a[c].path=u(s,h,c),l[c].push(h))}return Object.keys(a).forEach((t=>{const i={children:l[t]};i[n]=+a[t].value,i[e]=a[t].label,i.label=t,i.path=a[t].path,r&&(i[r]=o),h.push(i)})),h}function d(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]={v:t[i],_idx:i};return e}function p(t,e){e?t.sort(((t,n)=>+n[e]-+t[e])):t.sort(((t,e)=>+e-+t))}function f(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 g(t,e){const n=e.split(".");if(!t.split(".").reduce(((t,e,i)=>t&&e<=n[i]),!0))throw new Error(`Chart.js v${e} is not supported. v${t} or newer is required.`)}const m=(t,e)=>Math.round(t*e)/e;function x(t,e){return{...t,x:m(t.x,e),y:m(t.y,e),w:m(t.w,e),h:m(t.h,e)}}const y=new Map;function b(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{left:n,top:i,right:n+r,bottom:i+o}}function v(t,e,n){return Math.max(Math.min(t,n),e)}function w(t,e,i){const r=n.toTRBL(t);return{t:v(r.top,0,i),r:v(r.right,0,e),b:v(r.bottom,0,i),l:v(r.left,0,e)}}function _(t,e){const i=b(t),r=i.right-i.left,o=i.bottom-i.top,s=w(t.options.borderWidth,r/2,o/2),a=function(t,e,i){const r=n.toTRBLCorners(t),o=Math.min(e,i);return{topLeft:v(r.topLeft,0,o),topRight:v(r.topRight,0,o),bottomLeft:v(r.bottomLeft,0,o),bottomRight:v(r.bottomRight,0,o)}}(t.options.borderRadius,r/2,o/2),l=x({x:i.left,y:i.top,w:r,h:o,active:t.active,radius:a},e);return{outer:l,inner:{x:l.x+s.l,y:l.y+s.t,w:l.w-s.l-s.r,h:l.h-s.t-s.b,active:t.active,radius:{topLeft:Math.max(0,a.topLeft-Math.max(s.t,s.l)),topRight:Math.max(0,a.topRight-Math.max(s.t,s.r)),bottomLeft:Math.max(0,a.bottomLeft-Math.max(s.b,s.l)),bottomRight:Math.max(0,a.bottomRight-Math.max(s.b,s.r))}}}}function M(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&b(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function k(t,e){t.rect(e.x,e.y,e.w,e.h)}function R(t,e){if(!e||!1===e.display)return!1;const{w:i,h:r}=t,o=n.toFont(e.font).lineHeight,s=v(2*n.valueOrDefault(e.padding,3),0,Math.min(i,r));return i-s>o&&r-s>o}function O(t,e,i,r,o){const{captions:s,labels:a}=i;t.save(),t.beginPath(),t.rect(e.x,e.y,e.w,e.h),t.clip();const l=!("l"in r)||r.l===o;l&&a.display?function(t,e,i){const r=i.labels,o=r.formatter;if(!o)return;const s=n.isArray(o)?o:[o],{font:a,hoverFont:l}=r,h=(e.active?l:a)||a,u=n.isArray(h)?h.map((t=>n.toFont(t))):[n.toFont(h)],c=function(t,e,n){const i=n.reduce((function(t,e){return t+=e.string}),""),r=e.join()+i+(t._measureText?"-spriting":"");if(!y.has(r)){t.save();const i=e.length;let o=0,s=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const a=e[r];o=Math.max(o,t.measureText(a).width),s+=i.lineHeight}t.restore(),y.set(r,{width:o,height:s})}return y.get(r)}(t,s,u);if(!function(t,e,n,i){const{overflow:r,padding:o}=n,{width:s,height:a}=i;if("hidden"===r)return!(s+2*o>e.w||a+2*o>e.h);return!0}(0,e,r,c))return;const{color:d,hoverColor:p,align:f}=r,g=(e.active?p:d)||d,m=n.isArray(g)?g:[g],x=function(t,e,n){const{align:i,position:r,padding:o}=e;let s,a;s=C(t,i,o),a="top"===r?t.y+o:"bottom"===r?t.y+t.h-o-n.height:t.y+(t.h-n.height)/2+o;return{x:s,y:a}}(e,r,c);t.textAlign=f,t.textBaseline="middle";let b=0;s.forEach((function(e,n){const i=m[Math.min(n,m.length-1)],r=u[Math.min(n,u.length-1)],o=r.lineHeight;t.font=r.string,t.fillStyle=i,t.fillText(e,x.x,x.y+o/2+b),b+=o}))}(t,e,i):!l&&R(e,s)&&function(t,e,i,r){const{captions:o,spacing:s,rtl:a}=i,{color:l,hoverColor:h,font:u,hoverFont:c,padding:d,align:p,formatter:f}=o,g=(e.active?h:l)||l,m=p||(a?"right":"left"),x=(e.active?c:u)||u,y=n.toFont(x),b=y.lineHeight/2,v=C(e,m,d);t.fillStyle=g,t.font=y.string,t.textAlign=m,t.textBaseline="middle",t.fillText(f||r.g,v,e.y+d+s+b)}(t,e,i,r),t.restore()}function C(t,e,n){return"left"===e?t.x+n:"right"===e?t.x+t.w-n:t.x+t.w/2}class j extends e.Element{constructor(t){super(),this.options=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t,e,i=0,r){if(!e)return;const o=this.options,{inner:s,outer:a}=_(this,r),l=(h=a.radius).topLeft||h.topRight||h.bottomLeft||h.bottomRight?n.addRoundedRectPath:k;var h;t.save(),a.w===s.w&&a.h===s.h||(t.beginPath(),l(t,a),t.clip(),l(t,s),t.fillStyle=o.borderColor,t.fill("evenodd")),t.beginPath(),l(t,s),t.fillStyle=o.backgroundColor,t.fill(),function(t,e,n,i){const r=n.dividers;if(!r.display||!i._data.children.length)return;const{x:o,y:s,w:a,h:l}=e,{lineColor:h,lineCapStyle:u,lineDash:c,lineDashOffset:d,lineWidth:p}=r;if(t.save(),t.strokeStyle=h,t.lineCap=u,t.setLineDash(c),t.lineDashOffset=d,t.lineWidth=p,t.beginPath(),a>l){const e=a/2;t.moveTo(o+e,s),t.lineTo(o+e,s+l)}else{const e=l/2;t.moveTo(o,s+e),t.lineTo(o+a,s+e)}t.stroke(),t.restore()}(t,s,o,e),O(t,s,o,e,i),t.restore()}inRange(t,e,n){return M(this,t,e,n)}inXRange(t,e){return M(this,t,null,e)}inYRange(t,e){return M(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()}getRange(t){return"x"===t?this.width/2:this.height/2}}function T(t,e,n,i,r,o){const s=t._normalized,a=e*s/n,l=m(Math.sqrt(s*a),r),h=Math.min(m(s/l,r),o);return{d1:l,d2:h,w:"_ix"===i?l:h,h:"_ix"===i?h:l}}j.id="treemap",j.defaults={label:void 0,borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>t.raw.g||t.raw._data.label||"",padding:3},dividers:{display:!1,lineCapStyle:"butt",lineColor:"black",lineDash:[],lineDashOffset:0,lineWidth:1},labels:{align:"center",color:"black",display:!1,font:{},formatter:t=>t.raw.g?[t.raw.g,t.raw.v+""]:t.raw._data.label?[t.raw._data.label,t.raw.v+""]:t.raw.v+"",overflow:"cut",position:"middle",padding:3},rtl:!1,spacing:.5},j.descriptors={labels:{_fallback:!0},captions:{_fallback:!0},_scriptable:!0,_indexable:!1},j.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};const P=(t,e)=>t.rtl?t.x+t.iw-e:t.x+t._ix;function D(t,e,n,i,r){const o=x({x:P(t,n.w),y:t.y+t._iy,w:n.w,h:n.h,a:e._normalized,v:e.value,s:i,_data:e._data},r);return e.group&&(o.g=e.group,o.l=e.level,o.gs=e.groupSum),o}class L{constructor(t,e){this.dpr=e,t=t||{w:1,h:1},this.rtl=!!t.rtl,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}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 m("x"===this.dir?this.iw:this.ih,this.dpr)}map(t){const{dir:e,side:n,dpr:i}=this,{key:r,d2prop:o,id2prop:s,d2key:a}=function(t){if("x"===t)return{key:"_ix",d2prop:"h",id2prop:"ih",d2key:"_iy"};return{key:"_iy",d2prop:"w",id2prop:"iw",d2key:"_ix"}}(e),l=t.nsum,h=t.get(),u=n*n,c=m(this[s],i),d=l*l,p=[];let f=0,g=0;for(const e of h){const n=T(e,u,d,r,i,c);g+=n.d1,f=Math.min(Math.max(f,n.d2),c),p.push(D(this,e,n,t.sum,i)),this[r]+=n.d1}for(const t of p){const n=t[o];n!==f&&(this.rtl&&"y"===e&&(t.x-=f-n),t[o]=f)}return this[a]+=f,this[r]-=g,p}}const S=Math.min,E=Math.max;function F(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{min:S(t.min,n),max:E(t.max,n),sum:t.sum+n,nmin:S(t.nmin,i),nmax:E(t.nmax,i),nsum:t.nsum+i}}function A(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class V{constructor(t,e){const n=this;n.key=t,n.ratio=e,n.reset()}get length(){return this._arr.length}reset(){const t=this;t._arr=[],t._hist=[],t.sum=0,t.nsum=0,t.min=1/0,t.max=-1/0,t.nmin=1/0,t.nmax=-1/0}push(t){A(this,t,F(this,t))}pushIf(t,e,...n){const i=F(this,t);if(!e((r=this,{min:r.min,max:r.max,sum:r.sum,nmin:r.nmin,nmax:r.nmax,nsum:r.nsum}),i,n))return t;var r;A(this,t,i)}get(){return this._arr}}function z(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 H(t,e,n,i=1,r,o,s){t=t||[];const a=[],l=new L(e,i),u=new V("value",l.area/f(t,n));let c=l.side;const g=t.length;let m,x;if(!g)return a;const y=t.slice();n=d(y,n),p(y,n);const b=t=>r&&y[t][r];for(m=0;m<g;++m)x={value:(v=m,n?+y[v][n]:+y[v]),groupSum:s,_data:t[y[m]._idx],level:void 0,group:void 0},r&&(x.level=o,x.group=b(m)),x=u.pushIf(x,z,c),x&&(a.push(l.map(u)),c=l.side,u.reset(),u.push(x));var v;return u.length&&a.push(l.map(u)),h(a)}function W(t,e){const n=e?1:r(t);return{vMin:e?0:o(t,n),vMax:n}}class q extends e.DatasetController{constructor(t,e){super(t,e),this._rect=void 0,this._key=void 0,this._groups=void 0,this._useTree=void 0}initialize(){this.enableOptionSharing=!0,super.initialize()}updateRangeFromParsed(t,e){if(t.updated)return;if(t.updated=!0,"x"===e.axis)return t.min=0,void(t.max=1);const n=this.getDataset(),{vMin:i,vMax:r}=W(n.data,this._useTree);t.min=i,t.max=r}update(t){const e=this.getMeta(),i=this.getDataset(),r=this.chart.currentDevicePixelRatio;n.defined(this._useTree)||(this._useTree=!!i.tree);const o=i.groups||(i.groups=[]),a=i.key||"",h=!!i.rtl,u=x(function({xScale:t,yScale:e},n,i,r){const{vMin:o,vMax:s}=W(n,r),a=t.getPixelForValue(0),l=t.getPixelForValue(1),h=e.getPixelForValue(o),u=e.getPixelForValue(s);return{x:a,y:u,w:l-a,h:h-u,rtl:i}}(e,i.data,h,this._useTree),r);var d,p;"reset"!==t&&(d=this._rect,p=u,d&&p&&d.x===p.x&&d.y===p.y&&d.w===p.w&&d.h===p.h)&&this._key===a&&!function(t,e){let n,i;if(t.lenght!==e.length)return!0;for(n=0,i=t.length;n<i;++n)if(t[n]!==e[n])return!0;return!1}(this._groups,o)||(this._rect=u,this._groups=o.slice(),this._key=a,i.data=function(t,e,i){const r=t.key||"",o=t.treeLeafKey||"_leaf";let a=t.tree||[];n.isObject(a)&&(a=l(r,o,a));const h=t.groups||[],u=h.length,d=n.valueOrDefault(t.spacing,0),p=t.captions||{},f=n.toFont(p.font),g=n.valueOrDefault(p.padding,3);return!a.length&&t.data.length&&(a=t.tree=t.data),u?function e(n,l,m,y){const b=s(h[n]),v=n>0&&s(h[n-1]),_=c(a,b,r,o,v,m,h.filter(((t,e)=>e<=n))),M=H(_,l,r,i,b,n,y),k=M.slice();return n<u-1&&M.forEach((r=>{const o=w(t.borderWidth,r.w/2,r.h/2),s={...l,x:r.x+d+o.l,y:r.y+d+o.t,w:r.w-2*d-o.l-o.r,h:r.h-2*d-o.t-o.b};R(s,p)&&(s.y+=f.lineHeight+2*g,s.h-=f.lineHeight+2*g),k.push(...e(n+1,x(s,i),r.g,r.s))})),k}(0,e):H(a,e,r,i)}(i,u,r),this._dataCheck(),this._resyncElements()),this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,n,i){const r=this,o="reset"===i,s=r.getDataset(),a=r._rect.options=r.resolveDataElementOptions(e,i),l=r.getSharedOptions(a),h=r.includeOptions(i,l);for(let a=e;a<e+n;a++){const e=s.data[a],n=l||r.resolveDataElementOptions(a,i),u=n.spacing,c=2*u,d={x:e.x+u,y:e.y+u,width:o?0:e.w-c,height:o?0:e.h-c,hidden:c>e.w||c>e.h};h&&(d.options=n),r.updateElement(t[a],a,d,i)}r.updateSharedOptions(l,i,a)}draw(){const{ctx:t,chartArea:e,currentDevicePixelRatio:i}=this.chart,r=this.getMeta().data||[],o=this.getDataset(),s=(o.groups||[]).length-1,a=o.data;n.clipArea(t,e);for(let e=0,n=r.length;e<n;++e){const n=r[e];n.hidden||n.draw(t,a[e],s,i)}n.unclipArea(t)}}q.id="treemap",q.version="2.1.2",q.defaults={dataElementType:"treemap",animations:{numbers:{type:"number",properties:["x","y","width","height"]}}},q.descriptors={_scriptable:!0,_indexable:!1},q.overrides={interaction:{mode:"point",includeInvisible:!0,intersect:!0},hover:{},plugins:{tooltip:{position:"treemap",intersect:!0,callbacks:{title(t){if(t.length){return t[0].dataset.key||""}return""},label(t){const e=t.dataset,n=e.data[t.dataIndex],i=n.g||n._data.label||e.label;return(i?i+": ":"")+n.v}}}},scales:{x:{type:"linear",display:!1},y:{type:"linear",display:!1}}},q.beforeRegister=function(){g("3.8",e.Chart.version)},q.afterRegister=function(){const t=e.registry.plugins.get("tooltip");t?t.positioners.treemap=function(t){if(!t.length)return!1;return t[t.length-1].element.tooltipPosition()}:console.warn("Unable to register the treemap positioner because tooltip plugin is not registered")},q.afterUnregister=function(){const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap},e.Chart.register(q,j),t.flatten=h,t.getGroupKey=s,t.group=c,t.index=d,t.maxValue=r,t.minValue=o,t.normalizeTreeToArray=l,t.requireVersion=g,t.sort=p,t.sum=f,Object.defineProperty(t,"__esModule",{value:!0})}));
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";const i=t=>""+t;function r(t,e,o,s=[],a=0,h=[]){const l=a-1;if(t in o&&a>0){const n=s.reduce((function(t,e,n){return n!==l&&(t[i(n)]=e),t}),{});n[e]=s[l],n[t]=o[t],h.push(n)}else for(const i of Object.keys(o)){const l=o[i];n.isObject(l)&&(s.push(i),r(t,e,l,s,a+1,h))}return s.splice(l,1),h}function o(t,e,n){const o=r(t,e,n);if(!o.length)return o;const s=o.reduce((function(t,e){const n=Object.keys(e).length-2;return t>n?t:n}));return o.forEach((function(t){for(let e=0;e<s;e++){const n=i(e);t[n]||(t[n]="")}})),o}function s(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()}function a(t,e,n){if(!t.length)return;const i=[];for(const r of t){const t=e[r];if(""===t){i.push(n);break}i.push(t)}return i.length?i.join("."):n}function h(t,e,n,i,r,o,s=[]){const h=Object.create(null),l=Object.create(null),u=[];let c,d,g;for(d=0,g=t.length;d<g;++d){const u=t[d];r&&u[r]!==o||(c=u[e]||u[i]||"",c in h||(h[c]={value:0},l[c]=[]),h[c].value+=+u[n],h[c].label=u[e]||"",h[c].path=a(s,u,c),l[c].push(u))}return Object.keys(h).forEach((t=>{const i={children:l[t]};i[n]=+h[t].value,i[e]=h[t].label,i.label=t,i.path=h[t].path,r&&(i[r]=o),u.push(i)})),u}function l(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]={v:t[i],_idx:i};return e}function u(t,e){e?t.sort(((t,n)=>+n[e]-+t[e])):t.sort(((t,e)=>+e-+t))}function c(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 d(t,e){const n=e.split(".");if(!t.split(".").reduce(((t,e,i)=>t&&e<=n[i]),!0))throw new Error(`Chart.js v${e} is not supported. v${t} or newer is required.`)}const g=new Map;function f(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{left:n,top:i,right:n+r,bottom:i+o}}function p(t,e,n){return Math.max(Math.min(t,n),e)}function m(t,e,i){const r=n.toTRBL(t);return{t:p(r.top,0,i),r:p(r.right,0,e),b:p(r.bottom,0,i),l:p(r.left,0,e)}}function x(t){const e=f(t),i=e.right-e.left,r=e.bottom-e.top,o=m(t.options.borderWidth,i/2,r/2),s=function(t,e,i){const r=n.toTRBLCorners(t),o=Math.min(e,i);return{topLeft:p(r.topLeft,0,o),topRight:p(r.topRight,0,o),bottomLeft:p(r.bottomLeft,0,o),bottomRight:p(r.bottomRight,0,o)}}(t.options.borderRadius,i/2,r/2),a={x:e.left,y:e.top,w:i,h:r,active:t.active,radius:s};return{outer:a,inner:{x:a.x+o.l,y:a.y+o.t,w:a.w-o.l-o.r,h:a.h-o.t-o.b,active:t.active,radius:{topLeft:Math.max(0,s.topLeft-Math.max(o.t,o.l)),topRight:Math.max(0,s.topRight-Math.max(o.t,o.r)),bottomLeft:Math.max(0,s.bottomLeft-Math.max(o.b,o.l)),bottomRight:Math.max(0,s.bottomRight-Math.max(o.b,o.r))}}}}function b(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&f(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function y(t,e){t.rect(e.x,e.y,e.w,e.h)}function v(t,e){if(!e||!1===e.display)return!1;const{w:i,h:r}=t,o=n.toFont(e.font).lineHeight,s=p(2*n.valueOrDefault(e.padding,3),0,Math.min(i,r));return i-s>o&&r-s>o}function w(t,e,i,r,o){const{captions:s,labels:a}=i;t.save(),t.beginPath(),t.rect(e.x,e.y,e.w,e.h),t.clip();const h=r&&(!n.defined(r.l)||r.l===o);h&&a.display?function(t,e,i){const r=i.labels,o=r.formatter;if(!o)return;const s=n.isArray(o)?o:[o],{font:a,hoverFont:h}=r,l=(e.active?h:a)||a,u=n.isArray(l)?l.map((t=>n.toFont(t))):[n.toFont(l)],c=function(t,e,n){const i=n.reduce((function(t,e){return t+=e.string}),""),r=e.join()+i+(t._measureText?"-spriting":"");if(!g.has(r)){t.save();const i=e.length;let o=0,s=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const a=e[r];o=Math.max(o,t.measureText(a).width),s+=i.lineHeight}t.restore(),g.set(r,{width:o,height:s})}return g.get(r)}(t,s,u);if(!function(t,e,n,i){const{overflow:r,padding:o}=n,{width:s,height:a}=i;if("hidden"===r)return!(s+2*o>e.w||a+2*o>e.h);return!0}(0,e,r,c))return;const{color:d,hoverColor:f,align:p}=r,m=(e.active?f:d)||d,x=n.isArray(m)?m:[m],b=function(t,e,n){const{align:i,position:r,padding:o}=e;let s,a;s=_(t,i,o),a="top"===r?t.y+o:"bottom"===r?t.y+t.h-o-n.height:t.y+(t.h-n.height)/2+o;return{x:s,y:a}}(e,r,c);t.textAlign=p,t.textBaseline="middle";let y=0;s.forEach((function(e,n){const i=x[Math.min(n,x.length-1)],r=u[Math.min(n,u.length-1)],o=r.lineHeight;t.font=r.string,t.fillStyle=i,t.fillText(e,b.x,b.y+o/2+y),y+=o}))}(t,e,i):!h&&v(e,s)&&function(t,e,i,r){const{captions:o,spacing:s,rtl:a}=i,{color:h,hoverColor:l,font:u,hoverFont:c,padding:d,align:g,formatter:f}=o,p=(e.active?l:h)||h,m=g||(a?"right":"left"),x=(e.active?c:u)||u,b=n.toFont(x),y=b.lineHeight/2,v=_(e,m,d);t.fillStyle=p,t.font=b.string,t.textAlign=m,t.textBaseline="middle",t.fillText(f||r.g,v,e.y+d+s+y)}(t,e,i,r),t.restore()}function _(t,e,n){return"left"===e?t.x+n:"right"===e?t.x+t.w-n:t.x+t.w/2}class M extends e.Element{constructor(t){super(),this.options=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t,e,i=0){if(!e)return;const r=this.options,{inner:o,outer:s}=x(this),a=(h=s.radius).topLeft||h.topRight||h.bottomLeft||h.bottomRight?n.addRoundedRectPath:y;var h;t.save(),s.w===o.w&&s.h===o.h||(t.beginPath(),a(t,s),t.clip(),a(t,o),t.fillStyle=r.borderColor,t.fill("evenodd")),t.beginPath(),a(t,o),t.fillStyle=r.backgroundColor,t.fill(),function(t,e,n,i){const r=n.dividers;if(!r.display||!i._data.children.length)return;const{x:o,y:s,w:a,h:h}=e,{lineColor:l,lineCapStyle:u,lineDash:c,lineDashOffset:d,lineWidth:g}=r;if(t.save(),t.strokeStyle=l,t.lineCap=u,t.setLineDash(c),t.lineDashOffset=d,t.lineWidth=g,t.beginPath(),a>h){const e=a/2;t.moveTo(o+e,s),t.lineTo(o+e,s+h)}else{const e=h/2;t.moveTo(o,s+e),t.lineTo(o+a,s+e)}t.stroke(),t.restore()}(t,o,r,e),w(t,o,r,e,i),t.restore()}inRange(t,e,n){return b(this,t,e,n)}inXRange(t,e){return b(this,t,null,e)}inYRange(t,e){return b(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()}getRange(t){return"x"===t?this.width/2:this.height/2}}function C(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,w:"_ix"===i?s:a,h:"_ix"===i?a:s}}M.id="treemap",M.defaults={label:void 0,borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>t.raw.g||t.raw._data.label||"",padding:3},dividers:{display:!1,lineCapStyle:"butt",lineColor:"black",lineDash:[],lineDashOffset:0,lineWidth:1},labels:{align:"center",color:"black",display:!1,font:{},formatter:t=>t.raw.g?[t.raw.g,t.raw.v+""]:t.raw._data.label?[t.raw._data.label,t.raw.v+""]:t.raw.v+"",overflow:"cut",position:"middle",padding:3},rtl:!1,spacing:.5},M.descriptors={labels:{_fallback:!0},captions:{_fallback:!0},_scriptable:!0,_indexable:!1},M.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};const k=(t,e)=>t.rtl?t.x+t.iw-e:t.x+t._ix;function O(t,e,n,i){const r={x:k(t,n.w),y:t.y+t._iy,w:n.w,h:n.h,a:e._normalized,v:e.value,s:i,_data:e._data};return e.group&&(r.g=e.group,r.l=e.level,r.gs=e.groupSum),r}class R{constructor(t){t=t||{w:1,h:1},this.rtl=!!t.rtl,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}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,a=r*r,h=[];let l=0,u=0;for(const e of o){const n=C(e,s,a,i);u+=n.d1,l=Math.max(l,n.d2),h.push(O(this,e,n,t.sum)),this[i]+=n.d1}return this["x"===e?"_iy":"_ix"]+=l,this[i]-=u,h}}const j=Math.min,T=Math.max;function P(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{min:j(t.min,n),max:T(t.max,n),sum:t.sum+n,nmin:j(t.nmin,i),nmax:T(t.nmax,i),nsum:t.nsum+i}}function S(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class D{constructor(t,e){const n=this;n.key=t,n.ratio=e,n.reset()}get length(){return this._arr.length}reset(){const t=this;t._arr=[],t._hist=[],t.sum=0,t.nsum=0,t.min=1/0,t.max=-1/0,t.nmin=1/0,t.nmax=-1/0}push(t){S(this,t,P(this,t))}pushIf(t,e,...n){const i=P(this,t);if(!e((r=this,{min:r.min,max:r.max,sum:r.sum,nmin:r.nmin,nmax:r.nmax,nsum:r.nsum}),i,n))return t;var r;S(this,t,i)}get(){return this._arr}}function L(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 E(t,e,n,i,r,o){t=t||[];const a=[],h=new R(e),d=new D("value",h.area/c(t,n));let g=h.side;const f=t.length;let p,m;if(!f)return a;const x=t.slice();n=l(x,n),u(x,n);const b=t=>i&&x[t][i];for(p=0;p<f;++p)m={value:(y=p,n?+x[y][n]:+x[y]),groupSum:o,_data:t[x[p]._idx],level:void 0,group:void 0},i&&(m.level=r,m.group=b(p)),m=d.pushIf(m,L,g),m&&(a.push(h.map(d)),g=h.side,d.reset(),d.push(m));var y;return d.length&&a.push(h.map(d)),s(a)}function A(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{x:o+i,y:s+i,width:a-r,height:h-r,hidden:r>a||r>h}}class F extends e.DatasetController{constructor(t,e){super(t,e),this._groups=void 0,this._key=void 0,this._rect=void 0,this._rectChanged=!0}initialize(){this.enableOptionSharing=!0,super.initialize()}getMinMax(t){return{min:0,max:"x"===t.axis?t.right-t.left:t.bottom-t.top}}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={x:0,y:0,w:n,h:i,rtl:!!this.options.rtl};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||(this._rect=r,this._rectChanged=!0),this._rectChanged&&(t.max=n,t.configure(),e.max=i,e.configure())}update(t){const e=this.getDataset(),{data:r}=this.getMeta(),s=e.groups||(e.groups=[]),a=e.key,l=e.tree=e.tree||e.data||[];"reset"===t&&this.configure(),(this._rectChanged||this._key!==a||function(t,e){let n,i;if(!t||!e)return!0;if(t===e)return!1;if(t.length!==e.length)return!0;for(n=0,i=t.length;n<i;++n)if(t[n]!==e[n])return!0;return!1}(this._groups,s)||this._prevTree!==l)&&(this._groups=s.slice(),this._key=a,this._prevTree=l,this._rectChanged=!1,e.data=function(t,e,r){const s=e.key||"",a=e.treeLeafKey||"_leaf";n.isObject(t)&&(t=o(s,a,t));const l=e.groups||[],u=l.length,c=n.valueOrDefault(e.spacing,0),d=e.captions||{},g=n.toFont(d.font),f=n.valueOrDefault(d.padding,3);return u?function n(r,o,p,x){const b=i(l[r]),y=r>0&&i(l[r-1]),w=h(t,b,s,a,y,p,l.filter(((t,e)=>e<=r))),_=E(w,o,s,b,r,x),M=_.slice();return r<u-1&&_.forEach((t=>{const i=m(e.borderWidth,t.w/2,t.h/2),s={...o,x:t.x+c+i.l,y:t.y+c+i.t,w:t.w-2*c-i.l-i.r,h:t.h-2*c-i.t-i.b};v(s,d)&&(s.y+=g.lineHeight+2*f,s.h-=g.lineHeight+2*f),M.push(...n(r+1,s,t.g,t.s))})),M}(0,r):E(t,r,s)}(l,e,this._rect),this._dataCheck(),this._resyncElements()),this.updateElements(r,0,r.length,t)}updateElements(t,e,n,i){const r="reset"===i,o=this.getDataset(),s=this._rect.options=this.resolveDataElementOptions(e,i),a=this.getSharedOptions(s),h=this.includeOptions(i,a),{xScale:l,yScale:u}=this.getMeta(this.index);for(let s=e;s<e+n;s++){const e=a||this.resolveDataElementOptions(s,i),n=A(o.data[s],l,u,e.spacing);r&&(n.width=0,n.height=0),h&&(n.options=e),this.updateElement(t[s],s,n,i)}this.updateSharedOptions(a,i,s)}draw(){const{ctx:t,chartArea:e}=this.chart,i=this.getMeta().data||[],r=this.getDataset(),o=(r.groups||[]).length-1,s=r.data;n.clipArea(t,e);for(let e=0,n=i.length;e<n;++e){const n=i[e];n.hidden||n.draw(t,s[e],o)}n.unclipArea(t)}}F.id="treemap",F.version="2.1.3",F.defaults={dataElementType:"treemap",animations:{numbers:{type:"number",properties:["x","y","width","height"]}}},F.descriptors={_scriptable:!0,_indexable:!1},F.overrides={interaction:{mode:"point",includeInvisible:!0,intersect:!0},hover:{},plugins:{tooltip:{position:"treemap",intersect:!0,callbacks:{title(t){if(t.length){return t[0].dataset.key||""}return""},label(t){const e=t.dataset,n=e.data[t.dataIndex],i=n.g||n._data.label||e.label;return(i?i+": ":"")+n.v}}}},scales:{x:{type:"linear",alignToPixels:!0,bounds:"data",display:!1},y:{type:"linear",alignToPixels:!0,bounds:"data",display:!1,reverse:!0}}},F.beforeRegister=function(){d("3.8",e.Chart.version)},F.afterRegister=function(){const t=e.registry.plugins.get("tooltip");t?t.positioners.treemap=function(t){if(!t.length)return!1;return t[t.length-1].element.tooltipPosition()}:console.warn("Unable to register the treemap positioner because tooltip plugin is not registered")},F.afterUnregister=function(){const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap},e.Chart.register(F,M),t.flatten=s,t.getGroupKey=i,t.group=h,t.index=l,t.normalizeTreeToArray=o,t.requireVersion=d,t.sort=u,t.sum=c,Object.defineProperty(t,"__esModule",{value:!0})}));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chartjs-chart-treemap",
3
3
  "homepage": "https://chartjs-chart-treemap.pages.dev/",
4
- "version": "2.1.2",
4
+ "version": "2.1.3",
5
5
  "description": "Chart.js module for creating treemap charts",
6
6
  "main": "dist/chartjs-chart-treemap.js",
7
7
  "module": "dist/chartjs-chart-treemap.esm.js",