chartjs-chart-treemap 2.1.1 → 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.1
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,19 +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,
237
+ active: rect.active,
259
238
  radius
260
- }, dpr);
239
+ };
261
240
 
262
241
  return {
263
242
  outer,
@@ -266,6 +245,7 @@ function boundingRects(rect, dpr) {
266
245
  y: outer.y + border.t,
267
246
  w: outer.w - border.l - border.r,
268
247
  h: outer.h - border.t - border.b,
248
+ active: rect.active,
269
249
  radius: {
270
250
  topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
271
251
  topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
@@ -316,7 +296,7 @@ function drawText(ctx, rect, options, item, levels) {
316
296
  ctx.beginPath();
317
297
  ctx.rect(rect.x, rect.y, rect.w, rect.h);
318
298
  ctx.clip();
319
- const isLeaf = (!('l' in item) || item.l === levels);
299
+ const isLeaf = item && (!defined(item.l) || item.l === levels);
320
300
  if (isLeaf && labels.display) {
321
301
  drawLabel(ctx, rect, options);
322
302
  } else if (!isLeaf && shouldDrawCaption(rect, captions)) {
@@ -470,12 +450,12 @@ class TreemapElement extends Element {
470
450
  }
471
451
  }
472
452
 
473
- draw(ctx, data, levels = 0, dpr) {
453
+ draw(ctx, data, levels = 0) {
474
454
  if (!data) {
475
455
  return;
476
456
  }
477
457
  const options = this.options;
478
- const {inner, outer} = boundingRects(this, dpr);
458
+ const {inner, outer} = boundingRects(this);
479
459
 
480
460
  const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
481
461
 
@@ -589,11 +569,11 @@ TreemapElement.defaultRoutes = {
589
569
  borderColor: 'borderColor'
590
570
  };
591
571
 
592
- function getDims(itm, w2, s2, key, dpr, maxd2) {
572
+ function getDims(itm, w2, s2, key) {
593
573
  const a = itm._normalized;
594
574
  const ar = w2 * a / s2;
595
- const d1 = rasterize(Math.sqrt(a * ar), dpr);
596
- const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
575
+ const d1 = Math.sqrt(a * ar);
576
+ const d2 = a / d1;
597
577
  const w = key === '_ix' ? d1 : d2;
598
578
  const h = key === '_ix' ? d2 : d1;
599
579
 
@@ -602,8 +582,8 @@ function getDims(itm, w2, s2, key, dpr, maxd2) {
602
582
 
603
583
  const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
604
584
 
605
- function buildRow(rect, itm, dims, sum, dpr) {
606
- const r = rasterizeRect({
585
+ function buildRow(rect, itm, dims, sum) {
586
+ const r = {
607
587
  x: getX(rect, dims.w),
608
588
  y: rect.y + rect._iy,
609
589
  w: dims.w,
@@ -612,7 +592,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
612
592
  v: itm.value,
613
593
  s: sum,
614
594
  _data: itm._data
615
- }, dpr);
595
+ };
616
596
  if (itm.group) {
617
597
  r.g = itm.group;
618
598
  r.l = itm.level;
@@ -622,8 +602,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
622
602
  }
623
603
 
624
604
  class Rect {
625
- constructor(r, dpr) {
626
- this.dpr = dpr;
605
+ constructor(r) {
627
606
  r = r || {w: 1, h: 1};
628
607
  this.rtl = !!r.rtl;
629
608
  this.x = r.x || r.left || 0;
@@ -652,61 +631,33 @@ class Rect {
652
631
  }
653
632
 
654
633
  get side() {
655
- return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
634
+ return this.dir === 'x' ? this.iw : this.ih;
656
635
  }
657
636
 
658
637
  map(arr) {
659
- const {dir, side, dpr} = this;
660
- const {key, d2prop, id2prop, d2key} = getPropNames(dir);
638
+ const {dir, side} = this;
639
+ const key = dir === 'x' ? '_ix' : '_iy';
661
640
  const sum = arr.nsum;
662
641
  const row = arr.get();
663
642
  const w2 = side * side;
664
- const availd2 = rasterize(this[id2prop], dpr);
665
643
  const s2 = sum * sum;
666
644
  const ret = [];
667
645
  let maxd2 = 0;
668
646
  let totd1 = 0;
669
647
  for (const itm of row) {
670
- const dims = getDims(itm, w2, s2, key, dpr, availd2);
648
+ const dims = getDims(itm, w2, s2, key);
671
649
  totd1 += dims.d1;
672
- maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
673
- 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));
674
652
  this[key] += dims.d1;
675
653
  }
676
- // make sure all rects are same size in d2 direction
677
- for (const r of ret) {
678
- const d2 = r[d2prop];
679
- if (d2 !== maxd2) {
680
- if (this.rtl && dir === 'y') {
681
- // for RTL, x-coordinate needs to be adjusted too
682
- r.x -= maxd2 - d2;
683
- }
684
- r[d2prop] = maxd2;
685
- }
686
- }
687
- this[d2key] += maxd2;
654
+
655
+ this[dir === 'x' ? '_iy' : '_ix'] += maxd2;
688
656
  this[key] -= totd1;
689
657
  return ret;
690
658
  }
691
659
  }
692
660
 
693
- function getPropNames(dir) {
694
- if (dir === 'x') {
695
- return {
696
- key: '_ix',
697
- d2prop: 'h',
698
- id2prop: 'ih',
699
- d2key: '_iy'
700
- };
701
- }
702
- return {
703
- key: '_iy',
704
- d2prop: 'w',
705
- id2prop: 'iw',
706
- d2key: '_ix'
707
- };
708
- }
709
-
710
661
  const min = Math.min;
711
662
  const max = Math.max;
712
663
 
@@ -805,15 +756,14 @@ function compareAspectRatio(oldStat, newStat, args) {
805
756
  * @param {number[]|object[]} values
806
757
  * @param {object} rectangle
807
758
  * @param {string} [key]
808
- * @param {number} [dpr=1]
809
- * @param {*} [grp]
810
- * @param {*} [lvl]
811
- * @param {*} [gsum]
759
+ * @param {string} [grp]
760
+ * @param {number} [lvl]
761
+ * @param {number} [gsum]
812
762
  */
813
- function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
763
+ function squarify(values, rectangle, key, grp, lvl, gsum) {
814
764
  values = values || [];
815
765
  const rows = [];
816
- const rect = new Rect(rectangle, dpr);
766
+ const rect = new Rect(rectangle);
817
767
  const row = new StatArray('value', rect.area / sum(values, key));
818
768
  let length = rect.side;
819
769
  const n = values.length;
@@ -850,35 +800,58 @@ function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
850
800
  return flatten(rows);
851
801
  }
852
802
 
853
- var version = "2.1.1";
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
+ }
854
819
 
855
820
  function rectNotEqual(r1, r2) {
856
821
  return !r1 || !r2
857
822
  || r1.x !== r2.x
858
823
  || r1.y !== r2.y
859
824
  || r1.w !== r2.w
860
- || r1.h !== r2.h;
825
+ || r1.h !== r2.h
826
+ || r1.rtl !== r2.rtl;
861
827
  }
862
828
 
863
- function arrayNotEqual(a1, a2) {
829
+ function arrayNotEqual(a, b) {
864
830
  let i, n;
865
831
 
866
- 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) {
867
841
  return true;
868
842
  }
869
843
 
870
- for (i = 0, n = a1.length; i < n; ++i) {
871
- if (a1[i] !== a2[i]) {
844
+ for (i = 0, n = a.length; i < n; ++i) {
845
+ if (a[i] !== b[i]) {
872
846
  return true;
873
847
  }
874
848
  }
875
849
  return false;
876
850
  }
877
851
 
878
- function buildData(dataset, mainRect, dpr) {
852
+ function buildData(tree, dataset, mainRect) {
879
853
  const key = dataset.key || '';
880
854
  const treeLeafKey = dataset.treeLeafKey || '_leaf';
881
- let tree = dataset.tree || [];
882
855
  if (isObject(tree)) {
883
856
  tree = normalizeTreeToArray(key, treeLeafKey, tree);
884
857
  }
@@ -893,7 +866,7 @@ function buildData(dataset, mainRect, dpr) {
893
866
  const g = getGroupKey(groups[gidx]);
894
867
  const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
895
868
  const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
896
- const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
869
+ const gsq = squarify(gdata, rect, key, g, gidx, gs);
897
870
  const ret = gsq.slice();
898
871
  if (gidx < glen - 1) {
899
872
  gsq.forEach((sq) => {
@@ -909,44 +882,25 @@ function buildData(dataset, mainRect, dpr) {
909
882
  subRect.y += font.lineHeight + padding * 2;
910
883
  subRect.h -= font.lineHeight + padding * 2;
911
884
  }
912
- ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
885
+ ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
913
886
  });
914
887
  }
915
888
  return ret;
916
889
  }
917
890
 
918
- if (!tree.length && dataset.data.length) {
919
- tree = dataset.tree = dataset.data;
920
- }
921
-
922
891
  return glen
923
892
  ? recur(0, mainRect)
924
- : squarify(tree, mainRect, key, dpr);
925
- }
926
-
927
- function getMinMax(data, useTree) {
928
- const vMax = useTree ? 1 : maxValue(data);
929
- const vMin = useTree ? 0 : minValue(data, vMax);
930
- return {vMin, vMax};
931
- }
932
-
933
- function getArea({xScale, yScale}, data, rtl, useTree) {
934
- const {vMin, vMax} = getMinMax(data, useTree);
935
- const xMin = xScale.getPixelForValue(0);
936
- const xMax = xScale.getPixelForValue(1);
937
- const yMin = yScale.getPixelForValue(vMin);
938
- const yMax = yScale.getPixelForValue(vMax);
939
- return {x: xMin, y: yMax, w: xMax - xMin, h: yMin - yMax, rtl};
893
+ : squarify(tree, mainRect, key);
940
894
  }
941
895
 
942
896
  class TreemapController extends DatasetController {
943
897
  constructor(chart, datasetIndex) {
944
898
  super(chart, datasetIndex);
945
899
 
946
- this._rect = undefined;
947
- this._key = undefined;
948
900
  this._groups = undefined;
949
- this._useTree = undefined;
901
+ this._key = undefined;
902
+ this._rect = undefined;
903
+ this._rectChanged = true;
950
904
  }
951
905
 
952
906
  initialize() {
@@ -954,86 +908,93 @@ class TreemapController extends DatasetController {
954
908
  super.initialize();
955
909
  }
956
910
 
957
- /**
958
- * @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
959
- */
960
- updateRangeFromParsed(range, scale) {
961
- 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
962
923
  return;
963
924
  }
964
- range.updated = true;
965
- if (scale.axis === 'x') {
966
- range.min = 0;
967
- range.max = 1;
968
- 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();
969
940
  }
970
- const dataset = this.getDataset();
971
- const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
972
- range.min = vMin;
973
- range.max = vMax;
974
941
  }
975
942
 
976
943
  update(mode) {
977
- const meta = this.getMeta();
978
944
  const dataset = this.getDataset();
979
- const dpr = this.chart.currentDevicePixelRatio;
980
-
981
- if (!defined(this._useTree)) {
982
- this._useTree = !!dataset.tree;
983
- }
945
+ const {data} = this.getMeta();
984
946
  const groups = dataset.groups || (dataset.groups = []);
985
- const key = dataset.key || '';
986
- const rtl = !!dataset.rtl;
947
+ const key = dataset.key;
948
+ const tree = dataset.tree = dataset.tree || dataset.data || [];
987
949
 
988
- 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
+ }
989
954
 
990
- if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
991
- this._rect = mainRect;
955
+ if (this._rectChanged || this._key !== key || arrayNotEqual(this._groups, groups) || this._prevTree !== tree) {
992
956
  this._groups = groups.slice();
993
957
  this._key = key;
958
+ this._prevTree = tree;
959
+ this._rectChanged = false;
994
960
 
995
- dataset.data = buildData(dataset, mainRect, dpr);
961
+ dataset.data = buildData(tree, dataset, this._rect);
996
962
  // @ts-ignore using private stuff
997
963
  this._dataCheck();
998
964
  // @ts-ignore using private stuff
999
965
  this._resyncElements();
1000
966
  }
1001
967
 
1002
- this.updateElements(meta.data, 0, meta.data.length, mode);
968
+ this.updateElements(data, 0, data.length, mode);
1003
969
  }
1004
970
 
1005
971
  updateElements(rects, start, count, mode) {
1006
- const me = this;
1007
972
  const reset = mode === 'reset';
1008
- const dataset = me.getDataset();
1009
- const firstOpts = me._rect.options = me.resolveDataElementOptions(start, mode);
1010
- const sharedOptions = me.getSharedOptions(firstOpts);
1011
- 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);
1012
978
 
1013
979
  for (let i = start; i < start + count; i++) {
1014
- const sq = dataset.data[i];
1015
- const options = sharedOptions || me.resolveDataElementOptions(i, mode);
1016
- const sp = options.spacing;
1017
- const sp2 = sp * 2;
1018
- const properties = {
1019
- x: sq.x + sp,
1020
- y: sq.y + sp,
1021
- width: reset ? 0 : sq.w - sp2,
1022
- height: reset ? 0 : sq.h - sp2,
1023
- hidden: sp2 > sq.w || sp2 > sq.h,
1024
- };
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
+ }
1025
986
 
1026
987
  if (includeOptions) {
1027
988
  properties.options = options;
1028
989
  }
1029
- me.updateElement(rects[i], i, properties, mode);
990
+ this.updateElement(rects[i], i, properties, mode);
1030
991
  }
1031
992
 
1032
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
993
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
1033
994
  }
1034
995
 
1035
996
  draw() {
1036
- const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
997
+ const {ctx, chartArea} = this.chart;
1037
998
  const metadata = this.getMeta().data || [];
1038
999
  const dataset = this.getDataset();
1039
1000
  const levels = (dataset.groups || []).length - 1;
@@ -1043,7 +1004,7 @@ class TreemapController extends DatasetController {
1043
1004
  for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
1044
1005
  const rect = metadata[i];
1045
1006
  if (!rect.hidden) {
1046
- rect.draw(ctx, data[i], levels, dpr);
1007
+ rect.draw(ctx, data[i], levels);
1047
1008
  }
1048
1009
  }
1049
1010
  unclipArea(ctx);
@@ -1104,11 +1065,16 @@ TreemapController.overrides = {
1104
1065
  scales: {
1105
1066
  x: {
1106
1067
  type: 'linear',
1068
+ alignToPixels: true,
1069
+ bounds: 'data',
1107
1070
  display: false
1108
1071
  },
1109
1072
  y: {
1110
1073
  type: 'linear',
1111
- display: false
1074
+ alignToPixels: true,
1075
+ bounds: 'data',
1076
+ display: false,
1077
+ reverse: true
1112
1078
  }
1113
1079
  },
1114
1080
  };
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * chartjs-chart-treemap v2.1.1
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,19 +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,
240
+ active: rect.active,
262
241
  radius
263
- }, dpr);
242
+ };
264
243
 
265
244
  return {
266
245
  outer,
@@ -269,6 +248,7 @@ function boundingRects(rect, dpr) {
269
248
  y: outer.y + border.t,
270
249
  w: outer.w - border.l - border.r,
271
250
  h: outer.h - border.t - border.b,
251
+ active: rect.active,
272
252
  radius: {
273
253
  topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
274
254
  topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
@@ -319,7 +299,7 @@ function drawText(ctx, rect, options, item, levels) {
319
299
  ctx.beginPath();
320
300
  ctx.rect(rect.x, rect.y, rect.w, rect.h);
321
301
  ctx.clip();
322
- const isLeaf = (!('l' in item) || item.l === levels);
302
+ const isLeaf = item && (!helpers.defined(item.l) || item.l === levels);
323
303
  if (isLeaf && labels.display) {
324
304
  drawLabel(ctx, rect, options);
325
305
  } else if (!isLeaf && shouldDrawCaption(rect, captions)) {
@@ -473,12 +453,12 @@ class TreemapElement extends chart_js.Element {
473
453
  }
474
454
  }
475
455
 
476
- draw(ctx, data, levels = 0, dpr) {
456
+ draw(ctx, data, levels = 0) {
477
457
  if (!data) {
478
458
  return;
479
459
  }
480
460
  const options = this.options;
481
- const {inner, outer} = boundingRects(this, dpr);
461
+ const {inner, outer} = boundingRects(this);
482
462
 
483
463
  const addRectPath = hasRadius(outer.radius) ? helpers.addRoundedRectPath : addNormalRectPath;
484
464
 
@@ -592,11 +572,11 @@ TreemapElement.defaultRoutes = {
592
572
  borderColor: 'borderColor'
593
573
  };
594
574
 
595
- function getDims(itm, w2, s2, key, dpr, maxd2) {
575
+ function getDims(itm, w2, s2, key) {
596
576
  const a = itm._normalized;
597
577
  const ar = w2 * a / s2;
598
- const d1 = rasterize(Math.sqrt(a * ar), dpr);
599
- const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
578
+ const d1 = Math.sqrt(a * ar);
579
+ const d2 = a / d1;
600
580
  const w = key === '_ix' ? d1 : d2;
601
581
  const h = key === '_ix' ? d2 : d1;
602
582
 
@@ -605,8 +585,8 @@ function getDims(itm, w2, s2, key, dpr, maxd2) {
605
585
 
606
586
  const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
607
587
 
608
- function buildRow(rect, itm, dims, sum, dpr) {
609
- const r = rasterizeRect({
588
+ function buildRow(rect, itm, dims, sum) {
589
+ const r = {
610
590
  x: getX(rect, dims.w),
611
591
  y: rect.y + rect._iy,
612
592
  w: dims.w,
@@ -615,7 +595,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
615
595
  v: itm.value,
616
596
  s: sum,
617
597
  _data: itm._data
618
- }, dpr);
598
+ };
619
599
  if (itm.group) {
620
600
  r.g = itm.group;
621
601
  r.l = itm.level;
@@ -625,8 +605,7 @@ function buildRow(rect, itm, dims, sum, dpr) {
625
605
  }
626
606
 
627
607
  class Rect {
628
- constructor(r, dpr) {
629
- this.dpr = dpr;
608
+ constructor(r) {
630
609
  r = r || {w: 1, h: 1};
631
610
  this.rtl = !!r.rtl;
632
611
  this.x = r.x || r.left || 0;
@@ -655,61 +634,33 @@ class Rect {
655
634
  }
656
635
 
657
636
  get side() {
658
- return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
637
+ return this.dir === 'x' ? this.iw : this.ih;
659
638
  }
660
639
 
661
640
  map(arr) {
662
- const {dir, side, dpr} = this;
663
- const {key, d2prop, id2prop, d2key} = getPropNames(dir);
641
+ const {dir, side} = this;
642
+ const key = dir === 'x' ? '_ix' : '_iy';
664
643
  const sum = arr.nsum;
665
644
  const row = arr.get();
666
645
  const w2 = side * side;
667
- const availd2 = rasterize(this[id2prop], dpr);
668
646
  const s2 = sum * sum;
669
647
  const ret = [];
670
648
  let maxd2 = 0;
671
649
  let totd1 = 0;
672
650
  for (const itm of row) {
673
- const dims = getDims(itm, w2, s2, key, dpr, availd2);
651
+ const dims = getDims(itm, w2, s2, key);
674
652
  totd1 += dims.d1;
675
- maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
676
- 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));
677
655
  this[key] += dims.d1;
678
656
  }
679
- // make sure all rects are same size in d2 direction
680
- for (const r of ret) {
681
- const d2 = r[d2prop];
682
- if (d2 !== maxd2) {
683
- if (this.rtl && dir === 'y') {
684
- // for RTL, x-coordinate needs to be adjusted too
685
- r.x -= maxd2 - d2;
686
- }
687
- r[d2prop] = maxd2;
688
- }
689
- }
690
- this[d2key] += maxd2;
657
+
658
+ this[dir === 'x' ? '_iy' : '_ix'] += maxd2;
691
659
  this[key] -= totd1;
692
660
  return ret;
693
661
  }
694
662
  }
695
663
 
696
- function getPropNames(dir) {
697
- if (dir === 'x') {
698
- return {
699
- key: '_ix',
700
- d2prop: 'h',
701
- id2prop: 'ih',
702
- d2key: '_iy'
703
- };
704
- }
705
- return {
706
- key: '_iy',
707
- d2prop: 'w',
708
- id2prop: 'iw',
709
- d2key: '_ix'
710
- };
711
- }
712
-
713
664
  const min = Math.min;
714
665
  const max = Math.max;
715
666
 
@@ -808,15 +759,14 @@ function compareAspectRatio(oldStat, newStat, args) {
808
759
  * @param {number[]|object[]} values
809
760
  * @param {object} rectangle
810
761
  * @param {string} [key]
811
- * @param {number} [dpr=1]
812
- * @param {*} [grp]
813
- * @param {*} [lvl]
814
- * @param {*} [gsum]
762
+ * @param {string} [grp]
763
+ * @param {number} [lvl]
764
+ * @param {number} [gsum]
815
765
  */
816
- function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
766
+ function squarify(values, rectangle, key, grp, lvl, gsum) {
817
767
  values = values || [];
818
768
  const rows = [];
819
- const rect = new Rect(rectangle, dpr);
769
+ const rect = new Rect(rectangle);
820
770
  const row = new StatArray('value', rect.area / sum(values, key));
821
771
  let length = rect.side;
822
772
  const n = values.length;
@@ -853,35 +803,58 @@ function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
853
803
  return flatten(rows);
854
804
  }
855
805
 
856
- var version = "2.1.1";
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
+ }
857
822
 
858
823
  function rectNotEqual(r1, r2) {
859
824
  return !r1 || !r2
860
825
  || r1.x !== r2.x
861
826
  || r1.y !== r2.y
862
827
  || r1.w !== r2.w
863
- || r1.h !== r2.h;
828
+ || r1.h !== r2.h
829
+ || r1.rtl !== r2.rtl;
864
830
  }
865
831
 
866
- function arrayNotEqual(a1, a2) {
832
+ function arrayNotEqual(a, b) {
867
833
  let i, n;
868
834
 
869
- 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) {
870
844
  return true;
871
845
  }
872
846
 
873
- for (i = 0, n = a1.length; i < n; ++i) {
874
- if (a1[i] !== a2[i]) {
847
+ for (i = 0, n = a.length; i < n; ++i) {
848
+ if (a[i] !== b[i]) {
875
849
  return true;
876
850
  }
877
851
  }
878
852
  return false;
879
853
  }
880
854
 
881
- function buildData(dataset, mainRect, dpr) {
855
+ function buildData(tree, dataset, mainRect) {
882
856
  const key = dataset.key || '';
883
857
  const treeLeafKey = dataset.treeLeafKey || '_leaf';
884
- let tree = dataset.tree || [];
885
858
  if (helpers.isObject(tree)) {
886
859
  tree = normalizeTreeToArray(key, treeLeafKey, tree);
887
860
  }
@@ -896,7 +869,7 @@ function buildData(dataset, mainRect, dpr) {
896
869
  const g = getGroupKey(groups[gidx]);
897
870
  const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
898
871
  const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
899
- const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
872
+ const gsq = squarify(gdata, rect, key, g, gidx, gs);
900
873
  const ret = gsq.slice();
901
874
  if (gidx < glen - 1) {
902
875
  gsq.forEach((sq) => {
@@ -912,44 +885,25 @@ function buildData(dataset, mainRect, dpr) {
912
885
  subRect.y += font.lineHeight + padding * 2;
913
886
  subRect.h -= font.lineHeight + padding * 2;
914
887
  }
915
- ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
888
+ ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
916
889
  });
917
890
  }
918
891
  return ret;
919
892
  }
920
893
 
921
- if (!tree.length && dataset.data.length) {
922
- tree = dataset.tree = dataset.data;
923
- }
924
-
925
894
  return glen
926
895
  ? recur(0, mainRect)
927
- : squarify(tree, mainRect, key, dpr);
928
- }
929
-
930
- function getMinMax(data, useTree) {
931
- const vMax = useTree ? 1 : maxValue(data);
932
- const vMin = useTree ? 0 : minValue(data, vMax);
933
- return {vMin, vMax};
934
- }
935
-
936
- function getArea({xScale, yScale}, data, rtl, useTree) {
937
- const {vMin, vMax} = getMinMax(data, useTree);
938
- const xMin = xScale.getPixelForValue(0);
939
- const xMax = xScale.getPixelForValue(1);
940
- const yMin = yScale.getPixelForValue(vMin);
941
- const yMax = yScale.getPixelForValue(vMax);
942
- return {x: xMin, y: yMax, w: xMax - xMin, h: yMin - yMax, rtl};
896
+ : squarify(tree, mainRect, key);
943
897
  }
944
898
 
945
899
  class TreemapController extends chart_js.DatasetController {
946
900
  constructor(chart, datasetIndex) {
947
901
  super(chart, datasetIndex);
948
902
 
949
- this._rect = undefined;
950
- this._key = undefined;
951
903
  this._groups = undefined;
952
- this._useTree = undefined;
904
+ this._key = undefined;
905
+ this._rect = undefined;
906
+ this._rectChanged = true;
953
907
  }
954
908
 
955
909
  initialize() {
@@ -957,86 +911,93 @@ class TreemapController extends chart_js.DatasetController {
957
911
  super.initialize();
958
912
  }
959
913
 
960
- /**
961
- * @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
962
- */
963
- updateRangeFromParsed(range, scale) {
964
- 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
965
926
  return;
966
927
  }
967
- range.updated = true;
968
- if (scale.axis === 'x') {
969
- range.min = 0;
970
- range.max = 1;
971
- 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();
972
943
  }
973
- const dataset = this.getDataset();
974
- const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
975
- range.min = vMin;
976
- range.max = vMax;
977
944
  }
978
945
 
979
946
  update(mode) {
980
- const meta = this.getMeta();
981
947
  const dataset = this.getDataset();
982
- const dpr = this.chart.currentDevicePixelRatio;
983
-
984
- if (!helpers.defined(this._useTree)) {
985
- this._useTree = !!dataset.tree;
986
- }
948
+ const {data} = this.getMeta();
987
949
  const groups = dataset.groups || (dataset.groups = []);
988
- const key = dataset.key || '';
989
- const rtl = !!dataset.rtl;
950
+ const key = dataset.key;
951
+ const tree = dataset.tree = dataset.tree || dataset.data || [];
990
952
 
991
- 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
+ }
992
957
 
993
- if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
994
- this._rect = mainRect;
958
+ if (this._rectChanged || this._key !== key || arrayNotEqual(this._groups, groups) || this._prevTree !== tree) {
995
959
  this._groups = groups.slice();
996
960
  this._key = key;
961
+ this._prevTree = tree;
962
+ this._rectChanged = false;
997
963
 
998
- dataset.data = buildData(dataset, mainRect, dpr);
964
+ dataset.data = buildData(tree, dataset, this._rect);
999
965
  // @ts-ignore using private stuff
1000
966
  this._dataCheck();
1001
967
  // @ts-ignore using private stuff
1002
968
  this._resyncElements();
1003
969
  }
1004
970
 
1005
- this.updateElements(meta.data, 0, meta.data.length, mode);
971
+ this.updateElements(data, 0, data.length, mode);
1006
972
  }
1007
973
 
1008
974
  updateElements(rects, start, count, mode) {
1009
- const me = this;
1010
975
  const reset = mode === 'reset';
1011
- const dataset = me.getDataset();
1012
- const firstOpts = me._rect.options = me.resolveDataElementOptions(start, mode);
1013
- const sharedOptions = me.getSharedOptions(firstOpts);
1014
- 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);
1015
981
 
1016
982
  for (let i = start; i < start + count; i++) {
1017
- const sq = dataset.data[i];
1018
- const options = sharedOptions || me.resolveDataElementOptions(i, mode);
1019
- const sp = options.spacing;
1020
- const sp2 = sp * 2;
1021
- const properties = {
1022
- x: sq.x + sp,
1023
- y: sq.y + sp,
1024
- width: reset ? 0 : sq.w - sp2,
1025
- height: reset ? 0 : sq.h - sp2,
1026
- hidden: sp2 > sq.w || sp2 > sq.h,
1027
- };
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
+ }
1028
989
 
1029
990
  if (includeOptions) {
1030
991
  properties.options = options;
1031
992
  }
1032
- me.updateElement(rects[i], i, properties, mode);
993
+ this.updateElement(rects[i], i, properties, mode);
1033
994
  }
1034
995
 
1035
- me.updateSharedOptions(sharedOptions, mode, firstOpts);
996
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
1036
997
  }
1037
998
 
1038
999
  draw() {
1039
- const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
1000
+ const {ctx, chartArea} = this.chart;
1040
1001
  const metadata = this.getMeta().data || [];
1041
1002
  const dataset = this.getDataset();
1042
1003
  const levels = (dataset.groups || []).length - 1;
@@ -1046,7 +1007,7 @@ class TreemapController extends chart_js.DatasetController {
1046
1007
  for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
1047
1008
  const rect = metadata[i];
1048
1009
  if (!rect.hidden) {
1049
- rect.draw(ctx, data[i], levels, dpr);
1010
+ rect.draw(ctx, data[i], levels);
1050
1011
  }
1051
1012
  }
1052
1013
  helpers.unclipArea(ctx);
@@ -1107,11 +1068,16 @@ TreemapController.overrides = {
1107
1068
  scales: {
1108
1069
  x: {
1109
1070
  type: 'linear',
1071
+ alignToPixels: true,
1072
+ bounds: 'data',
1110
1073
  display: false
1111
1074
  },
1112
1075
  y: {
1113
1076
  type: 'linear',
1114
- display: false
1077
+ alignToPixels: true,
1078
+ bounds: 'data',
1079
+ display: false,
1080
+ reverse: true
1115
1081
  }
1116
1082
  },
1117
1083
  };
@@ -1151,8 +1117,6 @@ exports.flatten = flatten;
1151
1117
  exports.getGroupKey = getGroupKey;
1152
1118
  exports.group = group;
1153
1119
  exports.index = index;
1154
- exports.maxValue = maxValue;
1155
- exports.minValue = minValue;
1156
1120
  exports.normalizeTreeToArray = normalizeTreeToArray;
1157
1121
  exports.requireVersion = requireVersion;
1158
1122
  exports.sort = sort;
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * chartjs-chart-treemap v2.1.1
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,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,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.1",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.1",
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",