chartjs-chart-sankey 0.9.1 → 0.10.0

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.
package/README.md CHANGED
@@ -94,6 +94,37 @@ const chart = new Chart(ctx, {
94
94
  });
95
95
  ```
96
96
 
97
+ ### Custom data structure
98
+
99
+ Custom data structure can be used by specifying the custom data keys in `options.parsing`.
100
+ For example:
101
+
102
+ ```js
103
+ const chart = new Chart(ctx, {
104
+ type: 'sankey',
105
+ data: {
106
+ datasets: [
107
+ {
108
+ data: [
109
+ {source: 'a', destination: 'b', value: 20},
110
+ {source: 'c', destination: 'd', value: 10},
111
+ {source: 'c', destination: 'e', value: 5},
112
+ ],
113
+ colorFrom: 'red',
114
+ colorTo: 'green'
115
+ }
116
+ ]
117
+ },
118
+ options: {
119
+ parsing: {
120
+ from: 'source',
121
+ to: 'destination',
122
+ flow: 'value'
123
+ }
124
+ }
125
+ });
126
+ ```
127
+
97
128
  ## Example
98
129
 
99
130
  ![Sankey Example Image](sankey.png)
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * chartjs-chart-sankey v0.9.1
2
+ * chartjs-chart-sankey v0.10.0
3
3
  * https://github.com/kurkle/chartjs-chart-sankey#readme
4
4
  * (c) 2022 Jukka Kurkela
5
5
  * Released under the MIT license
@@ -428,16 +428,13 @@ class SankeyController extends DatasetController {
428
428
  * @return {Array<SankeyParsedData>}
429
429
  */
430
430
  parseObjectData(meta, data, start, count) {
431
- // https://github.com/chartjs/Chart.js/pull/8379
432
- if (count === 0) {
433
- return [];
434
- }
435
- const me = this;
431
+ const {from: fromKey = 'from', to: toKey = 'to', flow: flowKey = 'flow'} = this.options.parsing;
432
+ const sankeyData = data.map(({[fromKey]: from, [toKey]: to, [flowKey]: flow}) => ({from, to, flow}));
436
433
  const {xScale, yScale} = meta;
437
434
  const parsed = []; /* Array<SankeyParsedData> */
438
- const nodes = me._nodes = buildNodesFromRawData(data);
435
+ const nodes = this._nodes = buildNodesFromRawData(sankeyData);
439
436
  /* getDataset() => SankeyControllerDatasetOptions */
440
- const {column, priority, size} = me.getDataset();
437
+ const {column, priority, size} = this.getDataset();
441
438
  if (priority) {
442
439
  for (const node of nodes.values()) {
443
440
  if (node.key in priority) {
@@ -454,13 +451,13 @@ class SankeyController extends DatasetController {
454
451
  }
455
452
  }
456
453
 
457
- const {maxX, maxY} = layout(nodes, data, !!priority, validateSizeValue(size));
454
+ const {maxX, maxY} = layout(nodes, sankeyData, !!priority, validateSizeValue(size));
458
455
 
459
- me._maxX = maxX;
460
- me._maxY = maxY;
456
+ this._maxX = maxX;
457
+ this._maxY = maxY;
461
458
 
462
- for (let i = 0, ilen = data.length; i < ilen; ++i) {
463
- const dataPoint = data[i];
459
+ for (let i = 0, ilen = sankeyData.length; i < ilen; ++i) {
460
+ const dataPoint = sankeyData[i];
464
461
  const from = nodes.get(dataPoint.from);
465
462
  const to = nodes.get(dataPoint.to);
466
463
  const fromY = from.y + getAddY(from.to, dataPoint.to, i);
@@ -481,18 +478,16 @@ class SankeyController extends DatasetController {
481
478
  }
482
479
 
483
480
  getMinMax(scale) {
484
- const me = this;
485
481
  return {
486
482
  min: 0,
487
- max: scale === this._cachedMeta.xScale ? this._maxX : me._maxY
483
+ max: scale === this._cachedMeta.xScale ? this._maxX : this._maxY
488
484
  };
489
485
  }
490
486
 
491
487
  update(mode) {
492
- const me = this;
493
- const meta = me._cachedMeta;
488
+ const {data} = this._cachedMeta;
494
489
 
495
- me.updateElements(meta.data, 0, meta.data.length, mode);
490
+ this.updateElements(data, 0, data.length, mode);
496
491
  }
497
492
 
498
493
  /**
@@ -502,20 +497,19 @@ class SankeyController extends DatasetController {
502
497
  * @param {"resize" | "reset" | "none" | "hide" | "show" | "normal" | "active"} mode
503
498
  */
504
499
  updateElements(elems, start, count, mode) {
505
- const me = this;
506
- const {xScale, yScale} = me._cachedMeta;
507
- const firstOpts = me.resolveDataElementOptions(start, mode);
508
- const sharedOptions = me.getSharedOptions(mode, elems[start], firstOpts);
509
- const dataset = me.getDataset();
500
+ const {xScale, yScale} = this._cachedMeta;
501
+ const firstOpts = this.resolveDataElementOptions(start, mode);
502
+ const sharedOptions = this.getSharedOptions(mode, elems[start], firstOpts);
503
+ const dataset = this.getDataset();
510
504
  const borderWidth = valueOrDefault(dataset.borderWidth, 1) / 2 + 0.5;
511
505
  const nodeWidth = valueOrDefault(dataset.nodeWidth, 10);
512
506
 
513
507
  for (let i = start; i < start + count; i++) {
514
508
  /* getParsed(idx: number) => SankeyParsedData */
515
- const parsed = me.getParsed(i);
509
+ const parsed = this.getParsed(i);
516
510
  const custom = parsed._custom;
517
511
  const y = yScale.getPixelForValue(parsed.y);
518
- me.updateElement(
512
+ this.updateElement(
519
513
  elems[i],
520
514
  i,
521
515
  {
@@ -527,27 +521,26 @@ class SankeyController extends DatasetController {
527
521
  to: custom.to,
528
522
  progress: mode === 'reset' ? 0 : 1,
529
523
  height: Math.abs(yScale.getPixelForValue(parsed.y + custom.height) - y),
530
- options: me.resolveDataElementOptions(i, mode)
524
+ options: this.resolveDataElementOptions(i, mode)
531
525
  },
532
526
  mode);
533
527
  }
534
528
 
535
- me.updateSharedOptions(sharedOptions, mode);
529
+ this.updateSharedOptions(sharedOptions, mode);
536
530
  }
537
531
 
538
532
  _drawLabels() {
539
- const me = this;
540
- const ctx = me._ctx;
541
- const nodes = me._nodes || new Map();
542
- const dataset = me.getDataset(); /* SankeyControllerDatasetOptions */
533
+ const ctx = this._ctx;
534
+ const nodes = this._nodes || new Map();
535
+ const dataset = this.getDataset(); /* SankeyControllerDatasetOptions */
543
536
  const size = validateSizeValue(dataset.size);
544
537
  const borderWidth = valueOrDefault(dataset.borderWidth, 1);
545
538
  const nodeWidth = valueOrDefault(dataset.nodeWidth, 10);
546
539
  const labels = dataset.labels;
547
- const {xScale, yScale} = me._cachedMeta;
540
+ const {xScale, yScale} = this._cachedMeta;
548
541
 
549
542
  ctx.save();
550
- const chartArea = me.chart.chartArea;
543
+ const chartArea = this.chart.chartArea;
551
544
  for (const node of nodes.values()) {
552
545
  const x = xScale.getPixelForValue(node.x);
553
546
  const y = yScale.getPixelForValue(node.y);
@@ -579,13 +572,12 @@ class SankeyController extends DatasetController {
579
572
  * @private
580
573
  */
581
574
  _drawLabel(label, y, height, ctx, textX) {
582
- const me = this;
583
- const font = toFont(me.options.font, me.chart.options.font);
575
+ const font = toFont(this.options.font, this.chart.options.font);
584
576
  const lines = isNullOrUndef(label) ? [] : toTextLines(label);
585
577
  const linesLength = lines.length;
586
578
  const middle = y + height / 2;
587
579
  const textHeight = font.lineHeight;
588
- const padding = valueOrDefault(me.options.padding, textHeight / 2);
580
+ const padding = valueOrDefault(this.options.padding, textHeight / 2);
589
581
 
590
582
  ctx.font = font.string;
591
583
 
@@ -600,12 +592,11 @@ class SankeyController extends DatasetController {
600
592
  }
601
593
 
602
594
  _drawNodes() {
603
- const me = this;
604
- const ctx = me._ctx;
605
- const nodes = me._nodes || new Map();
606
- const dataset = me.getDataset(); /* SankeyControllerDatasetOptions */
595
+ const ctx = this._ctx;
596
+ const nodes = this._nodes || new Map();
597
+ const dataset = this.getDataset(); /* SankeyControllerDatasetOptions */
607
598
  const size = validateSizeValue(dataset.size);
608
- const {xScale, yScale} = me._cachedMeta;
599
+ const {xScale, yScale} = this._cachedMeta;
609
600
  const borderWidth = valueOrDefault(dataset.borderWidth, 1);
610
601
  const nodeWidth = valueOrDefault(dataset.nodeWidth, 10);
611
602
 
@@ -632,9 +623,8 @@ class SankeyController extends DatasetController {
632
623
  * That's where the drawing process happens
633
624
  */
634
625
  draw() {
635
- const me = this;
636
- const ctx = me._ctx;
637
- const data = me.getMeta().data || []; /* Array<Flow> */
626
+ const ctx = this._ctx;
627
+ const data = this.getMeta().data || []; /* Array<Flow> */
638
628
 
639
629
  for (let i = 0, ilen = data.length; i < ilen; ++i) {
640
630
  const flow = data[i]; /* Flow at index i */
@@ -643,7 +633,7 @@ class SankeyController extends DatasetController {
643
633
  }
644
634
 
645
635
  /* draw SankeyNodes on the canvas */
646
- me._drawNodes();
636
+ this._drawNodes();
647
637
 
648
638
  /* draw Flow elements on the canvas */
649
639
  for (let i = 0, ilen = data.length; i < ilen; ++i) {
@@ -651,7 +641,7 @@ class SankeyController extends DatasetController {
651
641
  }
652
642
 
653
643
  /* draw labels (for SankeyNodes) on the canvas */
654
- me._drawLabels();
644
+ this._drawLabels();
655
645
  }
656
646
  }
657
647
 
@@ -702,7 +692,6 @@ SankeyController.overrides = {
702
692
  intersect: true
703
693
  },
704
694
  datasets: {
705
- color: () => '#efefef',
706
695
  clip: false,
707
696
  parsing: true
708
697
  },
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * chartjs-chart-sankey v0.9.1
2
+ * chartjs-chart-sankey v0.10.0
3
3
  * https://github.com/kurkle/chartjs-chart-sankey#readme
4
4
  * (c) 2022 Jukka Kurkela
5
5
  * Released under the MIT license
@@ -431,16 +431,13 @@ class SankeyController extends chart_js.DatasetController {
431
431
  * @return {Array<SankeyParsedData>}
432
432
  */
433
433
  parseObjectData(meta, data, start, count) {
434
- // https://github.com/chartjs/Chart.js/pull/8379
435
- if (count === 0) {
436
- return [];
437
- }
438
- const me = this;
434
+ const {from: fromKey = 'from', to: toKey = 'to', flow: flowKey = 'flow'} = this.options.parsing;
435
+ const sankeyData = data.map(({[fromKey]: from, [toKey]: to, [flowKey]: flow}) => ({from, to, flow}));
439
436
  const {xScale, yScale} = meta;
440
437
  const parsed = []; /* Array<SankeyParsedData> */
441
- const nodes = me._nodes = buildNodesFromRawData(data);
438
+ const nodes = this._nodes = buildNodesFromRawData(sankeyData);
442
439
  /* getDataset() => SankeyControllerDatasetOptions */
443
- const {column, priority, size} = me.getDataset();
440
+ const {column, priority, size} = this.getDataset();
444
441
  if (priority) {
445
442
  for (const node of nodes.values()) {
446
443
  if (node.key in priority) {
@@ -457,13 +454,13 @@ class SankeyController extends chart_js.DatasetController {
457
454
  }
458
455
  }
459
456
 
460
- const {maxX, maxY} = layout(nodes, data, !!priority, validateSizeValue(size));
457
+ const {maxX, maxY} = layout(nodes, sankeyData, !!priority, validateSizeValue(size));
461
458
 
462
- me._maxX = maxX;
463
- me._maxY = maxY;
459
+ this._maxX = maxX;
460
+ this._maxY = maxY;
464
461
 
465
- for (let i = 0, ilen = data.length; i < ilen; ++i) {
466
- const dataPoint = data[i];
462
+ for (let i = 0, ilen = sankeyData.length; i < ilen; ++i) {
463
+ const dataPoint = sankeyData[i];
467
464
  const from = nodes.get(dataPoint.from);
468
465
  const to = nodes.get(dataPoint.to);
469
466
  const fromY = from.y + getAddY(from.to, dataPoint.to, i);
@@ -484,18 +481,16 @@ class SankeyController extends chart_js.DatasetController {
484
481
  }
485
482
 
486
483
  getMinMax(scale) {
487
- const me = this;
488
484
  return {
489
485
  min: 0,
490
- max: scale === this._cachedMeta.xScale ? this._maxX : me._maxY
486
+ max: scale === this._cachedMeta.xScale ? this._maxX : this._maxY
491
487
  };
492
488
  }
493
489
 
494
490
  update(mode) {
495
- const me = this;
496
- const meta = me._cachedMeta;
491
+ const {data} = this._cachedMeta;
497
492
 
498
- me.updateElements(meta.data, 0, meta.data.length, mode);
493
+ this.updateElements(data, 0, data.length, mode);
499
494
  }
500
495
 
501
496
  /**
@@ -505,20 +500,19 @@ class SankeyController extends chart_js.DatasetController {
505
500
  * @param {"resize" | "reset" | "none" | "hide" | "show" | "normal" | "active"} mode
506
501
  */
507
502
  updateElements(elems, start, count, mode) {
508
- const me = this;
509
- const {xScale, yScale} = me._cachedMeta;
510
- const firstOpts = me.resolveDataElementOptions(start, mode);
511
- const sharedOptions = me.getSharedOptions(mode, elems[start], firstOpts);
512
- const dataset = me.getDataset();
503
+ const {xScale, yScale} = this._cachedMeta;
504
+ const firstOpts = this.resolveDataElementOptions(start, mode);
505
+ const sharedOptions = this.getSharedOptions(mode, elems[start], firstOpts);
506
+ const dataset = this.getDataset();
513
507
  const borderWidth = helpers.valueOrDefault(dataset.borderWidth, 1) / 2 + 0.5;
514
508
  const nodeWidth = helpers.valueOrDefault(dataset.nodeWidth, 10);
515
509
 
516
510
  for (let i = start; i < start + count; i++) {
517
511
  /* getParsed(idx: number) => SankeyParsedData */
518
- const parsed = me.getParsed(i);
512
+ const parsed = this.getParsed(i);
519
513
  const custom = parsed._custom;
520
514
  const y = yScale.getPixelForValue(parsed.y);
521
- me.updateElement(
515
+ this.updateElement(
522
516
  elems[i],
523
517
  i,
524
518
  {
@@ -530,27 +524,26 @@ class SankeyController extends chart_js.DatasetController {
530
524
  to: custom.to,
531
525
  progress: mode === 'reset' ? 0 : 1,
532
526
  height: Math.abs(yScale.getPixelForValue(parsed.y + custom.height) - y),
533
- options: me.resolveDataElementOptions(i, mode)
527
+ options: this.resolveDataElementOptions(i, mode)
534
528
  },
535
529
  mode);
536
530
  }
537
531
 
538
- me.updateSharedOptions(sharedOptions, mode);
532
+ this.updateSharedOptions(sharedOptions, mode);
539
533
  }
540
534
 
541
535
  _drawLabels() {
542
- const me = this;
543
- const ctx = me._ctx;
544
- const nodes = me._nodes || new Map();
545
- const dataset = me.getDataset(); /* SankeyControllerDatasetOptions */
536
+ const ctx = this._ctx;
537
+ const nodes = this._nodes || new Map();
538
+ const dataset = this.getDataset(); /* SankeyControllerDatasetOptions */
546
539
  const size = validateSizeValue(dataset.size);
547
540
  const borderWidth = helpers.valueOrDefault(dataset.borderWidth, 1);
548
541
  const nodeWidth = helpers.valueOrDefault(dataset.nodeWidth, 10);
549
542
  const labels = dataset.labels;
550
- const {xScale, yScale} = me._cachedMeta;
543
+ const {xScale, yScale} = this._cachedMeta;
551
544
 
552
545
  ctx.save();
553
- const chartArea = me.chart.chartArea;
546
+ const chartArea = this.chart.chartArea;
554
547
  for (const node of nodes.values()) {
555
548
  const x = xScale.getPixelForValue(node.x);
556
549
  const y = yScale.getPixelForValue(node.y);
@@ -582,13 +575,12 @@ class SankeyController extends chart_js.DatasetController {
582
575
  * @private
583
576
  */
584
577
  _drawLabel(label, y, height, ctx, textX) {
585
- const me = this;
586
- const font = helpers.toFont(me.options.font, me.chart.options.font);
578
+ const font = helpers.toFont(this.options.font, this.chart.options.font);
587
579
  const lines = helpers.isNullOrUndef(label) ? [] : toTextLines(label);
588
580
  const linesLength = lines.length;
589
581
  const middle = y + height / 2;
590
582
  const textHeight = font.lineHeight;
591
- const padding = helpers.valueOrDefault(me.options.padding, textHeight / 2);
583
+ const padding = helpers.valueOrDefault(this.options.padding, textHeight / 2);
592
584
 
593
585
  ctx.font = font.string;
594
586
 
@@ -603,12 +595,11 @@ class SankeyController extends chart_js.DatasetController {
603
595
  }
604
596
 
605
597
  _drawNodes() {
606
- const me = this;
607
- const ctx = me._ctx;
608
- const nodes = me._nodes || new Map();
609
- const dataset = me.getDataset(); /* SankeyControllerDatasetOptions */
598
+ const ctx = this._ctx;
599
+ const nodes = this._nodes || new Map();
600
+ const dataset = this.getDataset(); /* SankeyControllerDatasetOptions */
610
601
  const size = validateSizeValue(dataset.size);
611
- const {xScale, yScale} = me._cachedMeta;
602
+ const {xScale, yScale} = this._cachedMeta;
612
603
  const borderWidth = helpers.valueOrDefault(dataset.borderWidth, 1);
613
604
  const nodeWidth = helpers.valueOrDefault(dataset.nodeWidth, 10);
614
605
 
@@ -635,9 +626,8 @@ class SankeyController extends chart_js.DatasetController {
635
626
  * That's where the drawing process happens
636
627
  */
637
628
  draw() {
638
- const me = this;
639
- const ctx = me._ctx;
640
- const data = me.getMeta().data || []; /* Array<Flow> */
629
+ const ctx = this._ctx;
630
+ const data = this.getMeta().data || []; /* Array<Flow> */
641
631
 
642
632
  for (let i = 0, ilen = data.length; i < ilen; ++i) {
643
633
  const flow = data[i]; /* Flow at index i */
@@ -646,7 +636,7 @@ class SankeyController extends chart_js.DatasetController {
646
636
  }
647
637
 
648
638
  /* draw SankeyNodes on the canvas */
649
- me._drawNodes();
639
+ this._drawNodes();
650
640
 
651
641
  /* draw Flow elements on the canvas */
652
642
  for (let i = 0, ilen = data.length; i < ilen; ++i) {
@@ -654,7 +644,7 @@ class SankeyController extends chart_js.DatasetController {
654
644
  }
655
645
 
656
646
  /* draw labels (for SankeyNodes) on the canvas */
657
- me._drawLabels();
647
+ this._drawLabels();
658
648
  }
659
649
  }
660
650
 
@@ -705,7 +695,6 @@ SankeyController.overrides = {
705
695
  intersect: true
706
696
  },
707
697
  datasets: {
708
- color: () => '#efefef',
709
698
  clip: false,
710
699
  parsing: true
711
700
  },
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * chartjs-chart-sankey v0.9.1
2
+ * chartjs-chart-sankey v0.10.0
3
3
  * https://github.com/kurkle/chartjs-chart-sankey#readme
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(require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Chart,t.Chart.helpers)}(this,(function(t,e){"use strict";function o(t){return t&&-1!==["min","max"].indexOf(t)?t:"max"}const r=t=>void 0!==t;function n(t,e){const o=t.filter((t=>!e.has(t)));return o.length?o:t.slice(0,1)}const a=(t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y;let i=-1;function s(t,e,o=function(){return i=i<100?i+1:0,i}()){let r=0;for(const n of t)n.node._visited!==o&&(n.node._visited=o,r+=n.node[e].length+s(n.node[e],e,o));return r}const l=t=>(e,o)=>s(e.node[t],t)-s(o.node[t],t)||e.node[t].length-o.node[t].length;function c(t,e){t.from.sort(l("from"));for(const o of t.from){const t=o.node;r(t.y)||(t.y=e,c(t,e)),e=Math.max(t.y+t.out,e)}return e}function f(t,e){t.to.sort(l("to"));for(const o of t.to){const t=o.node;r(t.y)||(t.y=e,f(t,e)),e=Math.max(t.y+t.in,e)}return e}function h(t,e){return r(t.y)?t.y:(t.y=e,e)}function d(t,e){t.sort(((t,e)=>Math.max(e.in,e.out)-Math.max(t.in,t.out)));const o=t[0];o.y=0;const n=c(o,0),a=f(o,0),i=function(t,e){const o=t.filter((t=>0===t.x)),n=t.filter((t=>t.x===e)),a=o.filter((t=>!r(t.y))),i=n.filter((t=>!r(t.y))),s=t.filter((t=>t.x>0&&t.x<e&&!r(t.y)));let l=o.reduce(((t,e)=>Math.max(t,e.y+e.out||0)),0),d=n.reduce(((t,e)=>Math.max(t,e.y+e.in||0)),0),u=0;return l>=d?(a.forEach((t=>{l=h(t,l),l=Math.max(l+t.out,f(t,l))})),i.forEach((t=>{d=h(t,d),d=Math.max(d+t.in,f(t,d))}))):(i.forEach((t=>{d=h(t,d),d=Math.max(d+t.in,f(t,d))})),a.forEach((t=>{l=h(t,l),l=Math.max(l+t.out,f(t,l))}))),s.forEach((e=>{let o=t.filter((t=>t.x===e.x&&r(t.y))).reduce(((t,e)=>Math.max(t,e.y+Math.max(e.in,e.out))),0);o=h(e,o),o=Math.max(o+e.in,c(e,o)),o=Math.max(o+e.out,f(e,o)),u=Math.max(u,o)})),Math.max(l,d,u)}(t,e);return Math.max(n,a,i)}function u(t,e,o,i){const s=[...t.values()],l=function(t,e){const o=new Set(e.map((t=>t.to))),a=new Set(e.map((t=>t.from))),i=new Set([...t.keys()]);let s=0;for(;i.size;){const a=n([...i],o);for(const e of a){const o=t.get(e);r(o.x)||(o.x=s),i.delete(e)}i.size&&(o.clear(),e.filter((t=>i.has(t.from))).forEach((t=>o.add(t.to))),s++)}return[...t.keys()].filter((t=>!a.has(t))).forEach((e=>{const o=t.get(e);o.column||(o.x=s)})),s}(t,e),c=o?function(t,e){let o=0,r=0;for(let n=0;n<=e;n++){let e=r;const a=t.filter((t=>t.x===n)).sort(((t,e)=>t.priority-e.priority));r=a[0].to.filter((t=>t.node.x>n+1)).reduce(((t,e)=>t+e.flow),0)||0;for(const t of a)t.y=e,e+=Math.max(t.out,t.in);o=Math.max(e,o)}return o}(s,l):d(s,l),f=function(t,e){let o=1,r=0,n=0,i=0;const s=[];t.sort(a);for(const a of t){if(a.y){if(0===a.x)s.push(a.y);else{for(r!==a.x&&(r=a.x,n=0),o=n+1;o<s.length&&!(s[o]>a.y);o++);n=o}a.y+=o*e,o++}i=Math.max(i,a.y+Math.max(a.in,a.out))}return i}(s,.03*c);return function(t,e){t.forEach((t=>{const o=Math[e](t.in||t.out,t.out||t.in),r=o<t.in,n=o<t.out;let a=0,i=t.from.length;t.from.sort(((t,e)=>t.node.y+t.node.out/2-(e.node.y+e.node.out/2))).forEach(((t,e)=>{r?t.addY=e*(o-t.flow)/(i-1):(t.addY=a,a+=t.flow)})),a=0,i=t.to.length,t.to.sort(((t,e)=>t.node.y+t.node.in/2-(e.node.y+e.node.in/2))).forEach(((t,e)=>{n?t.addY=e*(o-t.flow)/(i-1):(t.addY=a,a+=t.flow)}))}))}(s,i),{maxX:l,maxY:f}}function x(t,e,o){for(const r of t)if(r.key===e&&r.index===o)return r.addY;return 0}class y extends t.DatasetController{parseObjectData(t,e,r,n){if(0===n)return[];const a=this,{xScale:i,yScale:s}=t,l=[],c=a._nodes=function(t){const e=new Map;for(let o=0;o<t.length;o++){const{from:r,to:n,flow:a}=t[o];if(e.has(r)){const t=e.get(r);t.out+=a,t.to.push({key:n,flow:a,index:o})}else e.set(r,{key:r,in:0,out:a,from:[],to:[{key:n,flow:a,index:o}]});if(e.has(n)){const t=e.get(n);t.in+=a,t.from.push({key:r,flow:a,index:o})}else e.set(n,{key:n,in:a,out:0,from:[{key:r,flow:a,index:o}],to:[]})}const o=(t,e)=>e.flow-t.flow;return[...e.values()].forEach((t=>{t.from=t.from.sort(o),t.from.forEach((t=>{t.node=e.get(t.key)})),t.to=t.to.sort(o),t.to.forEach((t=>{t.node=e.get(t.key)}))})),e}(e),{column:f,priority:h,size:d}=a.getDataset();if(h)for(const t of c.values())t.key in h&&(t.priority=h[t.key]);if(f)for(const t of c.values())t.key in f&&(t.column=!0,t.x=f[t.key]);const{maxX:y,maxY:p}=u(c,e,!!h,o(d));a._maxX=y,a._maxY=p;for(let t=0,o=e.length;t<o;++t){const o=e[t],r=c.get(o.from),n=c.get(o.to),a=r.y+x(r.to,o.to,t),f=n.y+x(n.from,o.from,t);l.push({x:i.parse(r.x,t),y:s.parse(a,t),_custom:{from:r,to:n,x:i.parse(n.x,t),y:s.parse(f,t),height:s.parse(o.flow,t)}})}return l.slice(r,r+n)}getMinMax(t){return{min:0,max:t===this._cachedMeta.xScale?this._maxX:this._maxY}}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,o,r,n){const a=this,{xScale:i,yScale:s}=a._cachedMeta,l=a.resolveDataElementOptions(o,n),c=a.getSharedOptions(n,t[o],l),f=a.getDataset(),h=e.valueOrDefault(f.borderWidth,1)/2+.5,d=e.valueOrDefault(f.nodeWidth,10);for(let e=o;e<o+r;e++){const o=a.getParsed(e),r=o._custom,l=s.getPixelForValue(o.y);a.updateElement(t[e],e,{x:i.getPixelForValue(o.x)+d+h,y:l,x2:i.getPixelForValue(r.x)-h,y2:s.getPixelForValue(r.y),from:r.from,to:r.to,progress:"reset"===n?0:1,height:Math.abs(s.getPixelForValue(o.y+r.height)-l),options:a.resolveDataElementOptions(e,n)},n)}a.updateSharedOptions(c,n)}_drawLabels(){const t=this,r=t._ctx,n=t._nodes||new Map,a=t.getDataset(),i=o(a.size),s=e.valueOrDefault(a.borderWidth,1),l=e.valueOrDefault(a.nodeWidth,10),c=a.labels,{xScale:f,yScale:h}=t._cachedMeta;r.save();const d=t.chart.chartArea;for(const t of n.values()){const e=f.getPixelForValue(t.x),o=h.getPixelForValue(t.y),n=Math[i](t.in||t.out,t.out||t.in),u=Math.abs(h.getPixelForValue(t.y+n)-o),x=c&&c[t.key]||t.key;let y=e;r.fillStyle=a.color||"black",r.textBaseline="middle",e<d.width/2?(r.textAlign="left",y+=l+s+4):(r.textAlign="right",y-=s+4),this._drawLabel(x,o,u,r,y)}r.restore()}_drawLabel(t,o,r,n,a){const i=this,s=e.toFont(i.options.font,i.chart.options.font),l=e.isNullOrUndef(t)?[]:function(t){const o=[],r=e.isArray(t)?t:e.isNullOrUndef(t)?[]:[t];for(;r.length;){const t=r.pop();"string"==typeof t?o.unshift.apply(o,t.split("\n")):Array.isArray(t)?r.push.apply(r,t):e.isNullOrUndef(r)||o.unshift(""+t)}return o}(t),c=l.length,f=o+r/2,h=s.lineHeight,d=e.valueOrDefault(i.options.padding,h/2);if(n.font=s.string,c>1){const t=f-h*c/2+d;for(let e=0;e<c;e++)n.fillText(l[e],a,t+e*h)}else n.fillText(t,a,f)}_drawNodes(){const t=this,r=t._ctx,n=t._nodes||new Map,a=t.getDataset(),i=o(a.size),{xScale:s,yScale:l}=t._cachedMeta,c=e.valueOrDefault(a.borderWidth,1),f=e.valueOrDefault(a.nodeWidth,10);r.save(),r.strokeStyle=a.borderColor||"black",r.lineWidth=c;for(const t of n.values()){r.fillStyle=t.color;const e=s.getPixelForValue(t.x),o=l.getPixelForValue(t.y),n=Math[i](t.in||t.out,t.out||t.in),a=Math.abs(l.getPixelForValue(t.y+n)-o);c&&r.strokeRect(e,o,f,a),r.fillRect(e,o,f,a)}r.restore()}draw(){const t=this,e=t._ctx,o=t.getMeta().data||[];for(let t=0,e=o.length;t<e;++t){const e=o[t];e.from.color=e.options.colorFrom,e.to.color=e.options.colorTo}t._drawNodes();for(let t=0,r=o.length;t<r;++t)o[t].draw(e);t._drawLabels()}}y.id="sankey",y.defaults={dataElementType:"flow",animations:{numbers:{type:"number",properties:["x","y","x2","y2","height"]},progress:{easing:"linear",duration:t=>"data"===t.type?200*(t.parsed._custom.x-t.parsed.x):void 0,delay:t=>"data"===t.type?500*t.parsed.x+20*t.dataIndex:void 0},colors:{type:"color",properties:["colorFrom","colorTo"]}},transitions:{hide:{animations:{colors:{type:"color",properties:["colorFrom","colorTo"],to:"transparent"}}},show:{animations:{colors:{type:"color",properties:["colorFrom","colorTo"],from:"transparent"}}}}},y.overrides={interaction:{mode:"nearest",intersect:!0},datasets:{color:()=>"#efefef",clip:!1,parsing:!0},plugins:{tooltip:{callbacks:{title:()=>"",label(t){const e=t.dataset.data[t.dataIndex];return e.from+" -> "+e.to+": "+e.flow}}},legend:{display:!1}},scales:{x:{type:"linear",bounds:"data",display:!1,min:0,offset:!1},y:{type:"linear",bounds:"data",display:!1,min:0,reverse:!0,offset:!1}},layout:{padding:{top:3,left:3,right:13,bottom:3}}};const p=(t,e,o,r)=>t<o?{cp1:{x:t+(o-t)/3*2,y:e},cp2:{x:t+(o-t)/3,y:r}}:{cp1:{x:t-(t-o)/3,y:0},cp2:{x:o+(t-o)/3,y:0}},g=(t,e,o)=>({x:t.x+o*(e.x-t.x),y:t.y+o*(e.y-t.y)});class m extends t.Element{constructor(t){super(),this.options=void 0,this.x=void 0,this.y=void 0,this.x2=void 0,this.y2=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t){const{x:o,x2:r,y:n,y2:a,height:i,progress:s}=this,{cp1:l,cp2:c}=p(o,n,r,a);0!==s&&(t.save(),s<1&&(t.beginPath(),t.rect(o,Math.min(n,a),(r-o)*s+1,Math.abs(a-n)+i+1),t.clip()),function(t,{x:o,x2:r,options:n}){let a;"from"===n.colorMode?a=e.color(n.colorFrom).alpha(.5).rgbString():"to"===n.colorMode?a=e.color(n.colorTo).alpha(.5).rgbString():(a=t.createLinearGradient(o,0,r,0),a.addColorStop(0,e.color(n.colorFrom).alpha(.5).rgbString()),a.addColorStop(1,e.color(n.colorTo).alpha(.5).rgbString())),t.fillStyle=a,t.strokeStyle=a,t.lineWidth=.5}(t,this),t.beginPath(),t.moveTo(o,n),t.bezierCurveTo(l.x,l.y,c.x,c.y,r,a),t.lineTo(r,a+i),t.bezierCurveTo(c.x,c.y+i,l.x,l.y+i,o,n+i),t.lineTo(o,n),t.stroke(),t.closePath(),t.fill(),t.restore())}inRange(t,e,o){const{x:r,y:n,x2:a,y2:i,height:s}=this.getProps(["x","y","x2","y2","height"],o);if(t<r||t>a)return!1;const{cp1:l,cp2:c}=p(r,n,a,i),f=(t-r)/(a-r),h={x:a,y:i},d=g({x:r,y:n},l,f),u=g(l,c,f),x=g(c,h,f),y=g(d,u,f),m=g(u,x,f),M=g(y,m,f).y;return e>=M&&e<=M+s}inXRange(t,e){const{x:o,x2:r}=this.getProps(["x","x2"],e);return t>=o&&t<=r}inYRange(t,e){const{y:o,y2:r,height:n}=this.getProps(["y","y2","height"],e),a=Math.min(o,r),i=Math.max(o,r)+n;return t>=a&&t<=i}getCenterPoint(t){const{x:e,y:o,x2:r,y2:n,height:a}=this.getProps(["x","y","x2","y2","height"],t);return{x:(e+r)/2,y:(o+n+a)/2}}tooltipPosition(t){return this.getCenterPoint(t)}getRange(t){return"x"===t?this.width/2:this.height/2}}m.id="flow",m.defaults={colorFrom:"red",colorTo:"green",colorMode:"gradient"},t.Chart.register(y,m)}));
7
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Chart,t.Chart.helpers)}(this,(function(t,e){"use strict";function o(t){return t&&-1!==["min","max"].indexOf(t)?t:"max"}const r=t=>void 0!==t;function n(t,e){const o=t.filter((t=>!e.has(t)));return o.length?o:t.slice(0,1)}const a=(t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y;let i=-1;function s(t,e,o=function(){return i=i<100?i+1:0,i}()){let r=0;for(const n of t)n.node._visited!==o&&(n.node._visited=o,r+=n.node[e].length+s(n.node[e],e,o));return r}const l=t=>(e,o)=>s(e.node[t],t)-s(o.node[t],t)||e.node[t].length-o.node[t].length;function c(t,e){t.from.sort(l("from"));for(const o of t.from){const t=o.node;r(t.y)||(t.y=e,c(t,e)),e=Math.max(t.y+t.out,e)}return e}function h(t,e){t.to.sort(l("to"));for(const o of t.to){const t=o.node;r(t.y)||(t.y=e,h(t,e)),e=Math.max(t.y+t.in,e)}return e}function f(t,e){return r(t.y)?t.y:(t.y=e,e)}function d(t,e){t.sort(((t,e)=>Math.max(e.in,e.out)-Math.max(t.in,t.out)));const o=t[0];o.y=0;const n=c(o,0),a=h(o,0),i=function(t,e){const o=t.filter((t=>0===t.x)),n=t.filter((t=>t.x===e)),a=o.filter((t=>!r(t.y))),i=n.filter((t=>!r(t.y))),s=t.filter((t=>t.x>0&&t.x<e&&!r(t.y)));let l=o.reduce(((t,e)=>Math.max(t,e.y+e.out||0)),0),d=n.reduce(((t,e)=>Math.max(t,e.y+e.in||0)),0),u=0;return l>=d?(a.forEach((t=>{l=f(t,l),l=Math.max(l+t.out,h(t,l))})),i.forEach((t=>{d=f(t,d),d=Math.max(d+t.in,h(t,d))}))):(i.forEach((t=>{d=f(t,d),d=Math.max(d+t.in,h(t,d))})),a.forEach((t=>{l=f(t,l),l=Math.max(l+t.out,h(t,l))}))),s.forEach((e=>{let o=t.filter((t=>t.x===e.x&&r(t.y))).reduce(((t,e)=>Math.max(t,e.y+Math.max(e.in,e.out))),0);o=f(e,o),o=Math.max(o+e.in,c(e,o)),o=Math.max(o+e.out,h(e,o)),u=Math.max(u,o)})),Math.max(l,d,u)}(t,e);return Math.max(n,a,i)}function u(t,e,o,i){const s=[...t.values()],l=function(t,e){const o=new Set(e.map((t=>t.to))),a=new Set(e.map((t=>t.from))),i=new Set([...t.keys()]);let s=0;for(;i.size;){const a=n([...i],o);for(const e of a){const o=t.get(e);r(o.x)||(o.x=s),i.delete(e)}i.size&&(o.clear(),e.filter((t=>i.has(t.from))).forEach((t=>o.add(t.to))),s++)}return[...t.keys()].filter((t=>!a.has(t))).forEach((e=>{const o=t.get(e);o.column||(o.x=s)})),s}(t,e),c=o?function(t,e){let o=0,r=0;for(let n=0;n<=e;n++){let e=r;const a=t.filter((t=>t.x===n)).sort(((t,e)=>t.priority-e.priority));r=a[0].to.filter((t=>t.node.x>n+1)).reduce(((t,e)=>t+e.flow),0)||0;for(const t of a)t.y=e,e+=Math.max(t.out,t.in);o=Math.max(e,o)}return o}(s,l):d(s,l),h=function(t,e){let o=1,r=0,n=0,i=0;const s=[];t.sort(a);for(const a of t){if(a.y){if(0===a.x)s.push(a.y);else{for(r!==a.x&&(r=a.x,n=0),o=n+1;o<s.length&&!(s[o]>a.y);o++);n=o}a.y+=o*e,o++}i=Math.max(i,a.y+Math.max(a.in,a.out))}return i}(s,.03*c);return function(t,e){t.forEach((t=>{const o=Math[e](t.in||t.out,t.out||t.in),r=o<t.in,n=o<t.out;let a=0,i=t.from.length;t.from.sort(((t,e)=>t.node.y+t.node.out/2-(e.node.y+e.node.out/2))).forEach(((t,e)=>{r?t.addY=e*(o-t.flow)/(i-1):(t.addY=a,a+=t.flow)})),a=0,i=t.to.length,t.to.sort(((t,e)=>t.node.y+t.node.in/2-(e.node.y+e.node.in/2))).forEach(((t,e)=>{n?t.addY=e*(o-t.flow)/(i-1):(t.addY=a,a+=t.flow)}))}))}(s,i),{maxX:l,maxY:h}}function x(t,e,o){for(const r of t)if(r.key===e&&r.index===o)return r.addY;return 0}class y extends t.DatasetController{parseObjectData(t,e,r,n){const{from:a="from",to:i="to",flow:s="flow"}=this.options.parsing,l=e.map((({[a]:t,[i]:e,[s]:o})=>({from:t,to:e,flow:o}))),{xScale:c,yScale:h}=t,f=[],d=this._nodes=function(t){const e=new Map;for(let o=0;o<t.length;o++){const{from:r,to:n,flow:a}=t[o];if(e.has(r)){const t=e.get(r);t.out+=a,t.to.push({key:n,flow:a,index:o})}else e.set(r,{key:r,in:0,out:a,from:[],to:[{key:n,flow:a,index:o}]});if(e.has(n)){const t=e.get(n);t.in+=a,t.from.push({key:r,flow:a,index:o})}else e.set(n,{key:n,in:a,out:0,from:[{key:r,flow:a,index:o}],to:[]})}const o=(t,e)=>e.flow-t.flow;return[...e.values()].forEach((t=>{t.from=t.from.sort(o),t.from.forEach((t=>{t.node=e.get(t.key)})),t.to=t.to.sort(o),t.to.forEach((t=>{t.node=e.get(t.key)}))})),e}(l),{column:y,priority:p,size:m}=this.getDataset();if(p)for(const t of d.values())t.key in p&&(t.priority=p[t.key]);if(y)for(const t of d.values())t.key in y&&(t.column=!0,t.x=y[t.key]);const{maxX:g,maxY:M}=u(d,l,!!p,o(m));this._maxX=g,this._maxY=M;for(let t=0,e=l.length;t<e;++t){const e=l[t],o=d.get(e.from),r=d.get(e.to),n=o.y+x(o.to,e.to,t),a=r.y+x(r.from,e.from,t);f.push({x:c.parse(o.x,t),y:h.parse(n,t),_custom:{from:o,to:r,x:c.parse(r.x,t),y:h.parse(a,t),height:h.parse(e.flow,t)}})}return f.slice(r,r+n)}getMinMax(t){return{min:0,max:t===this._cachedMeta.xScale?this._maxX:this._maxY}}update(t){const{data:e}=this._cachedMeta;this.updateElements(e,0,e.length,t)}updateElements(t,o,r,n){const{xScale:a,yScale:i}=this._cachedMeta,s=this.resolveDataElementOptions(o,n),l=this.getSharedOptions(n,t[o],s),c=this.getDataset(),h=e.valueOrDefault(c.borderWidth,1)/2+.5,f=e.valueOrDefault(c.nodeWidth,10);for(let e=o;e<o+r;e++){const o=this.getParsed(e),r=o._custom,s=i.getPixelForValue(o.y);this.updateElement(t[e],e,{x:a.getPixelForValue(o.x)+f+h,y:s,x2:a.getPixelForValue(r.x)-h,y2:i.getPixelForValue(r.y),from:r.from,to:r.to,progress:"reset"===n?0:1,height:Math.abs(i.getPixelForValue(o.y+r.height)-s),options:this.resolveDataElementOptions(e,n)},n)}this.updateSharedOptions(l,n)}_drawLabels(){const t=this._ctx,r=this._nodes||new Map,n=this.getDataset(),a=o(n.size),i=e.valueOrDefault(n.borderWidth,1),s=e.valueOrDefault(n.nodeWidth,10),l=n.labels,{xScale:c,yScale:h}=this._cachedMeta;t.save();const f=this.chart.chartArea;for(const e of r.values()){const o=c.getPixelForValue(e.x),r=h.getPixelForValue(e.y),d=Math[a](e.in||e.out,e.out||e.in),u=Math.abs(h.getPixelForValue(e.y+d)-r),x=l&&l[e.key]||e.key;let y=o;t.fillStyle=n.color||"black",t.textBaseline="middle",o<f.width/2?(t.textAlign="left",y+=s+i+4):(t.textAlign="right",y-=i+4),this._drawLabel(x,r,u,t,y)}t.restore()}_drawLabel(t,o,r,n,a){const i=e.toFont(this.options.font,this.chart.options.font),s=e.isNullOrUndef(t)?[]:function(t){const o=[],r=e.isArray(t)?t:e.isNullOrUndef(t)?[]:[t];for(;r.length;){const t=r.pop();"string"==typeof t?o.unshift.apply(o,t.split("\n")):Array.isArray(t)?r.push.apply(r,t):e.isNullOrUndef(r)||o.unshift(""+t)}return o}(t),l=s.length,c=o+r/2,h=i.lineHeight,f=e.valueOrDefault(this.options.padding,h/2);if(n.font=i.string,l>1){const t=c-h*l/2+f;for(let e=0;e<l;e++)n.fillText(s[e],a,t+e*h)}else n.fillText(t,a,c)}_drawNodes(){const t=this._ctx,r=this._nodes||new Map,n=this.getDataset(),a=o(n.size),{xScale:i,yScale:s}=this._cachedMeta,l=e.valueOrDefault(n.borderWidth,1),c=e.valueOrDefault(n.nodeWidth,10);t.save(),t.strokeStyle=n.borderColor||"black",t.lineWidth=l;for(const e of r.values()){t.fillStyle=e.color;const o=i.getPixelForValue(e.x),r=s.getPixelForValue(e.y),n=Math[a](e.in||e.out,e.out||e.in),h=Math.abs(s.getPixelForValue(e.y+n)-r);l&&t.strokeRect(o,r,c,h),t.fillRect(o,r,c,h)}t.restore()}draw(){const t=this._ctx,e=this.getMeta().data||[];for(let t=0,o=e.length;t<o;++t){const o=e[t];o.from.color=o.options.colorFrom,o.to.color=o.options.colorTo}this._drawNodes();for(let o=0,r=e.length;o<r;++o)e[o].draw(t);this._drawLabels()}}y.id="sankey",y.defaults={dataElementType:"flow",animations:{numbers:{type:"number",properties:["x","y","x2","y2","height"]},progress:{easing:"linear",duration:t=>"data"===t.type?200*(t.parsed._custom.x-t.parsed.x):void 0,delay:t=>"data"===t.type?500*t.parsed.x+20*t.dataIndex:void 0},colors:{type:"color",properties:["colorFrom","colorTo"]}},transitions:{hide:{animations:{colors:{type:"color",properties:["colorFrom","colorTo"],to:"transparent"}}},show:{animations:{colors:{type:"color",properties:["colorFrom","colorTo"],from:"transparent"}}}}},y.overrides={interaction:{mode:"nearest",intersect:!0},datasets:{clip:!1,parsing:!0},plugins:{tooltip:{callbacks:{title:()=>"",label(t){const e=t.dataset.data[t.dataIndex];return e.from+" -> "+e.to+": "+e.flow}}},legend:{display:!1}},scales:{x:{type:"linear",bounds:"data",display:!1,min:0,offset:!1},y:{type:"linear",bounds:"data",display:!1,min:0,reverse:!0,offset:!1}},layout:{padding:{top:3,left:3,right:13,bottom:3}}};const p=(t,e,o,r)=>t<o?{cp1:{x:t+(o-t)/3*2,y:e},cp2:{x:t+(o-t)/3,y:r}}:{cp1:{x:t-(t-o)/3,y:0},cp2:{x:o+(t-o)/3,y:0}},m=(t,e,o)=>({x:t.x+o*(e.x-t.x),y:t.y+o*(e.y-t.y)});class g extends t.Element{constructor(t){super(),this.options=void 0,this.x=void 0,this.y=void 0,this.x2=void 0,this.y2=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t){const{x:o,x2:r,y:n,y2:a,height:i,progress:s}=this,{cp1:l,cp2:c}=p(o,n,r,a);0!==s&&(t.save(),s<1&&(t.beginPath(),t.rect(o,Math.min(n,a),(r-o)*s+1,Math.abs(a-n)+i+1),t.clip()),function(t,{x:o,x2:r,options:n}){let a;"from"===n.colorMode?a=e.color(n.colorFrom).alpha(.5).rgbString():"to"===n.colorMode?a=e.color(n.colorTo).alpha(.5).rgbString():(a=t.createLinearGradient(o,0,r,0),a.addColorStop(0,e.color(n.colorFrom).alpha(.5).rgbString()),a.addColorStop(1,e.color(n.colorTo).alpha(.5).rgbString())),t.fillStyle=a,t.strokeStyle=a,t.lineWidth=.5}(t,this),t.beginPath(),t.moveTo(o,n),t.bezierCurveTo(l.x,l.y,c.x,c.y,r,a),t.lineTo(r,a+i),t.bezierCurveTo(c.x,c.y+i,l.x,l.y+i,o,n+i),t.lineTo(o,n),t.stroke(),t.closePath(),t.fill(),t.restore())}inRange(t,e,o){const{x:r,y:n,x2:a,y2:i,height:s}=this.getProps(["x","y","x2","y2","height"],o);if(t<r||t>a)return!1;const{cp1:l,cp2:c}=p(r,n,a,i),h=(t-r)/(a-r),f={x:a,y:i},d=m({x:r,y:n},l,h),u=m(l,c,h),x=m(c,f,h),y=m(d,u,h),g=m(u,x,h),M=m(y,g,h).y;return e>=M&&e<=M+s}inXRange(t,e){const{x:o,x2:r}=this.getProps(["x","x2"],e);return t>=o&&t<=r}inYRange(t,e){const{y:o,y2:r,height:n}=this.getProps(["y","y2","height"],e),a=Math.min(o,r),i=Math.max(o,r)+n;return t>=a&&t<=i}getCenterPoint(t){const{x:e,y:o,x2:r,y2:n,height:a}=this.getProps(["x","y","x2","y2","height"],t);return{x:(e+r)/2,y:(o+n+a)/2}}tooltipPosition(t){return this.getCenterPoint(t)}getRange(t){return"x"===t?this.width/2:this.height/2}}g.id="flow",g.defaults={colorFrom:"red",colorTo:"green",colorMode:"gradient"},t.Chart.register(y,g)}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chartjs-chart-sankey",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Chart.js module for creating sankey diagrams",
5
5
  "main": "dist/chartjs-chart-sankey.js",
6
6
  "module": "dist/chartjs-chart-sankey.esm.js",